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 .
21 #include "svx/shapepropertynotifier.hxx"
23 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <cppuhelper/interfacecontainer.hxx>
26 #include <cppuhelper/weak.hxx>
27 #include <tools/diagnose_ex.h>
29 #include <unordered_map>
34 struct ShapePropertyHash
36 size_t operator()( svx::ShapeProperty __x
) const
48 using ::com::sun::star::uno::Reference
;
49 using ::com::sun::star::uno::XInterface
;
50 using ::com::sun::star::uno::UNO_QUERY
;
51 using ::com::sun::star::uno::UNO_QUERY_THROW
;
52 using ::com::sun::star::uno::UNO_SET_THROW
;
53 using ::com::sun::star::uno::Exception
;
54 using ::com::sun::star::uno::RuntimeException
;
55 using ::com::sun::star::uno::Any
;
56 using ::com::sun::star::uno::makeAny
;
57 using ::com::sun::star::uno::Sequence
;
58 using ::com::sun::star::uno::Type
;
59 using ::com::sun::star::beans::PropertyChangeEvent
;
60 using ::com::sun::star::beans::XPropertyChangeListener
;
61 using ::com::sun::star::lang::EventObject
;
62 using ::com::sun::star::beans::XPropertySet
;
64 typedef std::unordered_map
< ShapeProperty
, PPropertyValueProvider
, ShapePropertyHash
> PropertyProviders
;
66 typedef cppu::OMultiTypeInterfaceContainerHelperVar
<OUString
>
67 PropertyChangeListenerContainer
;
69 IPropertyValueProvider::~IPropertyValueProvider()
73 struct PropertyChangeNotifier_Data
75 ::cppu::OWeakObject
& m_rContext
;
76 PropertyProviders m_aProviders
;
77 PropertyChangeListenerContainer m_aPropertyChangeListeners
;
79 PropertyChangeNotifier_Data( ::cppu::OWeakObject
& _rContext
, ::osl::Mutex
& _rMutex
)
80 :m_rContext( _rContext
)
81 ,m_aPropertyChangeListeners( _rMutex
)
86 //= PropertyValueProvider
89 OUString
PropertyValueProvider::getPropertyName() const
91 return m_sPropertyName
;
95 void PropertyValueProvider::getCurrentValue( Any
& _out_rValue
) const
97 Reference
< XPropertySet
> xContextProps( const_cast< PropertyValueProvider
* >( this )->m_rContext
, UNO_QUERY_THROW
);
98 _out_rValue
= xContextProps
->getPropertyValue( getPropertyName() );
101 PropertyChangeNotifier::PropertyChangeNotifier( ::cppu::OWeakObject
& _rOwner
, ::osl::Mutex
& _rMutex
)
102 :m_xData( new PropertyChangeNotifier_Data( _rOwner
, _rMutex
) )
106 PropertyChangeNotifier::~PropertyChangeNotifier()
110 void PropertyChangeNotifier::registerProvider(const ShapeProperty _eProperty
, const PPropertyValueProvider
& _rProvider
)
112 ENSURE_OR_THROW( _eProperty
!= eInvalidShapeProperty
, "Illegal ShapeProperty value!" );
113 ENSURE_OR_THROW( !!_rProvider
, "NULL factory not allowed." );
115 OSL_ENSURE( m_xData
->m_aProviders
.find( _eProperty
) == m_xData
->m_aProviders
.end(),
116 "PropertyChangeNotifier::registerProvider: factory for this ID already present!" );
118 m_xData
->m_aProviders
[ _eProperty
] = _rProvider
;
121 void PropertyChangeNotifier::notifyPropertyChange( const ShapeProperty _eProperty
) const
123 ENSURE_OR_THROW( _eProperty
!= eInvalidShapeProperty
, "Illegal ShapeProperty value!" );
125 PropertyProviders::const_iterator provPos
= m_xData
->m_aProviders
.find( _eProperty
);
126 OSL_ENSURE( provPos
!= m_xData
->m_aProviders
.end(), "PropertyChangeNotifier::notifyPropertyChange: no factory!" );
127 if ( provPos
== m_xData
->m_aProviders
.end() )
130 OUString
sPropertyName( provPos
->second
->getPropertyName() );
132 ::cppu::OInterfaceContainerHelper
* pPropListeners
= m_xData
->m_aPropertyChangeListeners
.getContainer( sPropertyName
);
133 ::cppu::OInterfaceContainerHelper
* pAllListeners
= m_xData
->m_aPropertyChangeListeners
.getContainer( OUString() );
134 if ( !pPropListeners
&& !pAllListeners
)
139 PropertyChangeEvent aEvent
;
140 aEvent
.Source
= m_xData
->m_rContext
;
141 // Handle/OldValue not supported
142 aEvent
.PropertyName
= provPos
->second
->getPropertyName();
143 provPos
->second
->getCurrentValue( aEvent
.NewValue
);
145 if ( pPropListeners
)
146 pPropListeners
->notifyEach( &XPropertyChangeListener::propertyChange
, aEvent
);
148 pAllListeners
->notifyEach( &XPropertyChangeListener::propertyChange
, aEvent
);
150 catch( const Exception
& )
152 DBG_UNHANDLED_EXCEPTION();
157 void PropertyChangeNotifier::addPropertyChangeListener( const OUString
& _rPropertyName
, const Reference
< XPropertyChangeListener
>& _rxListener
)
159 m_xData
->m_aPropertyChangeListeners
.addInterface( _rPropertyName
, _rxListener
);
163 void PropertyChangeNotifier::removePropertyChangeListener( const OUString
& _rPropertyName
, const Reference
< XPropertyChangeListener
>& _rxListener
)
165 m_xData
->m_aPropertyChangeListeners
.removeInterface( _rPropertyName
, _rxListener
);
169 void PropertyChangeNotifier::disposing()
172 aEvent
.Source
= m_xData
->m_rContext
;
173 m_xData
->m_aPropertyChangeListeners
.disposeAndClear( aEvent
);
180 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */