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