/src/libreoffice/include/comphelper/propagg.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #ifndef INCLUDED_COMPHELPER_PROPAGG_HXX |
21 | | #define INCLUDED_COMPHELPER_PROPAGG_HXX |
22 | | |
23 | | #include <config_options.h> |
24 | | #include <com/sun/star/beans/Property.hpp> |
25 | | #include <com/sun/star/beans/XPropertiesChangeListener.hpp> |
26 | | #include <com/sun/star/beans/XVetoableChangeListener.hpp> |
27 | | #include <comphelper/propstate.hxx> |
28 | | #include <comphelper/comphelperdllapi.h> |
29 | | |
30 | | #include <cstddef> |
31 | | #include <map> |
32 | | #include <memory> |
33 | | #include <vector> |
34 | | |
35 | | |
36 | | //= property helper classes |
37 | | |
38 | | |
39 | | namespace comphelper |
40 | | { |
41 | | |
42 | | |
43 | | //= OPropertyAccessor |
44 | | //= internal helper class for OPropertyArrayAggregationHelper |
45 | | |
46 | | namespace internal |
47 | | { |
48 | | struct OPropertyAccessor |
49 | | { |
50 | | sal_Int32 nOriginalHandle; |
51 | | std::size_t nPos; |
52 | | bool bAggregate; |
53 | | |
54 | | OPropertyAccessor(sal_Int32 _nOriginalHandle, std::size_t _nPos, bool _bAggregate) |
55 | 0 | :nOriginalHandle(_nOriginalHandle) ,nPos(_nPos) ,bAggregate(_bAggregate) { } |
56 | | |
57 | 0 | bool operator==(const OPropertyAccessor& rOb) const { return nPos == rOb.nPos; } |
58 | 0 | bool operator <(const OPropertyAccessor& rOb) const { return nPos < rOb.nPos; } |
59 | | }; |
60 | | } |
61 | | |
62 | | |
63 | | /** |
64 | | * used as callback for an OPropertyArrayAggregationHelper |
65 | | */ |
66 | | class IPropertyInfoService |
67 | | { |
68 | | public: |
69 | | /** get the preferred handle for the given property |
70 | | @param _rName the property name |
71 | | @return the handle the property should be referred by, or -1 if there are no |
72 | | preferences for the given property |
73 | | */ |
74 | | virtual sal_Int32 getPreferredPropertyId(const OUString& _rName) = 0; |
75 | | |
76 | | protected: |
77 | 0 | ~IPropertyInfoService() {} |
78 | | }; |
79 | | |
80 | | /** |
81 | | * used for implementing a cppu::IPropertyArrayHelper for classes |
82 | | * aggregating property sets |
83 | | */ |
84 | | |
85 | 0 | #define DEFAULT_AGGREGATE_PROPERTY_ID 10000 |
86 | | |
87 | | class COMPHELPER_DLLPUBLIC OPropertyArrayAggregationHelper final : public ::cppu::IPropertyArrayHelper |
88 | | { |
89 | | friend class OPropertySetAggregationHelper; |
90 | | |
91 | | std::vector<css::beans::Property> m_aProperties; |
92 | | std::map< sal_Int32, internal::OPropertyAccessor > m_aPropertyAccessors; |
93 | | |
94 | | public: |
95 | | /** construct the object. |
96 | | @param _rProperties the properties of the object doing the aggregation. These properties |
97 | | are used without any checks, so the caller has to ensure that the names and |
98 | | handles are valid. |
99 | | @param _rAggProperties the properties of the aggregate, usually got via a call to getProperties on the |
100 | | XPropertySetInfo of the aggregate. |
101 | | The names of the properties are used without any checks, so the caller has to ensure |
102 | | that there are no doubles. |
103 | | The handles are stored for later quick access, but the outside-handles the |
104 | | aggregate properties get depend from the following two parameters. |
105 | | @param _pInfoService |
106 | | If not NULL, the object pointed to is used to calc handles which should be used |
107 | | for referring the aggregate's properties from outside. |
108 | | If one of the properties returned from the info service conflict with other handles |
109 | | already present (e.g. through _rProperties), the property is handled as if -1 was returned. |
110 | | If NULL (or, for a special property, a call to getPreferredPropertyId returns -1), |
111 | | the aggregate property(ies) get a new handle which they can be referred by from outside. |
112 | | @param _nFirstAggregateId |
113 | | if the object is about to create new handles for the aggregate properties, it uses |
114 | | id's ascending from this given id. |
115 | | No checks are made if the handle range determined by _nFirstAggregateId conflicts with other |
116 | | handles within _rProperties. |
117 | | */ |
118 | | OPropertyArrayAggregationHelper(const css::uno::Sequence< css::beans::Property>& _rProperties, |
119 | | const css::uno::Sequence< css::beans::Property>& _rAggProperties, |
120 | | IPropertyInfoService* _pInfoService = nullptr, |
121 | | sal_Int32 _nFirstAggregateId = DEFAULT_AGGREGATE_PROPERTY_ID); |
122 | | |
123 | | |
124 | | /// inherited from IPropertyArrayHelper |
125 | | virtual sal_Bool SAL_CALL fillPropertyMembersByHandle( OUString* _pPropName, sal_Int16* _pAttributes, |
126 | | sal_Int32 _nHandle) override ; |
127 | | |
128 | | /// inherited from IPropertyArrayHelper |
129 | | virtual css::uno::Sequence< css::beans::Property> SAL_CALL getProperties() override; |
130 | | /// inherited from IPropertyArrayHelper |
131 | | virtual css::beans::Property SAL_CALL getPropertyByName(const OUString& _rPropertyName) override; |
132 | | |
133 | | /// inherited from IPropertyArrayHelper |
134 | | virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& _rPropertyName) override ; |
135 | | /// inherited from IPropertyArrayHelper |
136 | | virtual sal_Int32 SAL_CALL getHandleByName(const OUString & _rPropertyName) override; |
137 | | /// inherited from IPropertyArrayHelper |
138 | | virtual sal_Int32 SAL_CALL fillHandles( /*out*/sal_Int32* _pHandles, const css::uno::Sequence< OUString >& _rPropNames ) override; |
139 | | |
140 | | /** returns information about a property of the aggregate. |
141 | | @param _pPropName points to a string to receive the property name. No name is returned if this is NULL. |
142 | | @param _pOriginalHandle points to a sal_Int32 to receive the original property handle. No original handle is returned |
143 | | if this is NULL. |
144 | | @param _nHandle the handle of the property as got by, for instance, fillHandles |
145 | | |
146 | | @return sal_True, if _nHandle marks an aggregate property, otherwise sal_False |
147 | | */ |
148 | | bool fillAggregatePropertyInfoByHandle(OUString* _pPropName, sal_Int32* _pOriginalHandle, |
149 | | sal_Int32 _nHandle) const; |
150 | | |
151 | | /** returns information about a property given by handle |
152 | | */ |
153 | | bool getPropertyByHandle( sal_Int32 _nHandle, css::beans::Property& _rProperty ) const; |
154 | | |
155 | | |
156 | | enum class PropertyOrigin |
157 | | { |
158 | | Aggregate, |
159 | | Delegator, |
160 | | Unknown |
161 | | }; |
162 | | /** prefer this one over the XPropertySetInfo of the aggregate! |
163 | | |
164 | | <p>The reason is that OPropertyArrayAggregationHelper is the only instance which really knows |
165 | | which properties of the aggregate are to be exposed. <br/> |
166 | | |
167 | | For instance, some derivee of OPropertySetAggregationHelper may decide to create an |
168 | | OPropertyArrayAggregationHelper which contains only a subset of the aggregate properties. This way, |
169 | | some of the aggregate properties may be hidden to the public.<br/> |
170 | | |
171 | | When using the XPropertySetInfo of the aggregate set to determine the existence of a property, then this |
172 | | would return false positives.</p> |
173 | | */ |
174 | | PropertyOrigin classifyProperty( const OUString& _rName ); |
175 | | |
176 | | private: |
177 | | const css::beans::Property* findPropertyByName(const OUString& _rName) const; |
178 | | }; |
179 | | |
180 | | |
181 | | namespace internal |
182 | | { |
183 | | class PropertyForwarder; |
184 | | } |
185 | | |
186 | | /** |
187 | | * helper class for implementing the property-set-related interfaces |
188 | | * for an object doin' aggregation |
189 | | * supports at least XPropertySet and XMultiPropertySet |
190 | | * |
191 | | */ |
192 | | class UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OPropertySetAggregationHelper :public OPropertyStateHelper |
193 | | ,public css::beans::XPropertiesChangeListener |
194 | | ,public css::beans::XVetoableChangeListener |
195 | | { |
196 | | friend class internal::PropertyForwarder; |
197 | | |
198 | | protected: |
199 | | css::uno::Reference< css::beans::XPropertyState> m_xAggregateState; |
200 | | css::uno::Reference< css::beans::XPropertySet> m_xAggregateSet; |
201 | | css::uno::Reference< css::beans::XMultiPropertySet> m_xAggregateMultiSet; |
202 | | css::uno::Reference< css::beans::XFastPropertySet> m_xAggregateFastSet; |
203 | | |
204 | | std::unique_ptr<internal::PropertyForwarder> m_pForwarder; |
205 | | bool m_bListening : 1; |
206 | | |
207 | | public: |
208 | | OPropertySetAggregationHelper( ::cppu::OBroadcastHelper& rBHelper ); |
209 | | |
210 | | virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& aType) override; |
211 | | |
212 | | // XEventListener |
213 | | virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; |
214 | | |
215 | | // XFastPropertySet |
216 | | virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const css::uno::Any& aValue) override; |
217 | | virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override; |
218 | | |
219 | | // XPropertySet |
220 | | virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener) override; |
221 | | virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener) override; |
222 | | |
223 | | // XPropertiesChangeListener |
224 | | virtual void SAL_CALL propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent >& evt) override; |
225 | | |
226 | | // XVetoableChangeListener |
227 | | virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent& aEvent) override; |
228 | | |
229 | | // XMultiPropertySet |
230 | | virtual void SAL_CALL setPropertyValues(const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Sequence< css::uno::Any >& Values) override; |
231 | | virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener) override; |
232 | | |
233 | | // XPropertyState |
234 | | virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString& PropertyName) override; |
235 | | virtual void SAL_CALL setPropertyToDefault(const OUString& PropertyName) override; |
236 | | virtual css::uno::Any SAL_CALL getPropertyDefault(const OUString& aPropertyName) override; |
237 | | |
238 | | // OPropertySetHelper |
239 | | /** still waiting to be overwritten ... |
240 | | you <B>must<B/> use an OPropertyArrayAggregationHelper here, as the implementation strongly relies on this. |
241 | | */ |
242 | | virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override = 0; |
243 | | |
244 | | /** only implemented for "forwarded" properties, every other property must be handled |
245 | | in the derivee, and will assert if passed herein |
246 | | */ |
247 | | virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& _rConvertedValue, css::uno::Any& _rOldValue, sal_Int32 _nHandle, const css::uno::Any& _rValue ) override; |
248 | | |
249 | | /** only implemented for "forwarded" properties, every other property must be handled |
250 | | in the derivee, and will assert if passed herein |
251 | | */ |
252 | | virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const css::uno::Any& _rValue ) override; |
253 | | |
254 | | protected: |
255 | | virtual ~OPropertySetAggregationHelper() override; |
256 | | |
257 | | virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue, sal_Int32 nHandle) const override; |
258 | | void disposing(); |
259 | | |
260 | | sal_Int32 getOriginalHandle( sal_Int32 _nHandle ) const; |
261 | | OUString getPropertyName( sal_Int32 _nHandle ) const; |
262 | | |
263 | | /** declares the property with the given (public) handle as one to be forwarded to the aggregate |
264 | | |
265 | | Sometimes, you might want to <em>overwrite</em> properties at the aggregate. That is, |
266 | | though the aggregate implements this property, and still is to hold the property value, |
267 | | you want to do additional handling upon setting the property, but then forward the value |
268 | | to the aggregate. |
269 | | |
270 | | Use this method to declare such properties. |
271 | | |
272 | | When a "forwarded property" is set from outside, the class first calls |
273 | | <member>forwardingPropertyValue</member> for any preprocessing, then forwards the property |
274 | | value to the aggregate, and then calls <member>forwardedPropertyValue</member>. |
275 | | |
276 | | When you declare a property as "forwarded", the class takes care for some multi-threading |
277 | | issues, for instance, it won't fire any property change notifications which result from |
278 | | forwarding a property value, unless it's safe to do so (i.e. unless our mutex is |
279 | | released). |
280 | | |
281 | | @see forwardingPropertyValue |
282 | | @see forwardedPropertyValue |
283 | | */ |
284 | | void declareForwardedProperty( sal_Int32 _nHandle ); |
285 | | |
286 | | /** checks whether we're actually forwarding a property value to our aggregate |
287 | | |
288 | | @see declareForwardedProperty |
289 | | @see forwardingPropertyValue |
290 | | @see forwardedPropertyValue |
291 | | */ |
292 | | bool isCurrentlyForwardingProperty( sal_Int32 _nHandle ) const; |
293 | | |
294 | | /** called immediately before a property value which is overwritten in this instance |
295 | | is forwarded to the aggregate |
296 | | |
297 | | @see declareForwardedProperty |
298 | | @see forwardedPropertyValue |
299 | | */ |
300 | | virtual void forwardingPropertyValue( sal_Int32 _nHandle ); |
301 | | |
302 | | /** called immediately after a property value which is overwritten in this instance |
303 | | has been forwarded to the aggregate |
304 | | |
305 | | @see declareForwardedProperty |
306 | | @see forwardingPropertyValue |
307 | | */ |
308 | | virtual void forwardedPropertyValue( sal_Int32 _nHandle ); |
309 | | |
310 | | /// must be called before aggregation, if aggregation is used |
311 | | /// |
312 | | /// @throws css::lang::IllegalArgumentException |
313 | | void setAggregation(const css::uno::Reference< css::uno::XInterface >&); |
314 | | void startListening(); |
315 | | }; |
316 | | |
317 | | |
318 | | } // namespace comphelper |
319 | | |
320 | | |
321 | | #endif // INCLUDED_COMPHELPER_PROPAGG_HXX |
322 | | |
323 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |