1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <uielement/statusbarmanager.hxx>
21 #include <uielement/genericstatusbarcontroller.hxx>
23 #include <framework/sfxhelperfunctions.hxx>
24 #include <framework/addonsoptions.hxx>
25 #include <uielement/statusbarmerger.hxx>
26 #include <uielement/statusbaritem.hxx>
27 #include <macros/generic.hxx>
28 #include <macros/xinterface.hxx>
29 #include <macros/xtypeprovider.hxx>
33 #include "properties.h"
34 #include <helper/mischelper.hxx>
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/frame/theStatusbarControllerFactory.hpp>
38 #include <com/sun/star/ui/ItemStyle.hpp>
39 #include <com/sun/star/ui/ItemType.hpp>
40 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/awt/Command.hpp>
44 #include <com/sun/star/ui/XStatusbarItem.hdl>
45 #include <comphelper/processfactory.hxx>
46 #include <toolkit/helper/vclunohelper.hxx>
47 #include <svtools/statusbarcontroller.hxx>
49 #include <vcl/status.hxx>
50 #include <vcl/svapp.hxx>
51 #include <vcl/settings.hxx>
55 using namespace ::com::sun::star
;
57 // Property names of a menu/menu item ItemDescriptor
58 static const char ITEM_DESCRIPTOR_COMMANDURL
[] = "CommandURL";
59 static const char ITEM_DESCRIPTOR_HELPURL
[] = "HelpURL";
60 static const char ITEM_DESCRIPTOR_OFFSET
[] = "Offset";
61 static const char ITEM_DESCRIPTOR_STYLE
[] = "Style";
62 static const char ITEM_DESCRIPTOR_WIDTH
[] = "Width";
63 static const char ITEM_DESCRIPTOR_TYPE
[] = "Type";
72 struct lcl_UpdateController
: public std::unary_function
< typename
MAP::value_type
, void >
74 void operator()( typename
MAP::value_type
&rElement
) const
78 if ( rElement
.second
.is() )
79 rElement
.second
->update();
81 catch ( uno::Exception
& )
88 struct lcl_RemoveController
: public std::unary_function
< typename
MAP::value_type
, void >
90 void operator()( typename
MAP::value_type
&rElement
) const
94 if ( rElement
.second
.is() )
95 rElement
.second
->dispose();
97 catch ( uno::Exception
& )
103 static sal_uInt16
impl_convertItemStyleToItemBits( sal_Int16 nStyle
)
105 sal_uInt16
nItemBits( 0 );
107 if (( nStyle
& ::com::sun::star::ui::ItemStyle::ALIGN_RIGHT
) == ::com::sun::star::ui::ItemStyle::ALIGN_RIGHT
)
108 nItemBits
|= SIB_RIGHT
;
109 else if ( nStyle
& ::com::sun::star::ui::ItemStyle::ALIGN_LEFT
)
110 nItemBits
|= SIB_LEFT
;
112 nItemBits
|= SIB_CENTER
;
114 if (( nStyle
& ::com::sun::star::ui::ItemStyle::DRAW_FLAT
) == ::com::sun::star::ui::ItemStyle::DRAW_FLAT
)
115 nItemBits
|= SIB_FLAT
;
116 else if ( nStyle
& ::com::sun::star::ui::ItemStyle::DRAW_OUT3D
)
117 nItemBits
|= SIB_OUT
;
121 if (( nStyle
& ::com::sun::star::ui::ItemStyle::AUTO_SIZE
) == ::com::sun::star::ui::ItemStyle::AUTO_SIZE
)
122 nItemBits
|= SIB_AUTOSIZE
;
123 if ( nStyle
& ::com::sun::star::ui::ItemStyle::OWNER_DRAW
)
124 nItemBits
|= SIB_USERDRAW
;
131 StatusBarManager::StatusBarManager(
132 const uno::Reference
< uno::XComponentContext
>& rxContext
,
133 const uno::Reference
< frame::XFrame
>& rFrame
,
134 const OUString
& rResourceName
,
135 StatusBar
* pStatusBar
) :
136 m_bDisposed( false ),
137 m_bFrameActionRegistered( false ),
138 m_bUpdateControllers( false ),
139 m_bModuleIdentified( false ),
140 m_pStatusBar( pStatusBar
),
141 m_aResourceName( rResourceName
),
143 m_aListenerContainer( m_mutex
),
144 m_xContext( rxContext
)
147 m_xStatusbarControllerFactory
= frame::theStatusbarControllerFactory::get(
148 ::comphelper::getProcessComponentContext());
150 m_pStatusBar
->AdjustItemWidthsForHiDPI(true);
151 m_pStatusBar
->SetClickHdl( LINK( this, StatusBarManager
, Click
) );
152 m_pStatusBar
->SetDoubleClickHdl( LINK( this, StatusBarManager
, DoubleClick
) );
155 StatusBarManager::~StatusBarManager()
159 StatusBar
* StatusBarManager::GetStatusBar() const
165 void StatusBarManager::frameAction( const frame::FrameActionEvent
& Action
)
166 throw ( uno::RuntimeException
, std::exception
)
169 if ( Action
.Action
== frame::FrameAction_CONTEXT_CHANGED
)
173 void SAL_CALL
StatusBarManager::disposing( const lang::EventObject
& Source
) throw ( uno::RuntimeException
, std::exception
)
185 if ( Source
.Source
== uno::Reference
< uno::XInterface
>( m_xFrame
, uno::UNO_QUERY
))
193 void SAL_CALL
StatusBarManager::dispose() throw( uno::RuntimeException
, std::exception
)
195 uno::Reference
< lang::XComponent
> xThis(
196 static_cast< OWeakObject
* >(this), uno::UNO_QUERY
);
198 lang::EventObject
aEvent( xThis
);
199 m_aListenerContainer
.disposeAndClear( aEvent
);
208 // destroy the item data
209 for ( sal_uInt16 n
= 0; n
< m_pStatusBar
->GetItemCount(); n
++ )
211 AddonStatusbarItemData
*pUserData
= static_cast< AddonStatusbarItemData
*>(
212 m_pStatusBar
->GetItemData( m_pStatusBar
->GetItemId( n
) ) );
217 m_pStatusBar
.disposeAndClear();
219 if ( m_bFrameActionRegistered
&& m_xFrame
.is() )
223 m_xFrame
->removeFrameActionListener( uno::Reference
< frame::XFrameActionListener
>(
224 static_cast< ::cppu::OWeakObject
*>( this ),
227 catch ( const uno::Exception
& )
239 void SAL_CALL
StatusBarManager::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
) throw( uno::RuntimeException
, std::exception
)
243 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
245 throw lang::DisposedException();
247 m_aListenerContainer
.addInterface( cppu::UnoType
<lang::XEventListener
>::get(), xListener
);
250 void SAL_CALL
StatusBarManager::removeEventListener( const uno::Reference
< lang::XEventListener
>& xListener
) throw( uno::RuntimeException
, std::exception
)
252 m_aListenerContainer
.removeInterface( cppu::UnoType
<lang::XEventListener
>::get(), xListener
);
255 // XUIConfigurationListener
256 void SAL_CALL
StatusBarManager::elementInserted( const css::ui::ConfigurationEvent
& ) throw ( uno::RuntimeException
, std::exception
)
264 void SAL_CALL
StatusBarManager::elementRemoved( const css::ui::ConfigurationEvent
& ) throw ( uno::RuntimeException
, std::exception
)
272 void SAL_CALL
StatusBarManager::elementReplaced( const css::ui::ConfigurationEvent
& ) throw ( uno::RuntimeException
, std::exception
)
280 void StatusBarManager::UpdateControllers()
282 if ( !m_bUpdateControllers
)
284 m_bUpdateControllers
= true;
285 std::for_each( m_aControllerMap
.begin(),
286 m_aControllerMap
.end(),
287 lcl_UpdateController
< StatusBarControllerMap
>() );
289 m_bUpdateControllers
= false;
292 void StatusBarManager::RemoveControllers()
299 std::for_each( m_aControllerMap
.begin(),
300 m_aControllerMap
.end(),
301 lcl_RemoveController
< StatusBarControllerMap
>() );
302 m_aControllerMap
.clear();
305 OUString
StatusBarManager::RetrieveLabelFromCommand( const OUString
& aCmdURL
)
307 return framework::RetrieveLabelFromCommand(aCmdURL
, m_xContext
, m_xUICommandLabels
,m_xFrame
,m_aModuleIdentifier
,m_bModuleIdentified
,"Name");
310 void StatusBarManager::CreateControllers()
312 uno::Reference
< awt::XWindow
> xStatusbarWindow
= VCLUnoHelper::GetInterface( m_pStatusBar
);
314 for ( sal_uInt16 i
= 0; i
< m_pStatusBar
->GetItemCount(); i
++ )
316 sal_uInt16 nId
= m_pStatusBar
->GetItemId( i
);
320 OUString
aCommandURL( m_pStatusBar
->GetItemCommand( nId
));
322 uno::Reference
< frame::XStatusbarController
> xController
;
323 AddonStatusbarItemData
*pItemData
= static_cast< AddonStatusbarItemData
*>( m_pStatusBar
->GetItemData( nId
) );
324 uno::Reference
< ui::XStatusbarItem
> xStatusbarItem(
325 static_cast< cppu::OWeakObject
*>( new StatusbarItem( m_pStatusBar
, pItemData
, nId
, aCommandURL
) ),
328 beans::PropertyValue aPropValue
;
329 std::vector
< uno::Any
> aPropVector
;
331 aPropValue
.Name
= "CommandURL";
332 aPropValue
.Value
<<= aCommandURL
;
333 aPropVector
.push_back( uno::makeAny( aPropValue
) );
335 aPropValue
.Name
= "ModuleIdentifier";
336 aPropValue
.Value
<<= m_aModuleIdentifier
;
337 aPropVector
.push_back( uno::makeAny( aPropValue
) );
339 aPropValue
.Name
= "Frame";
340 aPropValue
.Value
<<= m_xFrame
;
341 aPropVector
.push_back( uno::makeAny( aPropValue
) );
344 aPropValue
.Name
= "ServiceManager";
345 aPropValue
.Value
= uno::makeAny( uno::Reference
<lang::XMultiServiceFactory
>(m_xContext
->getServiceManager(), uno::UNO_QUERY_THROW
) );
346 aPropVector
.push_back( uno::makeAny( aPropValue
) );
348 aPropValue
.Name
= "ParentWindow";
349 aPropValue
.Value
<<= xStatusbarWindow
;
350 aPropVector
.push_back( uno::makeAny( aPropValue
) );
352 // TODO still needing with the css::ui::XStatusbarItem?
353 aPropValue
.Name
= "Identifier";
354 aPropValue
.Value
<<= nId
;
355 aPropVector
.push_back( uno::makeAny( aPropValue
) );
357 aPropValue
.Name
= "StatusbarItem";
358 aPropValue
.Value
<<= xStatusbarItem
;
359 aPropVector
.push_back( uno::makeAny( aPropValue
) );
361 uno::Sequence
< uno::Any
> aArgs( comphelper::containerToSequence( aPropVector
) );
363 // 1) UNO Statusbar controllers, registered in Controllers.xcu
364 if ( m_xStatusbarControllerFactory
.is() &&
365 m_xStatusbarControllerFactory
->hasController( aCommandURL
, m_aModuleIdentifier
))
367 xController
= uno::Reference
< frame::XStatusbarController
>(
368 m_xStatusbarControllerFactory
->createInstanceWithArgumentsAndContext(
369 aCommandURL
, aArgs
, m_xContext
),
371 bInit
= false; // Initialization is done through the factory service
374 if ( !xController
.is() )
376 svt::StatusbarController
* pController( 0 );
378 // 2) Old SFX2 Statusbar controllers
379 pController
= CreateStatusBarController( m_xFrame
, m_pStatusBar
, nId
, aCommandURL
);
382 // 3) Is Add-on? Generic statusbar controller
385 pController
= new GenericStatusbarController( m_xContext
,
392 // 4) Default Statusbar controller
393 pController
= new svt::StatusbarController( m_xContext
, m_xFrame
, aCommandURL
, nId
);
398 xController
= uno::Reference
< frame::XStatusbarController
>(
399 static_cast< ::cppu::OWeakObject
*>( pController
),
403 m_aControllerMap
[nId
] = xController
;
406 xController
->initialize( aArgs
);
410 AddFrameActionListener();
413 void StatusBarManager::AddFrameActionListener()
415 if ( !m_bFrameActionRegistered
&& m_xFrame
.is() )
417 m_bFrameActionRegistered
= true;
418 m_xFrame
->addFrameActionListener( uno::Reference
< frame::XFrameActionListener
>(
419 static_cast< ::cppu::OWeakObject
*>( this ), uno::UNO_QUERY
));
423 void StatusBarManager::FillStatusBar( const uno::Reference
< container::XIndexAccess
>& rItemContainer
)
427 if ( m_bDisposed
|| !m_pStatusBar
)
434 // reset and fill command map
435 m_pStatusBar
->Clear();
436 m_aControllerMap
.clear();// TODO already done in RemoveControllers
438 for ( sal_Int32 n
= 0; n
< rItemContainer
->getCount(); n
++ )
440 uno::Sequence
< beans::PropertyValue
> aProp
;
441 OUString aCommandURL
;
443 sal_Int16
nOffset( 0 );
444 sal_Int16
nStyle( 0 );
445 sal_Int16
nWidth( 0 );
446 sal_uInt16
nType( ::com::sun::star::ui::ItemType::DEFAULT
);
450 if ( rItemContainer
->getByIndex( n
) >>= aProp
)
452 for ( int i
= 0; i
< aProp
.getLength(); i
++ )
454 if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_COMMANDURL
)
456 aProp
[i
].Value
>>= aCommandURL
;
458 else if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_HELPURL
)
460 aProp
[i
].Value
>>= aHelpURL
;
462 else if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_STYLE
)
464 aProp
[i
].Value
>>= nStyle
;
466 else if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_TYPE
)
468 aProp
[i
].Value
>>= nType
;
470 else if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_WIDTH
)
472 aProp
[i
].Value
>>= nWidth
;
474 else if ( aProp
[i
].Name
== ITEM_DESCRIPTOR_OFFSET
)
476 aProp
[i
].Value
>>= nOffset
;
480 if (( nType
== ::com::sun::star::ui::ItemType::DEFAULT
) && !aCommandURL
.isEmpty() )
482 OUString
aString( RetrieveLabelFromCommand( aCommandURL
));
483 sal_uInt16
nItemBits( impl_convertItemStyleToItemBits( nStyle
));
485 m_pStatusBar
->InsertItem( nId
, nWidth
, nItemBits
, nOffset
);
486 m_pStatusBar
->SetItemCommand( nId
, aCommandURL
);
487 m_pStatusBar
->SetAccessibleName( nId
, aString
);
492 catch ( const ::com::sun::star::lang::IndexOutOfBoundsException
& )
499 const sal_uInt16 STATUSBAR_ITEM_STARTID
= 1000;
500 MergeStatusbarInstructionContainer aMergeInstructions
= AddonsOptions().GetMergeStatusbarInstructions();
501 if ( !aMergeInstructions
.empty() )
503 const sal_uInt32 nCount
= aMergeInstructions
.size();
504 sal_uInt16
nItemId( STATUSBAR_ITEM_STARTID
);
506 for ( sal_uInt32 i
= 0; i
< nCount
; i
++ )
508 MergeStatusbarInstruction
&rInstruction
= aMergeInstructions
[i
];
509 if ( !StatusbarMerger::IsCorrectContext( rInstruction
.aMergeContext
, m_aModuleIdentifier
) )
512 AddonStatusbarItemContainer aItems
;
513 StatusbarMerger::ConvertSeqSeqToVector( rInstruction
.aMergeStatusbarItems
, aItems
);
515 sal_uInt16 nRefPos
= StatusbarMerger::FindReferencePos( m_pStatusBar
, rInstruction
.aMergePoint
);
516 if ( nRefPos
!= STATUSBAR_ITEM_NOTFOUND
)
518 StatusbarMerger::ProcessMergeOperation( m_pStatusBar
,
522 rInstruction
.aMergeCommand
,
523 rInstruction
.aMergeCommandParameter
,
528 StatusbarMerger::ProcessMergeFallback( m_pStatusBar
,
532 rInstruction
.aMergeCommand
,
533 rInstruction
.aMergeCommandParameter
,
539 // Create controllers
542 // Notify controllers that they are now correctly initialized and can start listening
546 void StatusBarManager::DataChanged( const DataChangedEvent
& rDCEvt
)
548 SolarMutexClearableGuard aGuard
;
550 if ((( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) ||
551 ( rDCEvt
.GetType() == DataChangedEventType::FONTS
) ||
552 ( rDCEvt
.GetType() == DataChangedEventType::FONTSUBSTITUTION
) ||
553 ( rDCEvt
.GetType() == DataChangedEventType::DISPLAY
)) &&
554 ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
556 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
557 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( m_xFrame
, css::uno::UNO_QUERY
);
559 xPropSet
->getPropertyValue("LayoutManager") >>= xLayoutManager
;
560 if ( xLayoutManager
.is() )
563 xLayoutManager
->doLayout();
568 void StatusBarManager::UserDraw( const UserDrawEvent
& rUDEvt
)
570 SolarMutexClearableGuard aGuard
;
575 sal_uInt16
nId( rUDEvt
.GetItemId() );
576 StatusBarControllerMap::const_iterator it
= m_aControllerMap
.find( nId
);
577 if (( nId
> 0 ) && ( it
!= m_aControllerMap
.end() ))
579 uno::Reference
< frame::XStatusbarController
> xController( it
->second
);
580 if (xController
.is() && rUDEvt
.GetRenderContext())
582 uno::Reference
< awt::XGraphics
> xGraphics
= rUDEvt
.GetRenderContext()->CreateUnoGraphics();
584 awt::Rectangle
aRect( rUDEvt
.GetRect().Left(),
585 rUDEvt
.GetRect().Top(),
586 rUDEvt
.GetRect().GetWidth(),
587 rUDEvt
.GetRect().GetHeight() );
589 xController
->paint( xGraphics
, aRect
, rUDEvt
.GetStyle() );
594 void StatusBarManager::Command( const CommandEvent
& rEvt
)
601 if ( rEvt
.GetCommand() == CommandEventId::ContextMenu
)
603 sal_uInt16 nId
= m_pStatusBar
->GetItemId( rEvt
.GetMousePosPixel() );
604 StatusBarControllerMap::const_iterator it
= m_aControllerMap
.find( nId
);
605 if (( nId
> 0 ) && ( it
!= m_aControllerMap
.end() ))
607 uno::Reference
< frame::XStatusbarController
> xController( it
->second
);
608 if ( xController
.is() )
611 aPos
.X
= rEvt
.GetMousePosPixel().X();
612 aPos
.Y
= rEvt
.GetMousePosPixel().Y();
613 xController
->command( aPos
, awt::Command::CONTEXTMENU
, sal_True
, uno::Any() );
619 void StatusBarManager::MouseMove( const MouseEvent
& rMEvt
)
621 MouseButton(rMEvt
,&frame::XStatusbarController::mouseMove
);
624 void StatusBarManager::MouseButton( const MouseEvent
& rMEvt
,sal_Bool ( SAL_CALL
frame::XStatusbarController::*_pMethod
)(const ::com::sun::star::awt::MouseEvent
&))
630 sal_uInt16 nId
= m_pStatusBar
->GetItemId( rMEvt
.GetPosPixel() );
631 StatusBarControllerMap::const_iterator it
= m_aControllerMap
.find( nId
);
632 if (( nId
> 0 ) && ( it
!= m_aControllerMap
.end() ))
634 uno::Reference
< frame::XStatusbarController
> xController( it
->second
);
635 if ( xController
.is() )
637 ::com::sun::star::awt::MouseEvent aMouseEvent
;
638 aMouseEvent
.Buttons
= rMEvt
.GetButtons();
639 aMouseEvent
.X
= rMEvt
.GetPosPixel().X();
640 aMouseEvent
.Y
= rMEvt
.GetPosPixel().Y();
641 aMouseEvent
.ClickCount
= rMEvt
.GetClicks();
642 (xController
.get()->*_pMethod
)( aMouseEvent
);
648 void StatusBarManager::MouseButtonDown( const MouseEvent
& rMEvt
)
650 MouseButton(rMEvt
,&frame::XStatusbarController::mouseButtonDown
);
653 void StatusBarManager::MouseButtonUp( const MouseEvent
& rMEvt
)
655 MouseButton(rMEvt
,&frame::XStatusbarController::mouseButtonUp
);
658 IMPL_LINK_NOARG(StatusBarManager
, Click
)
665 sal_uInt16 nId
= m_pStatusBar
->GetCurItemId();
666 StatusBarControllerMap::const_iterator it
= m_aControllerMap
.find( nId
);
667 if (( nId
> 0 ) && ( it
!= m_aControllerMap
.end() ))
669 uno::Reference
< frame::XStatusbarController
> xController( it
->second
);
670 if ( xController
.is() )
672 const Point aVCLPos
= m_pStatusBar
->GetPointerPosPixel();
673 const awt::Point
aAWTPoint( aVCLPos
.X(), aVCLPos
.Y() );
674 xController
->click( aAWTPoint
);
681 IMPL_LINK_NOARG(StatusBarManager
, DoubleClick
)
688 sal_uInt16 nId
= m_pStatusBar
->GetCurItemId();
689 StatusBarControllerMap::const_iterator it
= m_aControllerMap
.find( nId
);
690 if (( nId
> 0 ) && ( it
!= m_aControllerMap
.end() ))
692 uno::Reference
< frame::XStatusbarController
> xController( it
->second
);
693 if ( xController
.is() )
695 const Point aVCLPos
= m_pStatusBar
->GetPointerPosPixel();
696 const awt::Point
aAWTPoint( aVCLPos
.X(), aVCLPos
.Y() );
697 xController
->doubleClick( aAWTPoint
);
706 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */