1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include "precompiled_svx.hxx"
23 
24 #include "InsertPropertyPanel.hxx"
25 #include "InsertPropertyPanel.hrc"
26 #include "sfx2/sidebar/CommandInfoProvider.hxx"
27 
28 #include <sfx2/sidebar/Theme.hxx>
29 #include <sfx2/sidebar/Tools.hxx>
30 #include <sfx2/sidebar/ControlFactory.hxx>
31 
32 #include <svx/dialmgr.hxx>
33 #include <svtools/miscopt.hxx>
34 #include <svtools/generictoolboxcontroller.hxx>
35 #include <vcl/toolbox.hxx>
36 #include <sfx2/tbxctrl.hxx>
37 #include <framework/sfxhelperfunctions.hxx>
38 #include <framework/imageproducer.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <cppuhelper/compbase1.hxx>
41 #include <cppuhelper/basemutex.hxx>
42 
43 #include <com/sun/star/frame/XStatusListener.hpp>
44 
45 using namespace css;
46 using namespace cssu;
47 using ::rtl::OUString;
48 
49 namespace svx { namespace sidebar {
50 
51 
52 InsertPropertyPanel::InsertPropertyPanel (
53     Window* pParent,
54     const cssu::Reference<css::frame::XFrame>& rxFrame)
55     :	Control(pParent, SVX_RES(RID_SIDEBAR_INSERT_PANEL)),
56         mpStandardShapesBackground(sfx2::sidebar::ControlFactory::CreateToolBoxBackground(this)),
57         mpStandardShapesToolBox(sfx2::sidebar::ControlFactory::CreateToolBox(
58                 mpStandardShapesBackground.get(),
59                 SVX_RES(TB_INSERT_STANDARD))),
60         mpCustomShapesBackground(sfx2::sidebar::ControlFactory::CreateToolBoxBackground(this)),
61         mpCustomShapesToolBox(sfx2::sidebar::ControlFactory::CreateToolBox(
62                 mpCustomShapesBackground.get(),
63                 SVX_RES(TB_INSERT_CUSTOM))),
64         maControllers(),
65         mxFrame(rxFrame)
66 {
67     SetupToolBox(*mpStandardShapesToolBox);
68     SetupToolBox(*mpCustomShapesToolBox);
69     FreeResource();
70 
71     UpdateIcons();
72 
73     mpStandardShapesToolBox->Show();
74     mpCustomShapesToolBox->Show();
75 
76     // Listen to all tool box selection events.
77     Window* pTopWindow = pParent;
78     while (pTopWindow->GetParent() != NULL)
79         pTopWindow = pTopWindow->GetParent();
80     pTopWindow->AddChildEventListener(LINK(this, InsertPropertyPanel, WindowEventListener));
81 }
82 
83 
84 
85 
86 InsertPropertyPanel::~InsertPropertyPanel (void)
87 {
88     ControllerContainer aControllers;
89     aControllers.swap(maControllers);
90     for (ControllerContainer::iterator iController(aControllers.begin()), iEnd(aControllers.end());
91          iController!=iEnd;
92          ++iController)
93     {
94         Reference<lang::XComponent> xComponent (iController->second.mxController, UNO_QUERY);
95         if (xComponent.is())
96             xComponent->dispose();
97     }
98 
99     // Remove window child listener.
100     Window* pTopWindow = this;
101     while (pTopWindow->GetParent() != NULL)
102         pTopWindow = pTopWindow->GetParent();
103     pTopWindow->RemoveChildEventListener(LINK(this, InsertPropertyPanel, WindowEventListener));
104 
105     mpStandardShapesToolBox.reset();
106     mpCustomShapesToolBox.reset();
107     mpStandardShapesBackground.reset();
108     mpCustomShapesBackground.reset();
109 }
110 
111 
112 
113 
114 void InsertPropertyPanel::SetupToolBox (ToolBox& rToolBox)
115 {
116     const sal_uInt16 nItemCount (rToolBox.GetItemCount());
117     for (sal_uInt16 nItemIndex=0; nItemIndex<nItemCount; ++nItemIndex)
118         CreateController(rToolBox.GetItemId(nItemIndex));
119 
120     rToolBox.SetDropdownClickHdl(LINK(this, InsertPropertyPanel, DropDownClickHandler));
121     rToolBox.SetClickHdl(LINK(this, InsertPropertyPanel, ClickHandler));
122     rToolBox.SetDoubleClickHdl(LINK(this, InsertPropertyPanel, DoubleClickHandler));
123     rToolBox.SetSelectHdl(LINK(this, InsertPropertyPanel, SelectHandler));
124 	rToolBox.SetActivateHdl(LINK(this, InsertPropertyPanel, Activate));
125 	rToolBox.SetDeactivateHdl(LINK(this, InsertPropertyPanel, Deactivate));
126 
127     rToolBox.SetSizePixel(rToolBox.CalcWindowSizePixel());
128 }
129 
130 
131 
132 
133 IMPL_LINK(InsertPropertyPanel, DropDownClickHandler, ToolBox*, pToolBox)
134 {
135     if (pToolBox != NULL)
136     {
137         Reference<frame::XToolbarController> xController (GetControllerForItemId(pToolBox->GetCurItemId()));
138         if (xController.is())
139         {
140             Reference<awt::XWindow> xWindow = xController->createPopupWindow();
141             if (xWindow.is() )
142                 xWindow->setFocus();
143         }
144     }
145     return 1;
146 }
147 
148 
149 
150 
151 IMPL_LINK(InsertPropertyPanel, ClickHandler, ToolBox*, pToolBox)
152 {
153     if (pToolBox == NULL)
154         return 0;
155 
156     Reference<frame::XToolbarController> xController (GetControllerForItemId(pToolBox->GetCurItemId()));
157     if (xController.is())
158         xController->click();
159 
160     return 1;
161 }
162 
163 
164 
165 
166 IMPL_LINK(InsertPropertyPanel, DoubleClickHandler, ToolBox*, pToolBox)
167 {
168     if (pToolBox == NULL)
169         return 0;
170 
171     Reference<frame::XToolbarController> xController (GetControllerForItemId(pToolBox->GetCurItemId()));
172     if (xController.is())
173         xController->doubleClick();
174 
175     return 1;
176 }
177 
178 
179 
180 
181 IMPL_LINK(InsertPropertyPanel, SelectHandler, ToolBox*, pToolBox)
182 {
183     if (pToolBox == NULL)
184         return 0;
185 
186     Reference<frame::XToolbarController> xController (GetControllerForItemId(pToolBox->GetCurItemId()));
187     if (xController.is())
188         xController->execute((sal_Int16)pToolBox->GetModifier());
189 
190     return 1;
191 }
192 
193 
194 
195 
196 IMPL_LINK(InsertPropertyPanel, WindowEventListener, VclSimpleEvent*, pEvent)
197 {
198     // We will be getting a lot of window events (well, basically all
199     // of them), so reject early everything that is not connected to
200     // toolbox selection.
201     if (pEvent == NULL)
202         return 1;
203     if ( ! pEvent->ISA(VclWindowEvent))
204         return 1;
205     if (pEvent->GetId() != VCLEVENT_TOOLBOX_SELECT)
206         return 1;
207 
208     ToolBox* pToolBox = dynamic_cast<ToolBox*>(dynamic_cast<VclWindowEvent*>(pEvent)->GetWindow());
209     if (pToolBox == NULL)
210         return 1;
211 
212     // Extract name of (sub)toolbar from help id.
213     OUString sToolbarName (rtl::OStringToOUString(pToolBox->GetHelpId(), RTL_TEXTENCODING_UTF8));
214     if (sToolbarName.getLength() == 0)
215         return 1;
216     const util::URL aURL (sfx2::sidebar::Tools::GetURL(sToolbarName));
217     if (aURL.Path.getLength() == 0)
218         return 1;
219 
220     // Get item id.
221     sal_uInt16 nId = pToolBox->GetCurItemId();
222     if (nId == 0)
223         return 1;
224 
225     // Get toolbar controller.
226     const sal_uInt16 nItemId (GetItemIdForSubToolbarName(aURL.Path));
227     Reference<frame::XSubToolbarController> xController (GetControllerForItemId(nItemId), UNO_QUERY);
228     if ( ! xController.is())
229         return 1;
230 
231     const OUString sCommand (pToolBox->GetItemCommand(nId));
232     ControllerContainer::iterator iController (maControllers.find(nItemId));
233     if (iController != maControllers.end())
234         iController->second.msCurrentCommand = sCommand;
235     xController->functionSelected(sCommand);
236 
237     const sal_Bool bBigImages (SvtMiscOptions().AreCurrentSymbolsLarge());
238     const bool bIsHighContrastActive (sfx2::sidebar::Theme::IsHighContrastMode());
239     Image aImage (framework::GetImageFromURL(mxFrame, sCommand, bBigImages, bIsHighContrastActive));
240     pToolBox->SetItemImage(iController->first, aImage);
241 
242     return 1;
243 }
244 
245 
246 
247 
248 IMPL_LINK(InsertPropertyPanel, Activate, ToolBox*, EMPTYARG)
249 {
250     return 1;
251 }
252 
253 
254 
255 
256 IMPL_LINK(InsertPropertyPanel, Deactivate, ToolBox*, EMPTYARG)
257 {
258     return 1;
259 }
260 
261 
262 
263 
264 void InsertPropertyPanel::CreateController (
265     const sal_uInt16 nItemId)
266 {
267     ToolBox* pToolBox = GetToolBoxForItemId(nItemId);
268     if (pToolBox != NULL)
269     {
270         ItemDescriptor aDescriptor;
271 
272         const OUString sCommandName (pToolBox->GetItemCommand(nItemId));
273 
274         // Create a controller for the new item.
275         aDescriptor.mxController.set(
276             static_cast<XWeak*>(::framework::CreateToolBoxController(
277                     mxFrame,
278                     pToolBox,
279                     nItemId,
280                     sCommandName)),
281             UNO_QUERY);
282         if ( ! aDescriptor.mxController.is())
283             aDescriptor.mxController.set(
284                 static_cast<XWeak*>(new svt::GenericToolboxController(
285                         ::comphelper::getProcessServiceFactory(),
286                         mxFrame,
287                         pToolBox,
288                         nItemId,
289                         sCommandName)),
290                 UNO_QUERY);
291         if ( ! aDescriptor.mxController.is())
292             return;
293 
294         // Get dispatch object for the command.
295         aDescriptor.maURL = sfx2::sidebar::Tools::GetURL(sCommandName);
296         aDescriptor.msCurrentCommand = sCommandName;
297         aDescriptor.mxDispatch = sfx2::sidebar::Tools::GetDispatch(mxFrame, aDescriptor.maURL);
298         if ( ! aDescriptor.mxDispatch.is())
299             return;
300 
301         // Initialize the controller with eg a service factory.
302         Reference<lang::XInitialization> xInitialization (aDescriptor.mxController, UNO_QUERY);
303         if (xInitialization.is())
304         {
305             beans::PropertyValue aPropValue;
306             std::vector<Any> aPropertyVector;
307 
308             aPropValue.Name = A2S("Frame");
309             aPropValue.Value <<= mxFrame;
310             aPropertyVector.push_back(makeAny(aPropValue));
311 
312             aPropValue.Name = A2S("ServiceManager");
313             aPropValue.Value <<= ::comphelper::getProcessServiceFactory();
314             aPropertyVector.push_back(makeAny(aPropValue));
315 
316             aPropValue.Name = A2S("CommandURL");
317             aPropValue.Value <<= sCommandName;
318             aPropertyVector.push_back(makeAny(aPropValue));
319 
320             Sequence<Any> aArgs (comphelper::containerToSequence(aPropertyVector));
321             xInitialization->initialize(aArgs);
322         }
323 
324         Reference<util::XUpdatable> xUpdatable (aDescriptor.mxController, UNO_QUERY);
325         if (xUpdatable.is())
326             xUpdatable->update();
327 
328         // Add label.
329         const OUString sLabel (sfx2::sidebar::CommandInfoProvider::Instance().GetLabelForCommand(
330                 sCommandName,
331                 mxFrame));
332         pToolBox->SetQuickHelpText(nItemId, sLabel);
333 
334         // Add item to toolbox.
335         pToolBox->EnableItem(nItemId);
336         maControllers.insert(::std::make_pair(nItemId, aDescriptor));
337     }
338 }
339 
340 
341 
342 
343 ToolBox* InsertPropertyPanel::GetToolBoxForItemId (const sal_uInt16 nItemId) const
344 {
345     switch(nItemId)
346     {
347         case TBI_STANDARD_LINE:
348         case TBI_STANDARD_ARROW:
349         case TBI_STANDARD_RECTANGLE:
350         case TBI_STANDARD_ELLIPSE:
351         case TBI_STANDARD_TEXT:
352         case TBI_STANDARD_LINES:
353         case TBI_STANDARD_CONNECTORS:
354         case TBI_STANDARD_ARROWS:
355             return mpStandardShapesToolBox.get();
356 
357         case TBI_CUSTOM_BASICS:
358         case TBI_CUSTOM_SYMBOLS:
359         case TBI_CUSTOM_ARROWS:
360         case TBI_CUSTOM_FLOWCHARTS:
361         case TBI_CUSTOM_CALLOUTS:
362         case TBI_CUSTOM_STARS:
363             return mpCustomShapesToolBox.get();
364 
365         default:
366             return NULL;
367     }
368 }
369 
370 
371 
372 
373 Reference<frame::XToolbarController> InsertPropertyPanel::GetControllerForItemId (const sal_uInt16 nItemId) const
374 {
375     ControllerContainer::const_iterator iController (maControllers.find(nItemId));
376     if (iController != maControllers.end())
377         return iController->second.mxController;
378     else
379         return NULL;
380 }
381 
382 
383 
384 
385 sal_uInt16 InsertPropertyPanel::GetItemIdForSubToolbarName (const OUString& rsSubToolbarName) const
386 {
387     for (ControllerContainer::const_iterator iController(maControllers.begin()), iEnd(maControllers.end());
388          iController!=iEnd;
389          ++iController)
390     {
391         Reference<frame::XSubToolbarController> xSubToolbarController (iController->second.mxController, UNO_QUERY);
392         if (xSubToolbarController.is())
393             if (xSubToolbarController->getSubToolbarName().equals(rsSubToolbarName))
394                 return iController->first;
395     }
396     return NULL;
397 }
398 
399 
400 
401 
402 void InsertPropertyPanel::UpdateIcons (void)
403 {
404     const sal_Bool bBigImages (SvtMiscOptions().AreCurrentSymbolsLarge());
405     const bool bIsHighContrastActive (sfx2::sidebar::Theme::IsHighContrastMode());
406 
407     for (ControllerContainer::iterator iController(maControllers.begin()), iEnd(maControllers.end());
408          iController!=iEnd;
409          ++iController)
410     {
411         const ::rtl::OUString sCommandURL (iController->second.msCurrentCommand);
412         Image aImage (framework::GetImageFromURL(mxFrame, sCommandURL, bBigImages, bIsHighContrastActive));
413         ToolBox* pToolBox = GetToolBoxForItemId(iController->first);
414         if (pToolBox != NULL)
415             pToolBox->SetItemImage(iController->first, aImage);
416     }
417 }
418 
419 
420 
421 
422 } } // end of namespace svx::sidebar
423