1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21 #ifdef __sun
22 #include <ctime>
23 #endif
24
25 #include <string>
26 #include <com/sun/star/uno/Reference.h>
27 #include <com/sun/star/frame/XFrame.hpp>
28 #include <com/sun/star/awt/XPopupMenu.hpp>
29 #include <com/sun/star/awt/XWindow.hpp>
30 #include <com/sun/star/awt/XWindowPeer.hpp>
31 #include <com/sun/star/util/URL.hpp>
32 #include <com/sun/star/util/URLTransformer.hpp>
33 #include <com/sun/star/util/XURLTransformer.hpp>
34 #include <com/sun/star/frame/XController.hpp>
35 #include <com/sun/star/lang/XUnoTunnel.hpp>
36 #include <com/sun/star/document/MacroExecMode.hpp>
37 #include <com/sun/star/document/UpdateDocMode.hpp>
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/frame/status/ItemStatus.hpp>
41 #include <com/sun/star/ui/XUIElementFactory.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/ui/XUIFunctionListener.hpp>
44 #include <com/sun/star/ui/theUIElementFactoryManager.hpp>
45 #include <com/sun/star/frame/status/Visibility.hpp>
46 #include <svl/eitem.hxx>
47 #include <svl/stritem.hxx>
48 #include <svl/intitem.hxx>
49 #include <svl/imageitm.hxx>
50 #include <svl/visitem.hxx>
51 #include <svl/urlbmk.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/toolbox.hxx>
54 #include <unotools/moduleoptions.hxx>
55
56 #include <svtools/imagemgr.hxx>
57 #include <svtools/framestatuslistener.hxx>
58 #include <comphelper/processfactory.hxx>
59 #include <framework/addonmenu.hxx>
60 #include <framework/addonsoptions.hxx>
61 #include <framework/menuconfiguration.hxx>
62 #include <framework/sfxhelperfunctions.hxx>
63 #include <vcl/taskpanelist.hxx>
64 #include <vcl/event.hxx>
65 #include <toolkit/helper/vclunohelper.hxx>
66 #include <tools/globname.hxx>
67 #include <svtools/menuoptions.hxx>
68 #include <svtools/miscopt.hxx>
69
70 #include <sfx2/tbxctrl.hxx>
71 #include <sfx2/dispatch.hxx>
72 #include <sfx2/msg.hxx>
73 #include <sfx2/msgpool.hxx>
74 #include <statcach.hxx>
75 #include <sfx2/viewfrm.hxx>
76 #include <sfxtypes.hxx>
77 #include <sfx2/module.hxx>
78 #include <sfx2/docfile.hxx>
79 #include <sfx2/docfac.hxx>
80 #include <sfx2/frmhtmlw.hxx>
81 #include <sfx2/app.hxx>
82 #include <sfx2/unoctitm.hxx>
83 #include <workwin.hxx>
84 #include <ctrlfactoryimpl.hxx>
85
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::beans;
88 using namespace ::com::sun::star::frame;
89 using namespace ::com::sun::star::frame::status;
90 using namespace ::com::sun::star::lang;
91 using namespace ::com::sun::star::uno;
92 using namespace ::com::sun::star::util;
93 using namespace ::com::sun::star::container;
94 using namespace ::com::sun::star::ui;
95
96
97 SFX_IMPL_TOOLBOX_CONTROL_ARG(SfxToolBoxControl, SfxStringItem, true);
98
GetTopMostParentSystemWindow(vcl::Window * pWindow)99 static vcl::Window* GetTopMostParentSystemWindow( vcl::Window* pWindow )
100 {
101 OSL_ASSERT( pWindow );
102 if ( pWindow )
103 {
104 // ->manually search topmost system window
105 // required because their might be another system window between this and the top window
106 pWindow = pWindow->GetParent();
107 SystemWindow* pTopMostSysWin = nullptr;
108 while ( pWindow )
109 {
110 if ( pWindow->IsSystemWindow() )
111 pTopMostSysWin = static_cast<SystemWindow*>(pWindow);
112 pWindow = pWindow->GetParent();
113 }
114 pWindow = pTopMostSysWin;
115 OSL_ASSERT( pWindow );
116 return pWindow;
117 }
118
119 return nullptr;
120 }
121
SfxToolBoxControllerFactory(const Reference<XFrame> & rFrame,ToolBox * pToolbox,unsigned short nID,const OUString & aCommandURL)122 svt::ToolboxController* SfxToolBoxControllerFactory( const Reference< XFrame >& rFrame, ToolBox* pToolbox, unsigned short nID, const OUString& aCommandURL )
123 {
124 SolarMutexGuard aGuard;
125
126 URL aTargetURL;
127 aTargetURL.Complete = aCommandURL;
128 Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
129 xTrans->parseStrict( aTargetURL );
130 if ( !aTargetURL.Arguments.isEmpty() )
131 return nullptr;
132
133 SfxObjectShell* pObjShell = nullptr;
134 Reference < XController > xController;
135 Reference < XModel > xModel;
136 if ( rFrame.is() )
137 {
138 xController = rFrame->getController();
139 if ( xController.is() )
140 xModel = xController->getModel();
141 }
142
143 if ( xModel.is() )
144 {
145 // Get tunnel from model to retrieve the SfxObjectShell pointer from it
146 css::uno::Reference < css::lang::XUnoTunnel > xObj( xModel, UNO_QUERY );
147 if ( xObj.is() )
148 {
149 css::uno::Sequence < sal_Int8 > aSeq = SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence();
150 sal_Int64 nHandle = xObj->getSomething( aSeq );
151 if ( nHandle )
152 pObjShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
153 }
154 }
155
156 SfxModule* pModule = pObjShell ? pObjShell->GetModule() : nullptr;
157 SfxSlotPool* pSlotPool = nullptr;
158
159 if ( pModule )
160 pSlotPool = pModule->GetSlotPool();
161 else
162 pSlotPool = &(SfxSlotPool::GetSlotPool());
163
164 const SfxSlot* pSlot = pSlotPool->GetUnoSlot( aTargetURL.Path );
165 if ( pSlot )
166 {
167 sal_uInt16 nSlotId = pSlot->GetSlotId();
168 if ( nSlotId > 0 )
169 return SfxToolBoxControl::CreateControl( nSlotId, nID, pToolbox, pModule );
170 }
171
172 return nullptr;
173 }
174
175 struct SfxToolBoxControl_Impl
176 {
177 VclPtr<ToolBox> pBox;
178 bool bShowString;
179 sal_uInt16 nTbxId;
180 sal_uInt16 nSlotId;
181 VclPtr<SfxPopupWindow> mpFloatingWindow;
182 VclPtr<SfxPopupWindow> mpPopupWindow;
183 DECL_LINK( WindowEventListener, VclWindowEvent&, void );
184 };
185
IMPL_LINK(SfxToolBoxControl_Impl,WindowEventListener,VclWindowEvent &,rEvent,void)186 IMPL_LINK( SfxToolBoxControl_Impl, WindowEventListener, VclWindowEvent&, rEvent, void )
187 {
188 if ( ( rEvent.GetId() == VclEventId::WindowMove ) ||
189 ( rEvent.GetId() == VclEventId::WindowActivate ))
190 {
191 vcl::Window* pWindow( rEvent.GetWindow() );
192 if (( pWindow == mpFloatingWindow ) &&
193 ( mpPopupWindow != nullptr ))
194 {
195 mpPopupWindow.disposeAndClear();
196 }
197 }
198 }
199
200
SfxToolBoxControl(sal_uInt16 nSlotID,sal_uInt16 nID,ToolBox & rBox,bool bShowStringItems)201 SfxToolBoxControl::SfxToolBoxControl(
202 sal_uInt16 nSlotID,
203 sal_uInt16 nID,
204 ToolBox& rBox,
205 bool bShowStringItems )
206 : pImpl( new SfxToolBoxControl_Impl )
207 {
208 pImpl->pBox = &rBox;
209 pImpl->bShowString = bShowStringItems;
210 pImpl->nTbxId = nID;
211 pImpl->nSlotId = nSlotID;
212 pImpl->mpFloatingWindow = nullptr;
213 pImpl->mpPopupWindow = nullptr;
214 }
215
216
~SfxToolBoxControl()217 SfxToolBoxControl::~SfxToolBoxControl()
218 {
219 }
220
221
GetToolBox() const222 ToolBox& SfxToolBoxControl::GetToolBox() const
223 {
224 return *pImpl->pBox;
225 }
GetId() const226 unsigned short SfxToolBoxControl::GetId() const
227 {
228 return pImpl->nTbxId;
229 }
GetSlotId() const230 unsigned short SfxToolBoxControl::GetSlotId() const
231 {
232 return pImpl->nSlotId;
233 }
234
235
dispose()236 void SAL_CALL SfxToolBoxControl::dispose()
237 {
238 if ( m_bDisposed )
239 return;
240
241 svt::ToolboxController::dispose();
242
243 // Remove and destroy our item window at our toolbox
244 SolarMutexGuard aGuard;
245 VclPtr< vcl::Window > pWindow = pImpl->pBox->GetItemWindow( pImpl->nTbxId );
246 pImpl->pBox->SetItemWindow( pImpl->nTbxId, nullptr );
247 pWindow.disposeAndClear();
248
249 // Delete my popup windows
250 pImpl->mpFloatingWindow.disposeAndClear();
251 pImpl->mpPopupWindow.disposeAndClear();
252 }
253
254
RegisterToolBoxControl(SfxModule * pMod,const SfxTbxCtrlFactory & rFact)255 void SfxToolBoxControl::RegisterToolBoxControl( SfxModule* pMod, const SfxTbxCtrlFactory& rFact)
256 {
257 SfxGetpApp()->RegisterToolBoxControl_Impl( pMod, rFact );
258 }
259
CreateControl(sal_uInt16 nSlotId,sal_uInt16 nTbxId,ToolBox * pBox,SfxModule const * pMod)260 SfxToolBoxControl* SfxToolBoxControl::CreateControl( sal_uInt16 nSlotId, sal_uInt16 nTbxId, ToolBox *pBox, SfxModule const * pMod )
261 {
262 SolarMutexGuard aGuard;
263
264 SfxApplication *pApp = SfxGetpApp();
265
266 SfxSlotPool *pSlotPool;
267 if ( pMod )
268 pSlotPool = pMod->GetSlotPool();
269 else
270 pSlotPool = &SfxSlotPool::GetSlotPool();
271 const std::type_info* aSlotType = pSlotPool->GetSlotType( nSlotId );
272 if ( aSlotType )
273 {
274 SfxToolBoxControl *pCtrl;
275 if ( pMod )
276 {
277 SfxTbxCtrlFactArr_Impl *pFactories = pMod->GetTbxCtrlFactories_Impl();
278 if ( pFactories )
279 {
280 SfxTbxCtrlFactArr_Impl &rFactories = *pFactories;
281 sal_uInt16 nFactory;
282 const sal_uInt16 nCount = rFactories.size();
283
284 // search for a factory with the given slot id
285 for( nFactory = 0; nFactory < nCount; ++nFactory )
286 if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == nSlotId) )
287 break;
288
289 if( nFactory == nCount )
290 {
291 // if no factory exists for the given slot id, see if we
292 // have a generic factory with the correct slot type and slot id == 0
293 for ( nFactory = 0; nFactory < nCount; ++nFactory )
294 if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == 0) )
295 break;
296 }
297
298 if( nFactory < nCount )
299 {
300 pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox );
301 return pCtrl;
302 }
303 }
304 }
305
306 SfxTbxCtrlFactArr_Impl &rFactories = pApp->GetTbxCtrlFactories_Impl();
307 sal_uInt16 nFactory;
308 const sal_uInt16 nCount = rFactories.size();
309
310 for( nFactory = 0; nFactory < nCount; ++nFactory )
311 if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == nSlotId) )
312 break;
313
314 if( nFactory == nCount )
315 {
316 // if no factory exists for the given slot id, see if we
317 // have a generic factory with the correct slot type and slot id == 0
318 for( nFactory = 0; nFactory < nCount; ++nFactory )
319 if( (rFactories[nFactory].nTypeId == *aSlotType) && (rFactories[nFactory].nSlotId == 0) )
320 break;
321 }
322
323 if( nFactory < nCount )
324 {
325 pCtrl = rFactories[nFactory].pCtor( nSlotId, nTbxId, *pBox );
326 return pCtrl;
327 }
328 }
329
330 return nullptr;
331 }
332
GetItemState(const SfxPoolItem * pState)333 SfxItemState SfxToolBoxControl::GetItemState(
334 const SfxPoolItem* pState )
335 /* [Description]
336
337 Static method for determining the status of the SfxPoolItem-pointer,
338 used in the method <SfxControllerItem::StateChanged(const SfxPoolItem*)>.
339
340 [Return value]
341
342 SfxItemState SfxItemState::UNKNOWN
343 Enabled, however no further status information is available.
344 Typical for <Slot>s, which are temporarily disabled a
345 anyway but other than that do not change their appearance.
346
347 SfxItemState::DISABLED
348 Disabled, no further status information is available.
349 All other displayed values should be reset to the default
350 if possible.
351
352 SfxItemState::DONTCARE
353 Enabled but there were only ambiguous values available
354 (i.e. none that could be queried).
355
356 SfxItemState::DEFAULT
357 Enabled and with available values which can be queried
358 through'pState'. The type is thus by the Slot clearly
359 defined in the entire Program.
360 */
361
362 {
363 return !pState
364 ? SfxItemState::DISABLED
365 : IsInvalidItem(pState)
366 ? SfxItemState::DONTCARE
367 : pState->IsVoidItem() && !pState->Which()
368 ? SfxItemState::UNKNOWN
369 : SfxItemState::DEFAULT;
370 }
371
Dispatch(const Reference<XDispatchProvider> & rProvider,const OUString & rCommand,Sequence<::PropertyValue> const & aArgs)372 void SfxToolBoxControl::Dispatch(
373 const Reference< XDispatchProvider >& rProvider,
374 const OUString& rCommand,
375 Sequence< ::PropertyValue > const & aArgs )
376 {
377 if ( rProvider.is() )
378 {
379 css::util::URL aTargetURL;
380 aTargetURL.Complete = rCommand;
381 Reference < XURLTransformer > xTrans( URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
382 xTrans->parseStrict( aTargetURL );
383
384 Reference < XDispatch > xDispatch = rProvider->queryDispatch( aTargetURL, OUString(), 0 );
385 if ( xDispatch.is() )
386 xDispatch->dispatch( aTargetURL, aArgs );
387 }
388 }
389
Dispatch(const OUString & aCommand,css::uno::Sequence<css::beans::PropertyValue> const & aArgs)390 void SfxToolBoxControl::Dispatch( const OUString& aCommand, css::uno::Sequence< css::beans::PropertyValue > const & aArgs )
391 {
392 Reference < XController > xController;
393
394 SolarMutexGuard aGuard;
395 if ( getFrameInterface().is() )
396 xController = getFrameInterface()->getController();
397
398 Reference < XDispatchProvider > xProvider( xController, UNO_QUERY );
399 if ( xProvider.is() )
400 {
401 css::util::URL aTargetURL;
402 aTargetURL.Complete = aCommand;
403 getURLTransformer()->parseStrict( aTargetURL );
404
405 Reference < XDispatch > xDispatch = xProvider->queryDispatch( aTargetURL, OUString(), 0 );
406 if ( xDispatch.is() )
407 xDispatch->dispatch( aTargetURL, aArgs );
408 }
409 }
410
411 // XStatusListener
statusChanged(const FeatureStateEvent & rEvent)412 void SAL_CALL SfxToolBoxControl::statusChanged( const FeatureStateEvent& rEvent )
413 {
414 SfxViewFrame* pViewFrame = nullptr;
415 Reference < XController > xController;
416
417 SolarMutexGuard aGuard;
418 if ( getFrameInterface().is() )
419 xController = getFrameInterface()->getController();
420
421 Reference < XDispatchProvider > xProvider( xController, UNO_QUERY );
422 if ( xProvider.is() )
423 {
424 Reference < XDispatch > xDisp = xProvider->queryDispatch( rEvent.FeatureURL, OUString(), 0 );
425 if ( xDisp.is() )
426 {
427 Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY );
428 SfxOfficeDispatch* pDisp = nullptr;
429 if ( xTunnel.is() )
430 {
431 sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
432 pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
433 }
434
435 if ( pDisp )
436 pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
437 }
438 }
439
440 sal_uInt16 nSlotId = 0;
441 SfxSlotPool& rPool = SfxSlotPool::GetSlotPool( pViewFrame );
442 const SfxSlot* pSlot = rPool.GetUnoSlot( rEvent.FeatureURL.Path );
443 if ( pSlot )
444 nSlotId = pSlot->GetSlotId();
445 else if ( m_aCommandURL == rEvent.FeatureURL.Path )
446 nSlotId = GetSlotId();
447
448 if ( nSlotId <= 0 )
449 return;
450
451 if ( rEvent.Requery )
452 svt::ToolboxController::statusChanged( rEvent );
453 else
454 {
455 SfxItemState eState = SfxItemState::DISABLED;
456 std::unique_ptr<SfxPoolItem> pItem;
457 if ( rEvent.IsEnabled )
458 {
459 eState = SfxItemState::DEFAULT;
460 css::uno::Type aType = rEvent.State.getValueType();
461
462 if ( aType == cppu::UnoType<void>::get() )
463 {
464 pItem.reset(new SfxVoidItem( nSlotId ));
465 eState = SfxItemState::UNKNOWN;
466 }
467 else if ( aType == cppu::UnoType<bool>::get() )
468 {
469 bool bTemp = false;
470 rEvent.State >>= bTemp ;
471 pItem.reset(new SfxBoolItem( nSlotId, bTemp ));
472 }
473 else if ( aType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get())
474 {
475 sal_uInt16 nTemp = 0;
476 rEvent.State >>= nTemp ;
477 pItem.reset(new SfxUInt16Item( nSlotId, nTemp ));
478 }
479 else if ( aType == cppu::UnoType<sal_uInt32>::get() )
480 {
481 sal_uInt32 nTemp = 0;
482 rEvent.State >>= nTemp ;
483 pItem.reset(new SfxUInt32Item( nSlotId, nTemp ));
484 }
485 else if ( aType == cppu::UnoType<OUString>::get() )
486 {
487 OUString sTemp ;
488 rEvent.State >>= sTemp ;
489 pItem.reset(new SfxStringItem( nSlotId, sTemp ));
490 }
491 else if ( aType == cppu::UnoType< css::frame::status::ItemStatus>::get() )
492 {
493 ItemStatus aItemStatus;
494 rEvent.State >>= aItemStatus;
495 SfxItemState tmpState = static_cast<SfxItemState>(aItemStatus.State);
496 // make sure no-one tries to send us a combination of states
497 if (tmpState != SfxItemState::UNKNOWN && tmpState != SfxItemState::DISABLED &&
498 tmpState != SfxItemState::READONLY && tmpState != SfxItemState::DONTCARE &&
499 tmpState != SfxItemState::DEFAULT && tmpState != SfxItemState::SET)
500 throw css::uno::RuntimeException("unknown status");
501 eState = tmpState;
502 pItem.reset(new SfxVoidItem( nSlotId ));
503 }
504 else if ( aType == cppu::UnoType< css::frame::status::Visibility>::get() )
505 {
506 Visibility aVisibilityStatus;
507 rEvent.State >>= aVisibilityStatus;
508 pItem.reset(new SfxVisibilityItem( nSlotId, aVisibilityStatus.bVisible ));
509 }
510 else
511 {
512 if ( pSlot )
513 pItem = pSlot->GetType()->CreateItem();
514 if ( pItem )
515 {
516 pItem->SetWhich( nSlotId );
517 pItem->PutValue( rEvent.State, 0 );
518 }
519 else
520 pItem.reset(new SfxVoidItem( nSlotId ));
521 }
522 }
523
524 StateChanged( nSlotId, eState, pItem.get() );
525 }
526 }
527
528 // XToolbarController
execute(sal_Int16 KeyModifier)529 void SAL_CALL SfxToolBoxControl::execute( sal_Int16 KeyModifier )
530 {
531 SolarMutexGuard aGuard;
532 Select( static_cast<sal_uInt16>(KeyModifier) );
533 }
534
click()535 void SAL_CALL SfxToolBoxControl::click()
536 {
537 SolarMutexGuard aGuard;
538 Click();
539 }
540
doubleClick()541 void SAL_CALL SfxToolBoxControl::doubleClick()
542 {
543 SolarMutexGuard aGuard;
544 DoubleClick();
545 }
546
createPopupWindow()547 Reference< css::awt::XWindow > SAL_CALL SfxToolBoxControl::createPopupWindow()
548 {
549 SolarMutexGuard aGuard;
550 VclPtr<vcl::Window> pWindow = CreatePopupWindow();
551 if ( pWindow )
552 return VCLUnoHelper::GetInterface( pWindow );
553 else
554 return Reference< css::awt::XWindow >();
555 }
556
createItemWindow(const Reference<css::awt::XWindow> & rParent)557 Reference< css::awt::XWindow > SAL_CALL SfxToolBoxControl::createItemWindow( const Reference< css::awt::XWindow >& rParent )
558 {
559 SolarMutexGuard aGuard;
560 return VCLUnoHelper::GetInterface( CreateItemWindow( VCLUnoHelper::GetWindow( rParent )));
561 }
562
SetPopupWindow(SfxPopupWindow * pWindow)563 void SfxToolBoxControl::SetPopupWindow( SfxPopupWindow* pWindow )
564 {
565 pImpl->mpPopupWindow = pWindow;
566 pImpl->mpPopupWindow->SetPopupModeEndHdl( LINK( this, SfxToolBoxControl, PopupModeEndHdl ));
567 pImpl->mpPopupWindow->SetDeleteLink_Impl( LINK( this, SfxToolBoxControl, ClosePopupWindow ));
568 }
569
570
IMPL_LINK_NOARG(SfxToolBoxControl,PopupModeEndHdl,FloatingWindow *,void)571 IMPL_LINK_NOARG(SfxToolBoxControl, PopupModeEndHdl, FloatingWindow*, void)
572 {
573 if ( pImpl->mpPopupWindow->IsVisible() )
574 {
575 // Replace floating window with popup window and destroy
576 // floating window instance.
577 pImpl->mpFloatingWindow.disposeAndClear();
578 pImpl->mpFloatingWindow = pImpl->mpPopupWindow;
579 pImpl->mpPopupWindow.clear();
580 // We also need to know when the user tries to use the
581 // floating window.
582 pImpl->mpFloatingWindow->AddEventListener( LINK( pImpl.get(), SfxToolBoxControl_Impl, WindowEventListener ));
583 }
584 else
585 {
586 // Popup window has been closed by the user. No replacement, instance
587 // will destroy itself.
588 pImpl->mpPopupWindow.clear();
589 }
590 }
591
592
IMPL_LINK(SfxToolBoxControl,ClosePopupWindow,SfxPopupWindow *,pWindow,void)593 IMPL_LINK( SfxToolBoxControl, ClosePopupWindow, SfxPopupWindow *, pWindow, void )
594 {
595 if ( pWindow == pImpl->mpFloatingWindow )
596 pImpl->mpFloatingWindow = nullptr;
597 else
598 pImpl->mpPopupWindow = nullptr;
599 }
600
601
StateChanged(sal_uInt16 nId,SfxItemState eState,const SfxPoolItem * pState)602 void SfxToolBoxControl::StateChanged
603 (
604 sal_uInt16 nId,
605 SfxItemState eState,
606 const SfxPoolItem* pState
607 )
608 {
609 DBG_ASSERT( pImpl->pBox != nullptr, "setting state to dangling ToolBox" );
610
611 // enabled/disabled-Flag correcting the lump sum
612 pImpl->pBox->EnableItem( GetId(), eState != SfxItemState::DISABLED );
613
614 ToolBoxItemBits nItemBits = pImpl->pBox->GetItemBits( GetId() );
615 nItemBits &= ~ToolBoxItemBits::CHECKABLE;
616 ::TriState eTri = TRISTATE_FALSE;
617 switch ( eState )
618 {
619 case SfxItemState::DEFAULT:
620 if ( pState )
621 {
622 if ( auto pBoolItem = dynamic_cast< const SfxBoolItem* >(pState) )
623 {
624 // BoolItem for checking
625 if ( pBoolItem->GetValue() )
626 eTri = TRISTATE_TRUE;
627 nItemBits |= ToolBoxItemBits::CHECKABLE;
628 }
629 else if ( dynamic_cast< const SfxEnumItemInterface *>( pState ) != nullptr &&
630 static_cast<const SfxEnumItemInterface *>(pState)->HasBoolValue())
631 {
632 // EnumItem is handled as Bool
633 if ( static_cast<const SfxEnumItemInterface *>(pState)->GetBoolValue() )
634 eTri = TRISTATE_TRUE;
635 nItemBits |= ToolBoxItemBits::CHECKABLE;
636 }
637 else if ( pImpl->bShowString && dynamic_cast< const SfxStringItem *>( pState ) != nullptr )
638 pImpl->pBox->SetItemText(nId, static_cast<const SfxStringItem*>(pState)->GetValue() );
639 }
640 break;
641
642 case SfxItemState::DONTCARE:
643 {
644 eTri = TRISTATE_INDET;
645 nItemBits |= ToolBoxItemBits::CHECKABLE;
646 }
647 break;
648
649 default: break; // do nothing
650 }
651
652 pImpl->pBox->SetItemState( GetId(), eTri );
653 pImpl->pBox->SetItemBits( GetId(), nItemBits );
654 }
655
656
Select(sal_uInt16 nSelectModifier)657 void SfxToolBoxControl::Select( sal_uInt16 nSelectModifier )
658 {
659 svt::ToolboxController::execute( nSelectModifier );
660 }
661
662
DoubleClick()663 void SfxToolBoxControl::DoubleClick()
664 {
665 }
666
667
Click()668 void SfxToolBoxControl::Click()
669 {
670 }
671
672
CreatePopupWindow()673 VclPtr<SfxPopupWindow> SfxToolBoxControl::CreatePopupWindow()
674 {
675 return nullptr;
676 }
677
CreateItemWindow(vcl::Window *)678 VclPtr<vcl::Window> SfxToolBoxControl::CreateItemWindow( vcl::Window * )
679 {
680 return VclPtr<vcl::Window>();
681 }
682
683 class SfxFrameStatusListener : public svt::FrameStatusListener
684 {
685 public:
686 SfxFrameStatusListener( const css::uno::Reference< css::uno::XComponentContext >& rxContext,
687 const css::uno::Reference< css::frame::XFrame >& xFrame,
688 SfxPopupWindow* pCallee );
689
690 // XStatusListener
691 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
692
693 private:
694 VclPtr<SfxPopupWindow> m_pCallee;
695 };
SfxFrameStatusListener(const Reference<XComponentContext> & rxContext,const Reference<XFrame> & xFrame,SfxPopupWindow * pCallee)696 SfxFrameStatusListener::SfxFrameStatusListener(
697 const Reference< XComponentContext >& rxContext,
698 const Reference< XFrame >& xFrame,
699 SfxPopupWindow* pCallee ) :
700 svt::FrameStatusListener( rxContext, xFrame ),
701 m_pCallee( pCallee )
702 {
703 }
704
705 // XStatusListener
statusChanged(const css::frame::FeatureStateEvent & rEvent)706 void SAL_CALL SfxFrameStatusListener::statusChanged( const css::frame::FeatureStateEvent& rEvent )
707 {
708 m_pCallee->statusChanged( rEvent );
709 }
710
SfxPopupWindow(sal_uInt16 nId,vcl::Window * pParentWindow,const Reference<XFrame> & rFrame,WinBits nBits)711 SfxPopupWindow::SfxPopupWindow(
712 sal_uInt16 nId,
713 vcl::Window* pParentWindow,
714 const Reference< XFrame >& rFrame,
715 WinBits nBits ) :
716 FloatingWindow( pParentWindow, nBits )
717 , m_bFloating( false )
718 , m_bCascading( false )
719 , m_nId( nId )
720 , m_xFrame( rFrame )
721 {
722 vcl::Window* pWindow = GetTopMostParentSystemWindow( this );
723 if ( pWindow )
724 static_cast<SystemWindow *>(pWindow)->GetTaskPaneList()->AddWindow( this );
725 }
726
SfxPopupWindow(sal_uInt16 nId,vcl::Window * pParentWindow,const OString & rID,const OUString & rUIXMLDescription,const Reference<XFrame> & rFrame)727 SfxPopupWindow::SfxPopupWindow(
728 sal_uInt16 nId,
729 vcl::Window* pParentWindow,
730 const OString& rID, const OUString& rUIXMLDescription,
731 const Reference< XFrame >& rFrame ) :
732 FloatingWindow( pParentWindow, rID, rUIXMLDescription, rFrame)
733 , m_bFloating( false )
734 , m_bCascading( false )
735 , m_nId( nId )
736 , m_xFrame( rFrame )
737 {
738 vcl::Window* pWindow = GetTopMostParentSystemWindow( this );
739 if ( pWindow )
740 static_cast<SystemWindow *>(pWindow)->GetTaskPaneList()->AddWindow( this );
741 }
742
~SfxPopupWindow()743 SfxPopupWindow::~SfxPopupWindow()
744 {
745 disposeOnce();
746 }
747
dispose()748 void SfxPopupWindow::dispose()
749 {
750 if ( m_xStatusListener.is() )
751 {
752 m_xStatusListener->dispose();
753 m_xStatusListener.clear();
754 }
755
756 vcl::Window* pWindow = GetTopMostParentSystemWindow( this );
757 if ( pWindow )
758 static_cast<SystemWindow *>(pWindow)->GetTaskPaneList()->RemoveWindow( this );
759 FloatingWindow::dispose();
760 }
761
762
AddStatusListener(const OUString & rCommandURL)763 void SfxPopupWindow::AddStatusListener( const OUString& rCommandURL )
764 {
765 if ( !m_xStatusListener.is() )
766 {
767 m_xStatusListener = new SfxFrameStatusListener(
768 ::comphelper::getProcessComponentContext(),
769 m_xFrame,
770 this );
771 }
772 if ( m_xStatusListener.is() )
773 m_xStatusListener->addStatusListener( rCommandURL );
774 }
775
776
Close()777 bool SfxPopupWindow::Close()
778 {
779 m_bFloating = false;
780 FloatingWindow::Close();
781
782 Delete();
783 return true;
784 }
785
786
PopupModeEnd()787 void SfxPopupWindow::PopupModeEnd()
788 {
789 //! to allow PopupModeEndHdl to be called
790 FloatingWindow::PopupModeEnd();
791
792 if ( IsVisible() )
793 {
794 // was teared-off
795 if ( m_bFloating )
796 {
797 Hide();
798 Delete();
799 }
800 m_bFloating = true;
801 }
802 else
803 Close();
804 }
805
806
MouseMove(const::MouseEvent & rMEvt)807 void SfxPopupWindow::MouseMove( const ::MouseEvent& rMEvt )
808 {
809 if ( !m_bCascading )
810 FloatingWindow::MouseMove( rMEvt );
811 else
812 {
813 // Forward MouseMove-Event to Children
814 ::Point aPos = rMEvt.GetPosPixel();
815 ::Point aScrPos = OutputToScreenPixel( aPos );
816 sal_uInt16 i = 0;
817 vcl::Window* pWindow = GetChild( i );
818 while ( pWindow )
819 {
820 ::MouseEvent aChildMEvt( pWindow->ScreenToOutputPixel( aScrPos ),
821 rMEvt.GetClicks(), rMEvt.GetMode(),
822 rMEvt.GetButtons(), rMEvt.GetModifier() );
823 pWindow->MouseMove( aChildMEvt );
824 pWindow->Update();
825 i++;
826 pWindow = GetChild( i );
827 }
828 }
829 }
830
831
StartCascading()832 void SfxPopupWindow::StartCascading()
833 {
834 m_bCascading = true;
835 }
836
837
statusChanged(const css::frame::FeatureStateEvent & rEvent)838 void SfxPopupWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent )
839 {
840 if ( !rEvent.IsEnabled )
841 {
842 Hide();
843 }
844 else if ( m_bFloating )
845 {
846 Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
847 }
848 }
849
850
Delete()851 void SfxPopupWindow::Delete()
852 {
853 VclPtr<SfxPopupWindow> xThis(this);
854 m_aDeleteLink.Call( this );
855 disposeOnce();
856 }
857
858 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
859