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 <sal/log.hxx>
46 #include <o3tl/string_view.hxx>
49 #include <string_view>
50 #include <unordered_map>
53 using namespace com::sun::star::uno
;
54 using namespace com::sun::star::lang
;
55 using namespace com::sun::star::beans
;
56 using namespace com::sun::star::util
;
57 using namespace com::sun::star::configuration
;
58 using namespace com::sun::star::container
;
59 using namespace ::com::sun::star::frame
;
60 using namespace ::com::sun::star::ui
;
61 using namespace framework
;
65 // Zero based indexes, order must be the same as WindowStateMask && CONFIGURATION_PROPERTIES!
66 const sal_Int16 PROPERTY_LOCKED
= 0;
67 const sal_Int16 PROPERTY_DOCKED
= 1;
68 const sal_Int16 PROPERTY_VISIBLE
= 2;
69 const sal_Int16 PROPERTY_CONTEXT
= 3;
70 const sal_Int16 PROPERTY_HIDEFROMMENU
= 4;
71 const sal_Int16 PROPERTY_NOCLOSE
= 5;
72 const sal_Int16 PROPERTY_SOFTCLOSE
= 6;
73 const sal_Int16 PROPERTY_CONTEXTACTIVE
= 7;
74 const sal_Int16 PROPERTY_DOCKINGAREA
= 8;
75 const sal_Int16 PROPERTY_POS
= 9;
76 const sal_Int16 PROPERTY_SIZE
= 10;
77 const sal_Int16 PROPERTY_UINAME
= 11;
78 const sal_Int16 PROPERTY_INTERNALSTATE
= 12;
79 const sal_Int16 PROPERTY_STYLE
= 13;
80 const sal_Int16 PROPERTY_DOCKPOS
= 14;
81 const sal_Int16 PROPERTY_DOCKSIZE
= 15;
83 // Order must be the same as WindowStateMask!!
84 constexpr OUString CONFIGURATION_PROPERTIES
[]
86 WINDOWSTATE_PROPERTY_LOCKED
,
87 WINDOWSTATE_PROPERTY_DOCKED
,
88 WINDOWSTATE_PROPERTY_VISIBLE
,
89 WINDOWSTATE_PROPERTY_CONTEXT
,
90 WINDOWSTATE_PROPERTY_HIDEFROMENU
,
91 WINDOWSTATE_PROPERTY_NOCLOSE
,
92 WINDOWSTATE_PROPERTY_SOFTCLOSE
,
93 WINDOWSTATE_PROPERTY_CONTEXTACTIVE
,
94 WINDOWSTATE_PROPERTY_DOCKINGAREA
,
95 WINDOWSTATE_PROPERTY_POS
,
96 WINDOWSTATE_PROPERTY_SIZE
,
97 WINDOWSTATE_PROPERTY_UINAME
,
98 WINDOWSTATE_PROPERTY_INTERNALSTATE
,
99 WINDOWSTATE_PROPERTY_STYLE
,
100 WINDOWSTATE_PROPERTY_DOCKPOS
,
101 WINDOWSTATE_PROPERTY_DOCKSIZE
104 // Configuration access class for WindowState supplier implementation
106 class ConfigurationAccess_WindowState
: public ::cppu::WeakImplHelper
< XNameContainer
, XContainerListener
>
109 ConfigurationAccess_WindowState( std::u16string_view aWindowStateConfigFile
, const Reference
< XComponentContext
>& rxContext
);
110 virtual ~ConfigurationAccess_WindowState() override
;
113 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
115 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames() override
;
117 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
120 virtual void SAL_CALL
removeByName( const OUString
& sName
) override
;
122 virtual void SAL_CALL
insertByName( const OUString
& sName
, const css::uno::Any
& aPropertySet
) override
;
125 virtual void SAL_CALL
replaceByName( const OUString
& sName
, const css::uno::Any
& aPropertySet
) override
;
128 virtual css::uno::Type SAL_CALL
getElementType() override
;
130 virtual sal_Bool SAL_CALL
hasElements() override
;
132 // container.XContainerListener
133 virtual void SAL_CALL
elementInserted( const ContainerEvent
& aEvent
) override
;
134 virtual void SAL_CALL
elementRemoved ( const ContainerEvent
& aEvent
) override
;
135 virtual void SAL_CALL
elementReplaced( const ContainerEvent
& aEvent
) override
;
137 // lang.XEventListener
138 virtual void SAL_CALL
disposing( const EventObject
& aEvent
) override
;
141 enum // WindowStateMask
143 WINDOWSTATE_MASK_DOCKINGAREA
= 256,
144 WINDOWSTATE_MASK_POS
= 512,
145 WINDOWSTATE_MASK_SIZE
= 1024,
146 WINDOWSTATE_MASK_UINAME
= 2048,
147 WINDOWSTATE_MASK_INTERNALSTATE
= 4096,
148 WINDOWSTATE_MASK_STYLE
= 8192,
149 WINDOWSTATE_MASK_DOCKPOS
= 16384,
150 WINDOWSTATE_MASK_DOCKSIZE
= 32768
153 // Cache structure. Valid values are described by the eMask member. All other values should not be
154 // provided to outside code!
155 struct WindowStateInfo
162 , bHideFromMenu(false)
165 , bContextActive(false)
166 , aDockingArea(css::ui::DockingArea_DOCKINGAREA_TOP
)
184 css::ui::DockingArea aDockingArea
;
185 css::awt::Point aDockPos
;
186 css::awt::Size aDockSize
;
187 css::awt::Point aPos
;
188 css::awt::Size aSize
;
190 sal_uInt32 nInternalState
;
192 sal_uInt32 nMask
; // see WindowStateMask
195 void impl_putPropertiesFromStruct( const WindowStateInfo
& rWinStateInfo
, Reference
< XPropertySet
> const & xPropSet
);
196 Any
impl_insertCacheAndReturnSequence( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
);
197 WindowStateInfo
& impl_insertCacheAndReturnWinState( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
);
198 Any
impl_getSequenceFromStruct( const WindowStateInfo
& rWinStateInfo
);
199 void impl_fillStructFromSequence( WindowStateInfo
& rWinStateInfo
, const Sequence
< PropertyValue
>& rSeq
);
200 Any
impl_getWindowStateFromResourceURL( const OUString
& rResourceURL
);
201 void impl_initializeConfigAccess();
204 typedef std::unordered_map
< OUString
,
205 WindowStateInfo
> ResourceURLToInfoCache
;
208 OUString m_aConfigWindowAccess
;
209 Reference
< XMultiServiceFactory
> m_xConfigProvider
;
210 Reference
< XNameAccess
> m_xConfigAccess
;
211 Reference
< XContainerListener
> m_xConfigListener
;
212 ResourceURLToInfoCache m_aResourceURLToInfoCache
;
213 bool m_bConfigAccessInitialized
: 1,
215 std::vector
< OUString
> m_aPropArray
;
218 ConfigurationAccess_WindowState::ConfigurationAccess_WindowState( std::u16string_view aModuleName
, const Reference
< XComponentContext
>& rxContext
) :
219 // Create configuration hierarchical access name
220 m_aConfigWindowAccess(
221 OUString::Concat("/org.openoffice.Office.UI.") + aModuleName
+ "/UIElements/States"),
222 m_xConfigProvider(theDefaultProvider::get( rxContext
)),
223 m_bConfigAccessInitialized( false ),
226 // Initialize access array with property names.
227 for (const OUString
& s
: CONFIGURATION_PROPERTIES
)
228 m_aPropArray
.push_back(s
);
231 ConfigurationAccess_WindowState::~ConfigurationAccess_WindowState()
234 std::unique_lock
g(m_aMutex
);
235 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
236 if ( xContainer
.is() )
237 xContainer
->removeContainerListener(m_xConfigListener
);
241 Any SAL_CALL
ConfigurationAccess_WindowState::getByName( const OUString
& rResourceURL
)
244 std::unique_lock
g(m_aMutex
);
246 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
247 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
248 return impl_getSequenceFromStruct( pIter
->second
);
251 Any
a( impl_getWindowStateFromResourceURL( rResourceURL
) );
253 throw NoSuchElementException();
258 Sequence
< OUString
> SAL_CALL
ConfigurationAccess_WindowState::getElementNames()
261 std::unique_lock
g(m_aMutex
);
263 if ( !m_bConfigAccessInitialized
)
265 impl_initializeConfigAccess();
266 m_bConfigAccessInitialized
= true;
269 if ( m_xConfigAccess
.is() )
270 return m_xConfigAccess
->getElementNames();
272 return Sequence
< OUString
> ();
275 sal_Bool SAL_CALL
ConfigurationAccess_WindowState::hasByName( const OUString
& rResourceURL
)
278 std::unique_lock
g(m_aMutex
);
280 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
281 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
285 Any
a( impl_getWindowStateFromResourceURL( rResourceURL
) );
294 Type SAL_CALL
ConfigurationAccess_WindowState::getElementType()
296 return cppu::UnoType
<Sequence
< PropertyValue
>>::get();
299 sal_Bool SAL_CALL
ConfigurationAccess_WindowState::hasElements()
302 std::unique_lock
g(m_aMutex
);
304 if ( !m_bConfigAccessInitialized
)
306 impl_initializeConfigAccess();
307 m_bConfigAccessInitialized
= true;
310 if ( m_xConfigAccess
.is() )
311 return m_xConfigAccess
->hasElements();
317 void SAL_CALL
ConfigurationAccess_WindowState::removeByName( const OUString
& rResourceURL
)
320 std::unique_lock
g(m_aMutex
);
322 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
323 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
324 m_aResourceURLToInfoCache
.erase( pIter
);
326 if ( !m_bConfigAccessInitialized
)
328 impl_initializeConfigAccess();
329 m_bConfigAccessInitialized
= true;
334 // Remove must be write-through => remove element from configuration
335 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
336 if ( xNameContainer
.is() )
340 xNameContainer
->removeByName( rResourceURL
);
341 Reference
< XChangesBatch
> xFlush( m_xConfigAccess
, UNO_QUERY
);
343 xFlush
->commitChanges();
346 catch ( const css::lang::WrappedTargetException
& )
351 void SAL_CALL
ConfigurationAccess_WindowState::insertByName( const OUString
& rResourceURL
, const css::uno::Any
& aPropertySet
)
354 std::unique_lock
g(m_aMutex
);
356 Sequence
< PropertyValue
> aPropSet
;
357 if ( !(aPropertySet
>>= aPropSet
) )
358 throw IllegalArgumentException();
360 ResourceURLToInfoCache::const_iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
361 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
362 throw ElementExistException();
364 if ( !m_bConfigAccessInitialized
)
366 impl_initializeConfigAccess();
367 m_bConfigAccessInitialized
= true;
370 // Try to ask our configuration access
371 if ( !m_xConfigAccess
.is() )
374 if ( m_xConfigAccess
->hasByName( rResourceURL
) )
375 throw ElementExistException();
377 WindowStateInfo aWinStateInfo
;
378 impl_fillStructFromSequence( aWinStateInfo
, aPropSet
);
379 m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWinStateInfo
);
381 // insert must be write-through => insert element into configuration
382 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
383 if ( !xNameContainer
.is() )
386 Reference
< XSingleServiceFactory
> xFactory( m_xConfigAccess
, UNO_QUERY
);
391 Reference
< XPropertySet
> xPropSet( xFactory
->createInstance(), UNO_QUERY
);
395 impl_putPropertiesFromStruct( aWinStateInfo
, xPropSet
);
397 xNameContainer
->insertByName( rResourceURL
, a
);
398 Reference
< XChangesBatch
> xFlush( xFactory
, UNO_QUERY
);
400 xFlush
->commitChanges();
403 catch ( const Exception
& )
409 void SAL_CALL
ConfigurationAccess_WindowState::replaceByName( const OUString
& rResourceURL
, const css::uno::Any
& aPropertySet
)
412 std::unique_lock
g(m_aMutex
);
414 Sequence
< PropertyValue
> aPropSet
;
415 if ( !(aPropertySet
>>= aPropSet
) )
416 throw IllegalArgumentException();
418 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
419 if ( pIter
!= m_aResourceURLToInfoCache
.end() )
421 WindowStateInfo
& rWinStateInfo
= pIter
->second
;
422 impl_fillStructFromSequence( rWinStateInfo
, aPropSet
);
427 if ( !m_bConfigAccessInitialized
)
429 impl_initializeConfigAccess();
430 m_bConfigAccessInitialized
= true;
433 // Try to ask our configuration access
434 Reference
< XNameAccess
> xNameAccess
;
435 Any
a( m_xConfigAccess
->getByName( rResourceURL
));
437 if ( !(a
>>= xNameAccess
) )
438 throw NoSuchElementException();
440 WindowStateInfo
& rWinStateInfo( impl_insertCacheAndReturnWinState( rResourceURL
, xNameAccess
));
441 impl_fillStructFromSequence( rWinStateInfo
, aPropSet
);
443 pIter
= m_aResourceURLToInfoCache
.find( rResourceURL
);
447 if ( !(m_bModified
&& pIter
!= m_aResourceURLToInfoCache
.end()) )
450 Reference
< XNameContainer
> xNameContainer( m_xConfigAccess
, UNO_QUERY
);
451 if ( !xNameContainer
.is() )
454 WindowStateInfo
aWinStateInfo( pIter
->second
);
455 OUString
aResourceURL( pIter
->first
);
461 Reference
< XPropertySet
> xPropSet
;
462 if ( xNameContainer
->getByName( aResourceURL
) >>= xPropSet
)
464 impl_putPropertiesFromStruct( aWinStateInfo
, xPropSet
);
466 Reference
< XChangesBatch
> xFlush( m_xConfigAccess
, UNO_QUERY
);
468 xFlush
->commitChanges();
471 catch ( const Exception
& )
477 // container.XContainerListener
478 void SAL_CALL
ConfigurationAccess_WindowState::elementInserted( const ContainerEvent
& )
480 // do nothing - next time someone wants to retrieve this node we will find it in the configuration
483 void SAL_CALL
ConfigurationAccess_WindowState::elementRemoved ( const ContainerEvent
& )
487 void SAL_CALL
ConfigurationAccess_WindowState::elementReplaced( const ContainerEvent
& )
491 // lang.XEventListener
492 void SAL_CALL
ConfigurationAccess_WindowState::disposing( const EventObject
& aEvent
)
495 // remove our reference to the config access
496 std::unique_lock
g(m_aMutex
);
498 Reference
< XInterface
> xIfac1( aEvent
.Source
, UNO_QUERY
);
499 Reference
< XInterface
> xIfac2( m_xConfigAccess
, UNO_QUERY
);
500 if ( xIfac1
== xIfac2
)
501 m_xConfigAccess
.clear();
504 // private helper methods
505 Any
ConfigurationAccess_WindowState::impl_getSequenceFromStruct( const WindowStateInfo
& rWinStateInfo
)
508 sal_Int32
nCount( m_aPropArray
.size() );
509 std::vector
< PropertyValue
> aPropVec
;
511 for ( i
= 0; i
< nCount
; i
++ )
513 if ( rWinStateInfo
.nMask
& ( 1 << i
))
515 // put value into the return sequence
517 pv
.Name
= m_aPropArray
[i
];
521 case PROPERTY_LOCKED
:
522 pv
.Value
<<= rWinStateInfo
.bLocked
; break;
523 case PROPERTY_DOCKED
:
524 pv
.Value
<<= rWinStateInfo
.bDocked
; break;
525 case PROPERTY_VISIBLE
:
526 pv
.Value
<<= rWinStateInfo
.bVisible
; break;
527 case PROPERTY_CONTEXT
:
528 pv
.Value
<<= rWinStateInfo
.bContext
; break;
529 case PROPERTY_HIDEFROMMENU
:
530 pv
.Value
<<= rWinStateInfo
.bHideFromMenu
; break;
531 case PROPERTY_NOCLOSE
:
532 pv
.Value
<<= rWinStateInfo
.bNoClose
; break;
533 case PROPERTY_SOFTCLOSE
:
534 pv
.Value
<<= rWinStateInfo
.bSoftClose
; break;
535 case PROPERTY_CONTEXTACTIVE
:
536 pv
.Value
<<= rWinStateInfo
.bContextActive
; break;
537 case PROPERTY_DOCKINGAREA
:
538 pv
.Value
<<= rWinStateInfo
.aDockingArea
; break;
540 pv
.Value
<<= rWinStateInfo
.aPos
; break;
542 pv
.Value
<<= rWinStateInfo
.aSize
; break;
543 case PROPERTY_UINAME
:
544 pv
.Value
<<= rWinStateInfo
.aUIName
; break;
545 case PROPERTY_INTERNALSTATE
:
546 pv
.Value
<<= sal_Int32( rWinStateInfo
.nInternalState
); break;
548 pv
.Value
<<= sal_Int16( rWinStateInfo
.nStyle
); break;
549 case PROPERTY_DOCKPOS
:
550 pv
.Value
<<= rWinStateInfo
.aDockPos
; break;
551 case PROPERTY_DOCKSIZE
:
552 pv
.Value
<<= rWinStateInfo
.aDockSize
; break;
554 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
556 aPropVec
.push_back(pv
);
560 return Any( comphelper::containerToSequence(aPropVec
) );
563 Any
ConfigurationAccess_WindowState::impl_insertCacheAndReturnSequence( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & xNameAccess
)
565 sal_Int32
nMask( 0 );
566 sal_Int32
nCount( m_aPropArray
.size() );
568 std::vector
< PropertyValue
> aPropVec
;
569 WindowStateInfo aWindowStateInfo
;
571 for ( i
= 0; i
< nCount
; i
++ )
575 bool bAddToSeq( false );
576 Any
a( xNameAccess
->getByName( m_aPropArray
[i
] ) );
579 case PROPERTY_LOCKED
:
580 case PROPERTY_DOCKED
:
581 case PROPERTY_VISIBLE
:
582 case PROPERTY_CONTEXT
:
583 case PROPERTY_HIDEFROMMENU
:
584 case PROPERTY_NOCLOSE
:
585 case PROPERTY_SOFTCLOSE
:
586 case PROPERTY_CONTEXTACTIVE
:
591 sal_Int32
nValue( 1 << i
);
596 case PROPERTY_LOCKED
:
597 aWindowStateInfo
.bLocked
= bValue
; break;
598 case PROPERTY_DOCKED
:
599 aWindowStateInfo
.bDocked
= bValue
; break;
600 case PROPERTY_VISIBLE
:
601 aWindowStateInfo
.bVisible
= bValue
; break;
602 case PROPERTY_CONTEXT
:
603 aWindowStateInfo
.bContext
= bValue
; break;
604 case PROPERTY_HIDEFROMMENU
:
605 aWindowStateInfo
.bHideFromMenu
= bValue
; break;
606 case PROPERTY_NOCLOSE
:
607 aWindowStateInfo
.bNoClose
= bValue
; break;
608 case PROPERTY_SOFTCLOSE
:
609 aWindowStateInfo
.bSoftClose
= bValue
; break;
610 case PROPERTY_CONTEXTACTIVE
:
611 aWindowStateInfo
.bContextActive
= bValue
; break;
617 case PROPERTY_DOCKINGAREA
:
619 sal_Int32 nDockingArea
= 0;
620 if ( a
>>= nDockingArea
)
622 if (( nDockingArea
>= 0 ) &&
623 ( nDockingArea
<= sal_Int32( DockingArea_DOCKINGAREA_RIGHT
)))
625 aWindowStateInfo
.aDockingArea
= static_cast<DockingArea
>(nDockingArea
);
626 nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
627 a
<<= aWindowStateInfo
.aDockingArea
;
635 case PROPERTY_DOCKPOS
:
640 sal_Int32
nToken( 0 );
641 std::u16string_view aXStr
= o3tl::getToken(aString
, 0, ',', nToken
);
644 css::awt::Point aPos
;
645 aPos
.X
= o3tl::toInt32(aXStr
);
646 aPos
.Y
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
648 if ( i
== PROPERTY_POS
)
650 aWindowStateInfo
.aPos
= aPos
;
651 nMask
|= WINDOWSTATE_MASK_POS
;
655 aWindowStateInfo
.aDockPos
= aPos
;
656 nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
667 case PROPERTY_DOCKSIZE
:
672 sal_Int32
nToken( 0 );
673 std::u16string_view aStr
= o3tl::getToken(aString
, 0, ',', nToken
);
676 css::awt::Size aSize
;
677 aSize
.Width
= o3tl::toInt32(aStr
);
678 aSize
.Height
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
679 if ( i
== PROPERTY_SIZE
)
681 aWindowStateInfo
.aSize
= aSize
;
682 nMask
|= WINDOWSTATE_MASK_SIZE
;
686 aWindowStateInfo
.aDockSize
= aSize
;
687 nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
697 case PROPERTY_UINAME
:
702 nMask
|= WINDOWSTATE_MASK_UINAME
;
703 aWindowStateInfo
.aUIName
= aValue
;
709 case PROPERTY_INTERNALSTATE
:
711 sal_uInt32 nValue
= 0;
714 nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
715 aWindowStateInfo
.nInternalState
= nValue
;
723 sal_Int32 nValue
= 0;
726 nMask
|= WINDOWSTATE_MASK_STYLE
;
727 aWindowStateInfo
.nStyle
= sal_uInt16( nValue
);
734 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
739 // put value into the return sequence
741 pv
.Name
= m_aPropArray
[i
];
743 aPropVec
.push_back(pv
);
746 catch( const css::container::NoSuchElementException
& )
749 catch ( const css::lang::WrappedTargetException
& )
754 aWindowStateInfo
.nMask
= nMask
;
755 m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWindowStateInfo
);
756 return Any( comphelper::containerToSequence(aPropVec
) );
759 ConfigurationAccess_WindowState::WindowStateInfo
& ConfigurationAccess_WindowState::impl_insertCacheAndReturnWinState( const OUString
& rResourceURL
, Reference
< XNameAccess
> const & rNameAccess
)
761 sal_Int32
nMask( 0 );
762 sal_Int32
nCount( m_aPropArray
.size() );
764 WindowStateInfo aWindowStateInfo
;
766 for ( i
= 0; i
< nCount
; i
++ )
770 Any
a( rNameAccess
->getByName( m_aPropArray
[i
] ) );
773 case PROPERTY_LOCKED
:
774 case PROPERTY_DOCKED
:
775 case PROPERTY_VISIBLE
:
776 case PROPERTY_CONTEXT
:
777 case PROPERTY_HIDEFROMMENU
:
778 case PROPERTY_NOCLOSE
:
779 case PROPERTY_SOFTCLOSE
:
780 case PROPERTY_CONTEXTACTIVE
:
785 sal_Int32
nValue( 1 << i
);
789 case PROPERTY_LOCKED
:
790 aWindowStateInfo
.bLocked
= bValue
; break;
791 case PROPERTY_DOCKED
:
792 aWindowStateInfo
.bDocked
= bValue
; break;
793 case PROPERTY_VISIBLE
:
794 aWindowStateInfo
.bVisible
= bValue
; break;
795 case PROPERTY_CONTEXT
:
796 aWindowStateInfo
.bContext
= bValue
; break;
797 case PROPERTY_HIDEFROMMENU
:
798 aWindowStateInfo
.bHideFromMenu
= bValue
; break;
799 case PROPERTY_NOCLOSE
:
800 aWindowStateInfo
.bNoClose
= bValue
; break;
801 case PROPERTY_SOFTCLOSE
:
802 aWindowStateInfo
.bNoClose
= bValue
; break;
803 case PROPERTY_CONTEXTACTIVE
:
804 aWindowStateInfo
.bContextActive
= bValue
; break;
806 SAL_WARN( "fwk.uiconfiguration", "Unknown boolean property in WindowState found!" );
812 case PROPERTY_DOCKINGAREA
:
814 sal_Int32 nDockingArea
= 0;
815 if ( a
>>= nDockingArea
)
817 if (( nDockingArea
>= 0 ) &&
818 ( nDockingArea
<= sal_Int32( DockingArea_DOCKINGAREA_RIGHT
)))
820 aWindowStateInfo
.aDockingArea
= static_cast<DockingArea
>(nDockingArea
);
821 nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
828 case PROPERTY_DOCKPOS
:
833 sal_Int32
nToken( 0 );
834 std::u16string_view aXStr
= o3tl::getToken(aString
, 0, ',', nToken
);
837 css::awt::Point aPos
;
838 aPos
.X
= o3tl::toInt32(aXStr
);
839 aPos
.Y
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
841 if ( i
== PROPERTY_POS
)
843 aWindowStateInfo
.aPos
= aPos
;
844 nMask
|= WINDOWSTATE_MASK_POS
;
848 aWindowStateInfo
.aDockPos
= aPos
;
849 nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
857 case PROPERTY_DOCKSIZE
:
862 sal_Int32
nToken( 0 );
863 std::u16string_view aStr
= o3tl::getToken(aString
, 0, ',', nToken
);
866 css::awt::Size aSize
;
867 aSize
.Width
= o3tl::toInt32(aStr
);
868 aSize
.Height
= o3tl::toInt32(o3tl::getToken(aString
, 0, ',', nToken
));
869 if ( i
== PROPERTY_SIZE
)
871 aWindowStateInfo
.aSize
= aSize
;
872 nMask
|= WINDOWSTATE_MASK_SIZE
;
876 aWindowStateInfo
.aDockSize
= aSize
;
877 nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
884 case PROPERTY_UINAME
:
889 nMask
|= WINDOWSTATE_MASK_UINAME
;
890 aWindowStateInfo
.aUIName
= aValue
;
895 case PROPERTY_INTERNALSTATE
:
897 sal_Int32 nValue
= 0;
900 nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
901 aWindowStateInfo
.nInternalState
= sal_uInt32( nValue
);
908 sal_Int32 nValue
= 0;
911 nMask
|= WINDOWSTATE_MASK_STYLE
;
912 aWindowStateInfo
.nStyle
= sal_uInt16( nValue
);
918 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
921 catch( const css::container::NoSuchElementException
& )
924 catch ( const css::lang::WrappedTargetException
& )
929 aWindowStateInfo
.nMask
= nMask
;
930 ResourceURLToInfoCache::iterator pIter
= m_aResourceURLToInfoCache
.emplace( rResourceURL
, aWindowStateInfo
).first
;
931 return pIter
->second
;
934 Any
ConfigurationAccess_WindowState::impl_getWindowStateFromResourceURL( const OUString
& rResourceURL
)
936 if ( !m_bConfigAccessInitialized
)
938 impl_initializeConfigAccess();
939 m_bConfigAccessInitialized
= true;
944 // Try to ask our configuration access
945 if ( m_xConfigAccess
.is() && m_xConfigAccess
->hasByName( rResourceURL
) )
948 Reference
< XNameAccess
> xNameAccess( m_xConfigAccess
->getByName( rResourceURL
), UNO_QUERY
);
949 if ( xNameAccess
.is() )
950 return impl_insertCacheAndReturnSequence( rResourceURL
, xNameAccess
);
953 catch( const css::container::NoSuchElementException
& )
956 catch ( const css::lang::WrappedTargetException
& )
963 void ConfigurationAccess_WindowState::impl_fillStructFromSequence( WindowStateInfo
& rWinStateInfo
, const Sequence
< PropertyValue
>& rSeq
)
965 sal_Int32
nCompareCount( m_aPropArray
.size() );
966 sal_Int32
nCount( rSeq
.getLength() );
969 for ( i
= 0; i
< nCount
; i
++ )
971 for ( sal_Int32 j
= 0; j
< nCompareCount
; j
++ )
973 if ( rSeq
[i
].Name
== m_aPropArray
[j
] )
977 case PROPERTY_LOCKED
:
978 case PROPERTY_DOCKED
:
979 case PROPERTY_VISIBLE
:
980 case PROPERTY_CONTEXT
:
981 case PROPERTY_HIDEFROMMENU
:
982 case PROPERTY_NOCLOSE
:
983 case PROPERTY_SOFTCLOSE
:
984 case PROPERTY_CONTEXTACTIVE
:
987 if ( rSeq
[i
].Value
>>= bValue
)
989 sal_Int32
nValue( 1 << j
);
990 rWinStateInfo
.nMask
|= nValue
;
993 case PROPERTY_LOCKED
:
994 rWinStateInfo
.bLocked
= bValue
;
996 case PROPERTY_DOCKED
:
997 rWinStateInfo
.bDocked
= bValue
;
999 case PROPERTY_VISIBLE
:
1000 rWinStateInfo
.bVisible
= bValue
;
1002 case PROPERTY_CONTEXT
:
1003 rWinStateInfo
.bContext
= bValue
;
1005 case PROPERTY_HIDEFROMMENU
:
1006 rWinStateInfo
.bHideFromMenu
= bValue
;
1008 case PROPERTY_NOCLOSE
:
1009 rWinStateInfo
.bNoClose
= bValue
;
1011 case PROPERTY_SOFTCLOSE
:
1012 rWinStateInfo
.bSoftClose
= bValue
;
1014 case PROPERTY_CONTEXTACTIVE
:
1015 rWinStateInfo
.bContextActive
= bValue
;
1022 case PROPERTY_DOCKINGAREA
:
1024 css::ui::DockingArea eDockingArea
;
1025 if ( rSeq
[i
].Value
>>= eDockingArea
)
1027 rWinStateInfo
.aDockingArea
= eDockingArea
;
1028 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKINGAREA
;
1034 case PROPERTY_DOCKPOS
:
1036 css::awt::Point aPoint
;
1037 if ( rSeq
[i
].Value
>>= aPoint
)
1039 if ( j
== PROPERTY_POS
)
1041 rWinStateInfo
.aPos
= aPoint
;
1042 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_POS
;
1046 rWinStateInfo
.aDockPos
= aPoint
;
1047 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKPOS
;
1054 case PROPERTY_DOCKSIZE
:
1056 css::awt::Size aSize
;
1057 if ( rSeq
[i
].Value
>>= aSize
)
1059 if ( j
== PROPERTY_SIZE
)
1061 rWinStateInfo
.aSize
= aSize
;
1062 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_SIZE
;
1066 rWinStateInfo
.aDockSize
= aSize
;
1067 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_DOCKSIZE
;
1073 case PROPERTY_UINAME
:
1076 if ( rSeq
[i
].Value
>>= aValue
)
1078 rWinStateInfo
.aUIName
= aValue
;
1079 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_UINAME
;
1084 case PROPERTY_INTERNALSTATE
:
1086 sal_Int32 nValue
= 0;
1087 if ( rSeq
[i
].Value
>>= nValue
)
1089 rWinStateInfo
.nInternalState
= sal_uInt32( nValue
);
1090 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_INTERNALSTATE
;
1095 case PROPERTY_STYLE
:
1097 sal_Int32 nValue
= 0;
1098 if ( rSeq
[i
].Value
>>= nValue
)
1100 rWinStateInfo
.nStyle
= sal_uInt16( nValue
);
1101 rWinStateInfo
.nMask
|= WINDOWSTATE_MASK_STYLE
;
1107 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
1116 void ConfigurationAccess_WindowState::impl_putPropertiesFromStruct( const WindowStateInfo
& rWinStateInfo
, Reference
< XPropertySet
> const & xPropSet
)
1119 sal_Int32
nCount( m_aPropArray
.size() );
1120 OUString
aDelim( "," );
1122 for ( i
= 0; i
< nCount
; i
++ )
1124 if ( rWinStateInfo
.nMask
& ( 1 << i
))
1128 // put values into the property set
1131 case PROPERTY_LOCKED
:
1132 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bLocked
) ); break;
1133 case PROPERTY_DOCKED
:
1134 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bDocked
) ); break;
1135 case PROPERTY_VISIBLE
:
1136 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bVisible
) ); break;
1137 case PROPERTY_CONTEXT
:
1138 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bContext
) ); break;
1139 case PROPERTY_HIDEFROMMENU
:
1140 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bHideFromMenu
) ); break;
1141 case PROPERTY_NOCLOSE
:
1142 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bNoClose
) ); break;
1143 case PROPERTY_SOFTCLOSE
:
1144 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bSoftClose
) ); break;
1145 case PROPERTY_CONTEXTACTIVE
:
1146 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.bContextActive
) ); break;
1147 case PROPERTY_DOCKINGAREA
:
1148 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int16( rWinStateInfo
.aDockingArea
) ) ); break;
1150 case PROPERTY_DOCKPOS
:
1153 if ( i
== PROPERTY_POS
)
1154 aPosStr
= OUString::number( rWinStateInfo
.aPos
.X
);
1156 aPosStr
= OUString::number( rWinStateInfo
.aDockPos
.X
);
1158 if ( i
== PROPERTY_POS
)
1159 aPosStr
+= OUString::number( rWinStateInfo
.aPos
.Y
);
1161 aPosStr
+= OUString::number( rWinStateInfo
.aDockPos
.Y
);
1162 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( aPosStr
) );
1166 case PROPERTY_DOCKSIZE
:
1169 if ( i
== PROPERTY_SIZE
)
1170 aSizeStr
= OUString::number( rWinStateInfo
.aSize
.Width
);
1172 aSizeStr
= OUString::number( rWinStateInfo
.aDockSize
.Width
);
1174 if ( i
== PROPERTY_SIZE
)
1175 aSizeStr
+= OUString::number( rWinStateInfo
.aSize
.Height
);
1177 aSizeStr
+= OUString::number( rWinStateInfo
.aDockSize
.Height
);
1178 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( aSizeStr
) );
1181 case PROPERTY_UINAME
:
1182 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( rWinStateInfo
.aUIName
) ); break;
1183 case PROPERTY_INTERNALSTATE
:
1184 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int32( rWinStateInfo
.nInternalState
)) ); break;
1185 case PROPERTY_STYLE
:
1186 xPropSet
->setPropertyValue( m_aPropArray
[i
], Any( sal_Int32( rWinStateInfo
.nStyle
)) ); break;
1188 assert( false && "Wrong value for ConfigurationAccess_WindowState. Who has forgotten to add this new property!" );
1191 catch( const Exception
& )
1198 void ConfigurationAccess_WindowState::impl_initializeConfigAccess()
1202 Sequence
<Any
> aArgs(comphelper::InitAnyPropertySequence(
1204 {"nodepath", Any(m_aConfigWindowAccess
)}
1206 m_xConfigAccess
.set( m_xConfigProvider
->createInstanceWithArguments(
1207 "com.sun.star.configuration.ConfigurationUpdateAccess", aArgs
), UNO_QUERY
);
1208 if ( m_xConfigAccess
.is() )
1210 // Add as container listener
1211 Reference
< XContainer
> xContainer( m_xConfigAccess
, UNO_QUERY
);
1212 if ( xContainer
.is() )
1214 m_xConfigListener
= new WeakContainerListener(this);
1215 xContainer
->addContainerListener(m_xConfigListener
);
1219 catch ( const WrappedTargetException
& )
1222 catch ( const Exception
& )
1227 typedef comphelper::WeakComponentImplHelper
< css::container::XNameAccess
,
1228 css::lang::XServiceInfo
> WindowStateConfiguration_BASE
;
1230 class WindowStateConfiguration
: public WindowStateConfiguration_BASE
1233 explicit WindowStateConfiguration( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
1234 virtual ~WindowStateConfiguration() override
;
1236 virtual OUString SAL_CALL
getImplementationName() override
1238 return "com.sun.star.comp.framework.WindowStateConfiguration";
1241 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
1243 return cppu::supportsService(this, ServiceName
);
1246 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
1248 return {"com.sun.star.ui.WindowStateConfiguration"};
1252 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
;
1254 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames() override
;
1256 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
;
1259 virtual css::uno::Type SAL_CALL
getElementType() override
;
1260 virtual sal_Bool SAL_CALL
hasElements() override
;
1262 typedef std::unordered_map
< OUString
,
1263 OUString
> ModuleToWindowStateFileMap
;
1265 typedef std::unordered_map
< OUString
,
1266 css::uno::Reference
< css::container::XNameAccess
> > ModuleToWindowStateConfigHashMap
;
1269 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
1270 ModuleToWindowStateFileMap m_aModuleToFileHashMap
;
1271 ModuleToWindowStateConfigHashMap m_aModuleToWindowStateHashMap
;
1274 WindowStateConfiguration::WindowStateConfiguration( const Reference
< XComponentContext
>& rxContext
) :
1275 m_xContext( rxContext
)
1277 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager
=
1278 ModuleManager::create( m_xContext
);
1279 Reference
< XNameAccess
> xEmptyNameAccess
;
1280 Sequence
< OUString
> aElementNames
;
1283 aElementNames
= xModuleManager
->getElementNames();
1285 catch (const css::uno::RuntimeException
&)
1288 Sequence
< PropertyValue
> aSeq
;
1290 for ( OUString
const & aModuleIdentifier
: std::as_const(aElementNames
) )
1292 if ( xModuleManager
->getByName( aModuleIdentifier
) >>= aSeq
)
1294 OUString aWindowStateFileStr
;
1295 for ( PropertyValue
const & rProp
: std::as_const(aSeq
) )
1297 if ( rProp
.Name
== "ooSetupFactoryWindowStateConfigRef" )
1299 rProp
.Value
>>= aWindowStateFileStr
;
1304 if ( !aWindowStateFileStr
.isEmpty() )
1306 // Create first mapping ModuleIdentifier ==> Window state configuration file
1307 m_aModuleToFileHashMap
.emplace( aModuleIdentifier
, aWindowStateFileStr
);
1309 // Create second mapping Command File ==> Window state configuration instance
1310 ModuleToWindowStateConfigHashMap::iterator pIter
= m_aModuleToWindowStateHashMap
.find( aWindowStateFileStr
);
1311 if ( pIter
== m_aModuleToWindowStateHashMap
.end() )
1312 m_aModuleToWindowStateHashMap
.emplace( aWindowStateFileStr
, xEmptyNameAccess
);
1318 WindowStateConfiguration::~WindowStateConfiguration()
1320 std::unique_lock
g(m_aMutex
);
1321 m_aModuleToFileHashMap
.clear();
1322 m_aModuleToWindowStateHashMap
.clear();
1325 Any SAL_CALL
WindowStateConfiguration::getByName( const OUString
& aModuleIdentifier
)
1327 std::unique_lock
g(m_aMutex
);
1329 ModuleToWindowStateFileMap::const_iterator pIter
= m_aModuleToFileHashMap
.find( aModuleIdentifier
);
1330 if ( pIter
!= m_aModuleToFileHashMap
.end() )
1333 OUString
aWindowStateConfigFile( pIter
->second
);
1335 ModuleToWindowStateConfigHashMap::iterator pModuleIter
= m_aModuleToWindowStateHashMap
.find( aWindowStateConfigFile
);
1336 if ( pModuleIter
!= m_aModuleToWindowStateHashMap
.end() )
1338 if ( pModuleIter
->second
.is() )
1339 a
<<= pModuleIter
->second
;
1342 Reference
< XNameAccess
> xResourceURLWindowState
= new ConfigurationAccess_WindowState( aWindowStateConfigFile
, m_xContext
);
1343 pModuleIter
->second
= xResourceURLWindowState
;
1344 a
<<= xResourceURLWindowState
;
1351 throw NoSuchElementException();
1354 Sequence
< OUString
> SAL_CALL
WindowStateConfiguration::getElementNames()
1356 std::unique_lock
g(m_aMutex
);
1358 return comphelper::mapKeysToSequence( m_aModuleToFileHashMap
);
1361 sal_Bool SAL_CALL
WindowStateConfiguration::hasByName( const OUString
& aName
)
1363 std::unique_lock
g(m_aMutex
);
1365 ModuleToWindowStateFileMap::const_iterator pIter
= m_aModuleToFileHashMap
.find( aName
);
1366 return ( pIter
!= m_aModuleToFileHashMap
.end() );
1370 Type SAL_CALL
WindowStateConfiguration::getElementType()
1372 return cppu::UnoType
<XNameAccess
>::get();
1375 sal_Bool SAL_CALL
WindowStateConfiguration::hasElements()
1377 // We always have at least one module. So it is valid to return true!
1383 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1384 com_sun_star_comp_framework_WindowStateConfiguration_get_implementation(
1385 css::uno::XComponentContext
*context
,
1386 css::uno::Sequence
<css::uno::Any
> const &)
1388 return cppu::acquire(new WindowStateConfiguration(context
));
1391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */