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 <uiconfiguration/windowstateproperties.hxx>
21 #include <helper/mischelper.hxx>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/container/XNameAccess.hpp>
27 #include <com/sun/star/container/XNameContainer.hpp>
28 #include <com/sun/star/container/XContainer.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
31 #include <com/sun/star/frame/ModuleManager.hpp>
32 #include <com/sun/star/frame/XModuleManager2.hpp>
33 #include <com/sun/star/awt/Point.hpp>
34 #include <com/sun/star/awt/Size.hpp>
35 #include <com/sun/star/ui/DockingArea.hpp>
36 #include <com/sun/star/util/XChangesBatch.hpp>
37 #include <com/sun/star/uno/XComponentContext.hpp>
39 #include <comphelper/compbase.hxx>
40 #include <comphelper/string.hxx>
41 #include <cppuhelper/implbase.hxx>
42 #include <cppuhelper/supportsservice.hxx>
43 #include <comphelper/propertysequence.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <rtl/ref.hxx>
46 #include <sal/log.hxx>
47 #include <o3tl/string_view.hxx>
50 #include <string_view>
51 #include <unordered_map>
54 using namespace com::sun::star::uno
;
55 using namespace com::sun::star::lang
;
56 using namespace com::sun::star::beans
;
57 using namespace com::sun::star::util
;
58 using namespace com::sun::star::configuration
;
59 using namespace com::sun::star::container
;
60 using namespace ::com::sun::star::frame
;
61 using namespace ::com::sun::star::ui
;
62 using namespace framework
;
66 // Zero based indexes, order must be the same as WindowStateMask && CONFIGURATION_PROPERTIES!
67 const sal_Int16 PROPERTY_LOCKED
= 0;
68 const sal_Int16 PROPERTY_DOCKED
= 1;
69 const sal_Int16 PROPERTY_VISIBLE
= 2;
70 const sal_Int16 PROPERTY_CONTEXT
= 3;
71 const sal_Int16 PROPERTY_HIDEFROMMENU
= 4;
72 const sal_Int16 PROPERTY_NOCLOSE
= 5;
73 const sal_Int16 PROPERTY_SOFTCLOSE
= 6;
74 const sal_Int16 PROPERTY_CONTEXTACTIVE
= 7;
75 const sal_Int16 PROPERTY_DOCKINGAREA
= 8;
76 const sal_Int16 PROPERTY_POS
= 9;
77 const sal_Int16 PROPERTY_SIZE
= 10;
78 const sal_Int16 PROPERTY_UINAME
= 11;
79 const sal_Int16 PROPERTY_INTERNALSTATE
= 12;
80 const sal_Int16 PROPERTY_STYLE
= 13;
81 const sal_Int16 PROPERTY_DOCKPOS
= 14;
82 const sal_Int16 PROPERTY_DOCKSIZE
= 15;
84 // Order must be the same as WindowStateMask!!
85 constexpr OUString CONFIGURATION_PROPERTIES
[]
87 WINDOWSTATE_PROPERTY_LOCKED
,
88 WINDOWSTATE_PROPERTY_DOCKED
,
89 WINDOWSTATE_PROPERTY_VISIBLE
,
90 WINDOWSTATE_PROPERTY_CONTEXT
,
91 WINDOWSTATE_PROPERTY_HIDEFROMENU
,
92 WINDOWSTATE_PROPERTY_NOCLOSE
,
93 WINDOWSTATE_PROPERTY_SOFTCLOSE
,
94 WINDOWSTATE_PROPERTY_CONTEXTACTIVE
,
95 WINDOWSTATE_PROPERTY_DOCKINGAREA
,
96 WINDOWSTATE_PROPERTY_POS
,
97 WINDOWSTATE_PROPERTY_SIZE
,
98 WINDOWSTATE_PROPERTY_UINAME
,
99 WINDOWSTATE_PROPERTY_INTERNALSTATE
,
100 WINDOWSTATE_PROPERTY_STYLE
,
101 WINDOWSTATE_PROPERTY_DOCKPOS
,
102 WINDOWSTATE_PROPERTY_DOCKSIZE
105 // Configuration access class for WindowState supplier implementation
107 class ConfigurationAccess_WindowState
: public ::cppu::WeakImplHelper
< XNameContainer
, XContainerListener
>
110 ConfigurationAccess_WindowState( std::u16string_view aWindowStateConfigFile
, const Reference
< XComponentContext
>& rxContext
);
111 virtual ~ConfigurationAccess_WindowState() override
;
114 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
116 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames() override
;
118 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
121 virtual void SAL_CALL
removeByName( const OUString
& sName
) override
;
123 virtual void SAL_CALL
insertByName( const OUString
& sName
, const css::uno::Any
& aPropertySet
) override
;
126 virtual void SAL_CALL
replaceByName( const OUString
& sName
, const css::uno::Any
& aPropertySet
) override
;
129 virtual css::uno::Type SAL_CALL
getElementType() override
;
131 virtual sal_Bool SAL_CALL
hasElements() override
;
133 // container.XContainerListener
134 virtual void SAL_CALL
elementInserted( const ContainerEvent
& aEvent
) override
;
135 virtual void SAL_CALL
elementRemoved ( const ContainerEvent
& aEvent
) override
;
136 virtual void SAL_CALL
elementReplaced( const ContainerEvent
& aEvent
) override
;
138 // lang.XEventListener
139 virtual void SAL_CALL
disposing( const EventObject
& aEvent
) override
;
142 enum // WindowStateMask
144 WINDOWSTATE_MASK_DOCKINGAREA
= 256,
145 WINDOWSTATE_MASK_POS
= 512,
146 WINDOWSTATE_MASK_SIZE
= 1024,
147 WINDOWSTATE_MASK_UINAME
= 2048,
148 WINDOWSTATE_MASK_INTERNALSTATE
= 4096,
149 WINDOWSTATE_MASK_STYLE
= 8192,
150 WINDOWSTATE_MASK_DOCKPOS
= 16384,
151 WINDOWSTATE_MASK_DOCKSIZE
= 32768
154 // Cache structure. Valid values are described by the eMask member. All other values should not be
155 // provided to outside code!
156 struct WindowStateInfo
163 , bHideFromMenu(false)
166 , bContextActive(false)
167 , aDockingArea(css::ui::DockingArea_DOCKINGAREA_TOP
)
185 css::ui::DockingArea aDockingArea
;
186 css::awt::Point aDockPos
;
187 css::awt::Size aDockSize
;
188 css::awt::Point aPos
;
189 css::awt::Size aSize
;
191 sal_uInt32 nInternalState
;
193 sal_uInt32 nMask
; // see WindowStateMask
196 void impl_putPropertiesFromStruct( const WindowStateInfo
& rWinStateInfo
, Reference
< XPropertySet
> const & xPropSet
);
197 Any
impl_insertCacheAndReturnSequence( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
);
198 WindowStateInfo
& impl_insertCacheAndReturnWinState( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
);
199 Any
impl_getSequenceFromStruct( const WindowStateInfo
& rWinStateInfo
);
200 void impl_fillStructFromSequence( WindowStateInfo
& rWinStateInfo
, const Sequence
< PropertyValue
>& rSeq
);
201 Any
impl_getWindowStateFromResourceURL( const OUString
& rResourceURL
);
202 void impl_initializeConfigAccess();
205 typedef std::unordered_map
< OUString
,
206 WindowStateInfo
> ResourceURLToInfoCache
;
209 OUString m_aConfigWindowAccess
;
210 Reference
< XMultiServiceFactory
> m_xConfigProvider
;
211 Reference
< XNameAccess
> m_xConfigAccess
;
212 rtl::Reference
< WeakContainerListener
> m_xConfigListener
;
213 ResourceURLToInfoCache m_aResourceURLToInfoCache
;
214 bool m_bConfigAccessInitialized
: 1,
216 std::vector
< OUString
> m_aPropArray
;
219 ConfigurationAccess_WindowState::ConfigurationAccess_WindowState( std::u16string_view aModuleName
, const Reference
< XComponentContext
>& rxContext
) :
220 // Create configuration hierarchical access name
221 m_aConfigWindowAccess(
222 OUString::Concat("/org.openoffice.Office.UI.") + aModuleName
+ "/UIElements/States"),
223 m_xConfigProvider(theDefaultProvider::get( rxContext
)),
224 m_bConfigAccessInitialized( false ),
227 // Initialize access array with property names.
228 for (const OUString
& s
: CONFIGURATION_PROPERTIES
)
229 m_aPropArray
.push_back(s
);
232 ConfigurationAccess_WindowState::~ConfigurationAccess_WindowState()
235 std::unique_lock
g(m_aMutex
);
236 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
237 if ( xContainer
.is() )
238 xContainer
->removeContainerListener(m_xConfigListener
);
242 Any SAL_CALL
ConfigurationAccess_WindowState::getByName( const OUString
& rResourceURL
)
245 std::unique_lock
g(m_aMutex
);
247 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
248 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
249 return impl_getSequenceFromStruct( pIter
->second
);
252 Any
a( impl_getWindowStateFromResourceURL( rResourceURL
) );
254 throw NoSuchElementException();
259 Sequence
< OUString
> SAL_CALL
ConfigurationAccess_WindowState::getElementNames()
262 std::unique_lock
g(m_aMutex
);
264 if ( !m_bConfigAccessInitialized
)
266 impl_initializeConfigAccess();
267 m_bConfigAccessInitialized
= true;
270 if ( m_xConfigAccess
.is() )
271 return m_xConfigAccess
->getElementNames();
273 return Sequence
< OUString
> ();
276 sal_Bool SAL_CALL
ConfigurationAccess_WindowState::hasByName( const OUString
& rResourceURL
)
279 std::unique_lock
g(m_aMutex
);
281 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
282 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
286 Any
a( impl_getWindowStateFromResourceURL( rResourceURL
) );
295 Type SAL_CALL
ConfigurationAccess_WindowState::getElementType()
297 return cppu::UnoType
<Sequence
< PropertyValue
>>::get();
300 sal_Bool SAL_CALL
ConfigurationAccess_WindowState::hasElements()
303 std::unique_lock
g(m_aMutex
);
305 if ( !m_bConfigAccessInitialized
)
307 impl_initializeConfigAccess();
308 m_bConfigAccessInitialized
= true;
311 if ( m_xConfigAccess
.is() )
312 return m_xConfigAccess
->hasElements();
318 void SAL_CALL
ConfigurationAccess_WindowState::removeByName( const OUString
& rResourceURL
)
321 std::unique_lock
g(m_aMutex
);
323 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
324 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
325 m_aResourceURLToInfoCache
.erase( pIter
);
327 if ( !m_bConfigAccessInitialized
)
329 impl_initializeConfigAccess();
330 m_bConfigAccessInitialized
= true;
335 // Remove must be write-through => remove element from configuration
336 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
337 if ( xNameContainer
.is() )
341 xNameContainer
->removeByName( rResourceURL
);
342 Reference
< XChangesBatch
> xFlush( m_xConfigAccess
, UNO_QUERY
);
344 xFlush
->commitChanges();
347 catch ( const css::lang::WrappedTargetException
& )
352 void SAL_CALL
ConfigurationAccess_WindowState::insertByName( const OUString
& rResourceURL
, const css::uno::Any
& aPropertySet
)
355 std::unique_lock
g(m_aMutex
);
357 Sequence
< PropertyValue
> aPropSet
;
358 if ( !(aPropertySet
>>= aPropSet
) )
359 throw IllegalArgumentException();
361 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
362 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
363 throw ElementExistException();
365 if ( !m_bConfigAccessInitialized
)
367 impl_initializeConfigAccess();
368 m_bConfigAccessInitialized
= true;
371 // Try to ask our configuration access
372 if ( !m_xConfigAccess
.is() )
375 if ( m_xConfigAccess
->hasByName( rResourceURL
) )
376 throw ElementExistException();
378 WindowStateInfo aWinStateInfo
;
379 impl_fillStructFromSequence( aWinStateInfo
, aPropSet
);
380 m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWinStateInfo
);
382 // insert must be write-through => insert element into configuration
383 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
384 if ( !xNameContainer
.is() )
387 Reference
< XSingleServiceFactory
> xFactory( m_xConfigAccess
, UNO_QUERY
);
392 Reference
< XPropertySet
> xPropSet( xFactory
->createInstance(), UNO_QUERY
);
396 impl_putPropertiesFromStruct( aWinStateInfo
, xPropSet
);
398 xNameContainer
->insertByName( rResourceURL
, a
);
399 Reference
< XChangesBatch
> xFlush( xFactory
, UNO_QUERY
);
401 xFlush
->commitChanges();
404 catch ( const Exception
& )
410 void SAL_CALL
ConfigurationAccess_WindowState::replaceByName( const OUString
& rResourceURL
, const css::uno::Any
& aPropertySet
)
413 std::unique_lock
g(m_aMutex
);
415 Sequence
< PropertyValue
> aPropSet
;
416 if ( !(aPropertySet
>>= aPropSet
) )
417 throw IllegalArgumentException();
419 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
420 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
422 WindowStateInfo
& rWinStateInfo
= pIter
->second
;
423 impl_fillStructFromSequence( rWinStateInfo
, aPropSet
);
428 if ( !m_bConfigAccessInitialized
)
430 impl_initializeConfigAccess();
431 m_bConfigAccessInitialized
= true;
434 // Try to ask our configuration access
435 Reference
< XNameAccess
> xNameAccess
;
436 Any
a( m_xConfigAccess
->getByName( rResourceURL
));
438 if ( !(a
>>= xNameAccess
) )
439 throw NoSuchElementException();
441 WindowStateInfo
& rWinStateInfo( impl_insertCacheAndReturnWinState( rResourceURL
, xNameAccess
));
442 impl_fillStructFromSequence( rWinStateInfo
, aPropSet
);
444 pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
448 if ( !(m_bModified
&& pIter
!= m_aResourceURLToInfoCache
.end()) )
451 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
452 if ( !xNameContainer
.is() )
455 WindowStateInfo
aWinStateInfo( pIter
->second
);
456 OUString
aResourceURL( pIter
->first
);
462 Reference
< XPropertySet
> xPropSet
;
463 if ( xNameContainer
->getByName( aResourceURL
) >>= xPropSet
)
465 impl_putPropertiesFromStruct( aWinStateInfo
, xPropSet
);
467 Reference
< XChangesBatch
> xFlush( m_xConfigAccess
, UNO_QUERY
);
469 xFlush
->commitChanges();
472 catch ( const Exception
& )
478 // container.XContainerListener
479 void SAL_CALL
ConfigurationAccess_WindowState::elementInserted( const ContainerEvent
& )
481 // do nothing - next time someone wants to retrieve this node we will find it in the configuration
484 void SAL_CALL
ConfigurationAccess_WindowState::elementRemoved ( const ContainerEvent
& )
488 void SAL_CALL
ConfigurationAccess_WindowState::elementReplaced( const ContainerEvent
& )
492 // lang.XEventListener
493 void SAL_CALL
ConfigurationAccess_WindowState::disposing( const EventObject
& aEvent
)
496 // remove our reference to the config access
497 std::unique_lock
g(m_aMutex
);
499 Reference
< XInterface
> xIfac1( aEvent
.Source
, UNO_QUERY
);
500 Reference
< XInterface
> xIfac2( m_xConfigAccess
, UNO_QUERY
);
501 if ( xIfac1
== xIfac2
)
502 m_xConfigAccess
.clear();
505 // private helper methods
506 Any
ConfigurationAccess_WindowState::impl_getSequenceFromStruct( const WindowStateInfo
& rWinStateInfo
)
509 sal_Int32
nCount( m_aPropArray
.size() );
510 std::vector
< PropertyValue
> aPropVec
;
512 for ( i
= 0; i
< nCount
; i
++ )
514 if ( rWinStateInfo
.nMask
& ( 1 << i
))
516 // put value into the return sequence
518 pv
.Name
= m_aPropArray
[i
];
522 case PROPERTY_LOCKED
:
523 pv
.Value
<<= rWinStateInfo
.bLocked
; break;
524 case PROPERTY_DOCKED
:
525 pv
.Value
<<= rWinStateInfo
.bDocked
; break;
526 case PROPERTY_VISIBLE
:
527 pv
.Value
<<= rWinStateInfo
.bVisible
; break;
528 case PROPERTY_CONTEXT
:
529 pv
.Value
<<= rWinStateInfo
.bContext
; break;
530 case PROPERTY_HIDEFROMMENU
:
531 pv
.Value
<<= rWinStateInfo
.bHideFromMenu
; break;
532 case PROPERTY_NOCLOSE
:
533 pv
.Value
<<= rWinStateInfo
.bNoClose
; break;
534 case PROPERTY_SOFTCLOSE
:
535 pv
.Value
<<= rWinStateInfo
.bSoftClose
; break;
536 case PROPERTY_CONTEXTACTIVE
:
537 pv
.Value
<<= rWinStateInfo
.bContextActive
; break;
538 case PROPERTY_DOCKINGAREA
:
539 pv
.Value
<<= rWinStateInfo
.aDockingArea
; break;
541 pv
.Value
<<= rWinStateInfo
.aPos
; break;
543 pv
.Value
<<= rWinStateInfo
.aSize
; break;
544 case PROPERTY_UINAME
:
545 pv
.Value
<<= rWinStateInfo
.aUIName
; break;
546 case PROPERTY_INTERNALSTATE
:
547 pv
.Value
<<= sal_Int32( rWinStateInfo
.nInternalState
); break;
549 pv
.Value
<<= sal_Int16( rWinStateInfo
.nStyle
); break;
550 case PROPERTY_DOCKPOS
:
551 pv
.Value
<<= rWinStateInfo
.aDockPos
; break;
552 case PROPERTY_DOCKSIZE
:
553 pv
.Value
<<= rWinStateInfo
.aDockSize
; break;
555 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
557 aPropVec
.push_back(pv
);
561 return Any( comphelper::containerToSequence(aPropVec
) );
564 Any
ConfigurationAccess_WindowState::impl_insertCacheAndReturnSequence( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & xNameAccess
)
566 sal_Int32
nMask( 0 );
567 sal_Int32
nCount( m_aPropArray
.size() );
569 std::vector
< PropertyValue
> aPropVec
;
570 WindowStateInfo aWindowStateInfo
;
572 for ( i
= 0; i
< nCount
; i
++ )
576 bool bAddToSeq( false );
577 Any
a( xNameAccess
->getByName( m_aPropArray
[i
] ) );
580 case PROPERTY_LOCKED
:
581 case PROPERTY_DOCKED
:
582 case PROPERTY_VISIBLE
:
583 case PROPERTY_CONTEXT
:
584 case PROPERTY_HIDEFROMMENU
:
585 case PROPERTY_NOCLOSE
:
586 case PROPERTY_SOFTCLOSE
:
587 case PROPERTY_CONTEXTACTIVE
:
592 sal_Int32
nValue( 1 << i
);
597 case PROPERTY_LOCKED
:
598 aWindowStateInfo
.bLocked
= bValue
; break;
599 case PROPERTY_DOCKED
:
600 aWindowStateInfo
.bDocked
= bValue
; break;
601 case PROPERTY_VISIBLE
:
602 aWindowStateInfo
.bVisible
= bValue
; break;
603 case PROPERTY_CONTEXT
:
604 aWindowStateInfo
.bContext
= bValue
; break;
605 case PROPERTY_HIDEFROMMENU
:
606 aWindowStateInfo
.bHideFromMenu
= bValue
; break;
607 case PROPERTY_NOCLOSE
:
608 aWindowStateInfo
.bNoClose
= bValue
; break;
609 case PROPERTY_SOFTCLOSE
:
610 aWindowStateInfo
.bSoftClose
= bValue
; break;
611 case PROPERTY_CONTEXTACTIVE
:
612 aWindowStateInfo
.bContextActive
= bValue
; break;
618 case PROPERTY_DOCKINGAREA
:
620 sal_Int32 nDockingArea
= 0;
621 if ( a
>>= nDockingArea
)
623 if (( nDockingArea
>= 0 ) &&
624 ( nDockingArea
<= sal_Int32( DockingArea_DOCKINGAREA_RIGHT
)))
626 aWindowStateInfo
.aDockingArea
= static_cast<DockingArea
>(nDockingArea
);
627 nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
628 a
<<= aWindowStateInfo
.aDockingArea
;
636 case PROPERTY_DOCKPOS
:
641 sal_Int32
nToken( 0 );
642 std::u16string_view aXStr
= o3tl::getToken(aString
, 0, ',', nToken
);
645 css::awt::Point aPos
;
646 aPos
.X
= o3tl::toInt32(aXStr
);
647 aPos
.Y
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
649 if ( i
== PROPERTY_POS
)
651 aWindowStateInfo
.aPos
= aPos
;
652 nMask
|= WINDOWSTATE_MASK_POS
;
656 aWindowStateInfo
.aDockPos
= aPos
;
657 nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
668 case PROPERTY_DOCKSIZE
:
673 sal_Int32
nToken( 0 );
674 std::u16string_view aStr
= o3tl::getToken(aString
, 0, ',', nToken
);
677 css::awt::Size aSize
;
678 aSize
.Width
= o3tl::toInt32(aStr
);
679 aSize
.Height
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
680 if ( i
== PROPERTY_SIZE
)
682 aWindowStateInfo
.aSize
= aSize
;
683 nMask
|= WINDOWSTATE_MASK_SIZE
;
687 aWindowStateInfo
.aDockSize
= aSize
;
688 nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
698 case PROPERTY_UINAME
:
703 nMask
|= WINDOWSTATE_MASK_UINAME
;
704 aWindowStateInfo
.aUIName
= aValue
;
710 case PROPERTY_INTERNALSTATE
:
712 sal_uInt32 nValue
= 0;
715 nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
716 aWindowStateInfo
.nInternalState
= nValue
;
724 sal_Int32 nValue
= 0;
727 nMask
|= WINDOWSTATE_MASK_STYLE
;
728 aWindowStateInfo
.nStyle
= sal_uInt16( nValue
);
735 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
740 // put value into the return sequence
742 pv
.Name
= m_aPropArray
[i
];
743 pv
.Value
= std::move(a
);
744 aPropVec
.push_back(pv
);
747 catch( const css::container::NoSuchElementException
& )
750 catch ( const css::lang::WrappedTargetException
& )
755 aWindowStateInfo
.nMask
= nMask
;
756 m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWindowStateInfo
);
757 return Any( comphelper::containerToSequence(aPropVec
) );
760 ConfigurationAccess_WindowState::WindowStateInfo
& ConfigurationAccess_WindowState::impl_insertCacheAndReturnWinState( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
)
762 sal_Int32
nMask( 0 );
763 sal_Int32
nCount( m_aPropArray
.size() );
765 WindowStateInfo aWindowStateInfo
;
767 for ( i
= 0; i
< nCount
; i
++ )
771 Any
a( rNameAccess
->getByName( m_aPropArray
[i
] ) );
774 case PROPERTY_LOCKED
:
775 case PROPERTY_DOCKED
:
776 case PROPERTY_VISIBLE
:
777 case PROPERTY_CONTEXT
:
778 case PROPERTY_HIDEFROMMENU
:
779 case PROPERTY_NOCLOSE
:
780 case PROPERTY_SOFTCLOSE
:
781 case PROPERTY_CONTEXTACTIVE
:
786 sal_Int32
nValue( 1 << i
);
790 case PROPERTY_LOCKED
:
791 aWindowStateInfo
.bLocked
= bValue
; break;
792 case PROPERTY_DOCKED
:
793 aWindowStateInfo
.bDocked
= bValue
; break;
794 case PROPERTY_VISIBLE
:
795 aWindowStateInfo
.bVisible
= bValue
; break;
796 case PROPERTY_CONTEXT
:
797 aWindowStateInfo
.bContext
= bValue
; break;
798 case PROPERTY_HIDEFROMMENU
:
799 aWindowStateInfo
.bHideFromMenu
= bValue
; break;
800 case PROPERTY_NOCLOSE
:
801 aWindowStateInfo
.bNoClose
= bValue
; break;
802 case PROPERTY_SOFTCLOSE
:
803 aWindowStateInfo
.bNoClose
= bValue
; break;
804 case PROPERTY_CONTEXTACTIVE
:
805 aWindowStateInfo
.bContextActive
= bValue
; break;
807 SAL_WARN( "fwk.uiconfiguration", "Unknown boolean property in WindowState found!" );
813 case PROPERTY_DOCKINGAREA
:
815 sal_Int32 nDockingArea
= 0;
816 if ( a
>>= nDockingArea
)
818 if (( nDockingArea
>= 0 ) &&
819 ( nDockingArea
<= sal_Int32( DockingArea_DOCKINGAREA_RIGHT
)))
821 aWindowStateInfo
.aDockingArea
= static_cast<DockingArea
>(nDockingArea
);
822 nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
829 case PROPERTY_DOCKPOS
:
834 sal_Int32
nToken( 0 );
835 std::u16string_view aXStr
= o3tl::getToken(aString
, 0, ',', nToken
);
838 css::awt::Point aPos
;
839 aPos
.X
= o3tl::toInt32(aXStr
);
840 aPos
.Y
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
842 if ( i
== PROPERTY_POS
)
844 aWindowStateInfo
.aPos
= aPos
;
845 nMask
|= WINDOWSTATE_MASK_POS
;
849 aWindowStateInfo
.aDockPos
= aPos
;
850 nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
858 case PROPERTY_DOCKSIZE
:
863 sal_Int32
nToken( 0 );
864 std::u16string_view aStr
= o3tl::getToken(aString
, 0, ',', nToken
);
867 css::awt::Size aSize
;
868 aSize
.Width
= o3tl::toInt32(aStr
);
869 aSize
.Height
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
870 if ( i
== PROPERTY_SIZE
)
872 aWindowStateInfo
.aSize
= aSize
;
873 nMask
|= WINDOWSTATE_MASK_SIZE
;
877 aWindowStateInfo
.aDockSize
= aSize
;
878 nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
885 case PROPERTY_UINAME
:
890 nMask
|= WINDOWSTATE_MASK_UINAME
;
891 aWindowStateInfo
.aUIName
= aValue
;
896 case PROPERTY_INTERNALSTATE
:
898 sal_Int32 nValue
= 0;
901 nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
902 aWindowStateInfo
.nInternalState
= sal_uInt32( nValue
);
909 sal_Int32 nValue
= 0;
912 nMask
|= WINDOWSTATE_MASK_STYLE
;
913 aWindowStateInfo
.nStyle
= sal_uInt16( nValue
);
919 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
922 catch( const css::container::NoSuchElementException
& )
925 catch ( const css::lang::WrappedTargetException
& )
930 aWindowStateInfo
.nMask
= nMask
;
931 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWindowStateInfo
).first
;
932 return pIter
->second
;
935 Any
ConfigurationAccess_WindowState::impl_getWindowStateFromResourceURL( const OUString
& rResourceURL
)
937 if ( !m_bConfigAccessInitialized
)
939 impl_initializeConfigAccess();
940 m_bConfigAccessInitialized
= true;
945 // Try to ask our configuration access
946 if ( m_xConfigAccess
.is() && m_xConfigAccess
->hasByName( rResourceURL
) )
949 Reference
< XNameAccess
> xNameAccess( m_xConfigAccess
->getByName( rResourceURL
), UNO_QUERY
);
950 if ( xNameAccess
.is() )
951 return impl_insertCacheAndReturnSequence( rResourceURL
, xNameAccess
);
954 catch( const css::container::NoSuchElementException
& )
957 catch ( const css::lang::WrappedTargetException
& )
964 void ConfigurationAccess_WindowState::impl_fillStructFromSequence( WindowStateInfo
& rWinStateInfo
, const Sequence
< PropertyValue
>& rSeq
)
966 sal_Int32
nCompareCount( m_aPropArray
.size() );
967 sal_Int32
nCount( rSeq
.getLength() );
970 for ( i
= 0; i
< nCount
; i
++ )
972 for ( sal_Int32 j
= 0; j
< nCompareCount
; j
++ )
974 if ( rSeq
[i
].Name
== m_aPropArray
[j
] )
978 case PROPERTY_LOCKED
:
979 case PROPERTY_DOCKED
:
980 case PROPERTY_VISIBLE
:
981 case PROPERTY_CONTEXT
:
982 case PROPERTY_HIDEFROMMENU
:
983 case PROPERTY_NOCLOSE
:
984 case PROPERTY_SOFTCLOSE
:
985 case PROPERTY_CONTEXTACTIVE
:
988 if ( rSeq
[i
].Value
>>= bValue
)
990 sal_Int32
nValue( 1 << j
);
991 rWinStateInfo
.nMask
|= nValue
;
994 case PROPERTY_LOCKED
:
995 rWinStateInfo
.bLocked
= bValue
;
997 case PROPERTY_DOCKED
:
998 rWinStateInfo
.bDocked
= bValue
;
1000 case PROPERTY_VISIBLE
:
1001 rWinStateInfo
.bVisible
= bValue
;
1003 case PROPERTY_CONTEXT
:
1004 rWinStateInfo
.bContext
= bValue
;
1006 case PROPERTY_HIDEFROMMENU
:
1007 rWinStateInfo
.bHideFromMenu
= bValue
;
1009 case PROPERTY_NOCLOSE
:
1010 rWinStateInfo
.bNoClose
= bValue
;
1012 case PROPERTY_SOFTCLOSE
:
1013 rWinStateInfo
.bSoftClose
= bValue
;
1015 case PROPERTY_CONTEXTACTIVE
:
1016 rWinStateInfo
.bContextActive
= bValue
;
1023 case PROPERTY_DOCKINGAREA
:
1025 css::ui::DockingArea eDockingArea
;
1026 if ( rSeq
[i
].Value
>>= eDockingArea
)
1028 rWinStateInfo
.aDockingArea
= eDockingArea
;
1029 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
1035 case PROPERTY_DOCKPOS
:
1037 css::awt::Point aPoint
;
1038 if ( rSeq
[i
].Value
>>= aPoint
)
1040 if ( j
== PROPERTY_POS
)
1042 rWinStateInfo
.aPos
= aPoint
;
1043 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_POS
;
1047 rWinStateInfo
.aDockPos
= aPoint
;
1048 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
1055 case PROPERTY_DOCKSIZE
:
1057 css::awt::Size aSize
;
1058 if ( rSeq
[i
].Value
>>= aSize
)
1060 if ( j
== PROPERTY_SIZE
)
1062 rWinStateInfo
.aSize
= aSize
;
1063 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_SIZE
;
1067 rWinStateInfo
.aDockSize
= aSize
;
1068 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
1074 case PROPERTY_UINAME
:
1077 if ( rSeq
[i
].Value
>>= aValue
)
1079 rWinStateInfo
.aUIName
= aValue
;
1080 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_UINAME
;
1085 case PROPERTY_INTERNALSTATE
:
1087 sal_Int32 nValue
= 0;
1088 if ( rSeq
[i
].Value
>>= nValue
)
1090 rWinStateInfo
.nInternalState
= sal_uInt32( nValue
);
1091 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
1096 case PROPERTY_STYLE
:
1098 sal_Int32 nValue
= 0;
1099 if ( rSeq
[i
].Value
>>= nValue
)
1101 rWinStateInfo
.nStyle
= sal_uInt16( nValue
);
1102 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_STYLE
;
1108 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
1117 void ConfigurationAccess_WindowState::impl_putPropertiesFromStruct( const WindowStateInfo
& rWinStateInfo
, Reference
< XPropertySet
> const & xPropSet
)
1120 sal_Int32
nCount( m_aPropArray
.size() );
1121 OUString
aDelim( u
","_ustr
);
1123 for ( i
= 0; i
< nCount
; i
++ )
1125 if ( rWinStateInfo
.nMask
& ( 1 << i
))
1129 // put values into the property set
1132 case PROPERTY_LOCKED
:
1133 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bLocked
) ); break;
1134 case PROPERTY_DOCKED
:
1135 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bDocked
) ); break;
1136 case PROPERTY_VISIBLE
:
1137 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bVisible
) ); break;
1138 case PROPERTY_CONTEXT
:
1139 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bContext
) ); break;
1140 case PROPERTY_HIDEFROMMENU
:
1141 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bHideFromMenu
) ); break;
1142 case PROPERTY_NOCLOSE
:
1143 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bNoClose
) ); break;
1144 case PROPERTY_SOFTCLOSE
:
1145 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bSoftClose
) ); break;
1146 case PROPERTY_CONTEXTACTIVE
:
1147 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bContextActive
) ); break;
1148 case PROPERTY_DOCKINGAREA
:
1149 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int16( rWinStateInfo
.aDockingArea
) ) ); break;
1151 case PROPERTY_DOCKPOS
:
1154 if ( i
== PROPERTY_POS
)
1155 aPosStr
= OUString::number( rWinStateInfo
.aPos
.X
);
1157 aPosStr
= OUString::number( rWinStateInfo
.aDockPos
.X
);
1159 if ( i
== PROPERTY_POS
)
1160 aPosStr
+= OUString::number( rWinStateInfo
.aPos
.Y
);
1162 aPosStr
+= OUString::number( rWinStateInfo
.aDockPos
.Y
);
1163 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( aPosStr
) );
1167 case PROPERTY_DOCKSIZE
:
1170 if ( i
== PROPERTY_SIZE
)
1171 aSizeStr
= OUString::number( rWinStateInfo
.aSize
.Width
);
1173 aSizeStr
= OUString::number( rWinStateInfo
.aDockSize
.Width
);
1175 if ( i
== PROPERTY_SIZE
)
1176 aSizeStr
+= OUString::number( rWinStateInfo
.aSize
.Height
);
1178 aSizeStr
+= OUString::number( rWinStateInfo
.aDockSize
.Height
);
1179 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( aSizeStr
) );
1182 case PROPERTY_UINAME
:
1183 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.aUIName
) ); break;
1184 case PROPERTY_INTERNALSTATE
:
1185 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int32( rWinStateInfo
.nInternalState
)) ); break;
1186 case PROPERTY_STYLE
:
1187 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int32( rWinStateInfo
.nStyle
)) ); break;
1189 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
1192 catch( const Exception
& )
1199 void ConfigurationAccess_WindowState::impl_initializeConfigAccess()
1203 Sequence
<Any
> aArgs(comphelper::InitAnyPropertySequence(
1205 {"nodepath", Any(m_aConfigWindowAccess
)}
1207 m_xConfigAccess
.set( m_xConfigProvider
->createInstanceWithArguments(
1208 u
"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr
, aArgs
), UNO_QUERY
);
1209 if ( m_xConfigAccess
.is() )
1211 // Add as container listener
1212 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
1213 if ( xContainer
.is() )
1215 m_xConfigListener
= new WeakContainerListener(this);
1216 xContainer
->addContainerListener(m_xConfigListener
);
1220 catch ( const WrappedTargetException
& )
1223 catch ( const Exception
& )
1228 typedef comphelper::WeakComponentImplHelper
< css::container::XNameAccess
,
1229 css::lang::XServiceInfo
> WindowStateConfiguration_BASE
;
1231 class WindowStateConfiguration
: public WindowStateConfiguration_BASE
1234 explicit WindowStateConfiguration( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
1235 virtual ~WindowStateConfiguration() override
;
1237 virtual OUString SAL_CALL
getImplementationName() override
1239 return u
"com.sun.star.comp.framework.WindowStateConfiguration"_ustr
;
1242 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
1244 return cppu::supportsService(this, ServiceName
);
1247 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
1249 return {u
"com.sun.star.ui.WindowStateConfiguration"_ustr
};
1253 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
1255 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames() override
;
1257 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
1260 virtual css::uno::Type SAL_CALL
getElementType() override
;
1261 virtual sal_Bool SAL_CALL
hasElements() override
;
1263 typedef std::unordered_map
< OUString
,
1264 OUString
> ModuleToWindowStateFileMap
;
1266 typedef std::unordered_map
< OUString
,
1267 css::uno::Reference
< css::container::XNameAccess
> > ModuleToWindowStateConfigHashMap
;
1270 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
1271 ModuleToWindowStateFileMap m_aModuleToFileHashMap
;
1272 ModuleToWindowStateConfigHashMap m_aModuleToWindowStateHashMap
;
1275 WindowStateConfiguration::WindowStateConfiguration( const Reference
< XComponentContext
>& rxContext
) :
1276 m_xContext( rxContext
)
1278 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager
=
1279 ModuleManager::create( m_xContext
);
1280 Reference
< XNameAccess
> xEmptyNameAccess
;
1281 Sequence
< OUString
> aElementNames
;
1284 aElementNames
= xModuleManager
->getElementNames();
1286 catch (const css::uno::RuntimeException
&)
1289 Sequence
< PropertyValue
> aSeq
;
1291 for (OUString
const& aModuleIdentifier
: aElementNames
)
1293 if ( xModuleManager
->getByName( aModuleIdentifier
) >>= aSeq
)
1295 OUString aWindowStateFileStr
;
1296 for (PropertyValue
const& rProp
: aSeq
)
1298 if ( rProp
.Name
== "ooSetupFactoryWindowStateConfigRef" )
1300 rProp
.Value
>>= aWindowStateFileStr
;
1305 if ( !aWindowStateFileStr
.isEmpty() )
1307 // Create first mapping ModuleIdentifier ==> Window state configuration file
1308 m_aModuleToFileHashMap
.emplace( aModuleIdentifier
, aWindowStateFileStr
);
1310 // Create second mapping Command File ==> Window state configuration instance
1311 ModuleToWindowStateConfigHashMap::iterator pIter
= m_aModuleToWindowStateHashMap
.find( aWindowStateFileStr
);
1312 if ( pIter
== m_aModuleToWindowStateHashMap
.end() )
1313 m_aModuleToWindowStateHashMap
.emplace( aWindowStateFileStr
, xEmptyNameAccess
);
1319 WindowStateConfiguration::~WindowStateConfiguration()
1321 std::unique_lock
g(m_aMutex
);
1322 m_aModuleToFileHashMap
.clear();
1323 m_aModuleToWindowStateHashMap
.clear();
1326 Any SAL_CALL
WindowStateConfiguration::getByName( const OUString
& aModuleIdentifier
)
1328 std::unique_lock
g(m_aMutex
);
1330 ModuleToWindowStateFileMap::const_iterator pIter
= m_aModuleToFileHashMap
.find( aModuleIdentifier
);
1331 if ( pIter
!= m_aModuleToFileHashMap
.end() )
1334 OUString
aWindowStateConfigFile( pIter
->second
);
1336 ModuleToWindowStateConfigHashMap::iterator pModuleIter
= m_aModuleToWindowStateHashMap
.find( aWindowStateConfigFile
);
1337 if ( pModuleIter
!= m_aModuleToWindowStateHashMap
.end() )
1339 if ( pModuleIter
->second
.is() )
1340 a
<<= pModuleIter
->second
;
1343 Reference
< XNameAccess
> xResourceURLWindowState
= new ConfigurationAccess_WindowState( aWindowStateConfigFile
, m_xContext
);
1344 pModuleIter
->second
= xResourceURLWindowState
;
1345 a
<<= xResourceURLWindowState
;
1352 throw NoSuchElementException();
1355 Sequence
< OUString
> SAL_CALL
WindowStateConfiguration::getElementNames()
1357 std::unique_lock
g(m_aMutex
);
1359 return comphelper::mapKeysToSequence( m_aModuleToFileHashMap
);
1362 sal_Bool SAL_CALL
WindowStateConfiguration::hasByName( const OUString
& aName
)
1364 std::unique_lock
g(m_aMutex
);
1366 ModuleToWindowStateFileMap::const_iterator pIter
= m_aModuleToFileHashMap
.find( aName
);
1367 return ( pIter
!= m_aModuleToFileHashMap
.end() );
1371 Type SAL_CALL
WindowStateConfiguration::getElementType()
1373 return cppu::UnoType
<XNameAccess
>::get();
1376 sal_Bool SAL_CALL
WindowStateConfiguration::hasElements()
1378 // We always have at least one module. So it is valid to return true!
1384 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1385 com_sun_star_comp_framework_WindowStateConfiguration_get_implementation(
1386 css::uno::XComponentContext
*context
,
1387 css::uno::Sequence
<css::uno::Any
> const &)
1389 return cppu::acquire(new WindowStateConfiguration(context
));
1392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */