Line data Source code
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 : #include "composeduiupdate.hxx"
21 :
22 : #include <boost/noncopyable.hpp>
23 : #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
24 : #include <com/sun/star/lang/DisposedException.hpp>
25 : #include <com/sun/star/inspection/PropertyLineElement.hpp>
26 : #include <osl/mutex.hxx>
27 : #include <rtl/ref.hxx>
28 :
29 : #include <algorithm>
30 :
31 :
32 : namespace pcr
33 : {
34 :
35 :
36 : using ::com::sun::star::uno::Exception;
37 : using ::com::sun::star::lang::DisposedException;
38 : using ::com::sun::star::lang::NullPointerException;
39 : using ::com::sun::star::inspection::XPropertyHandler;
40 : using ::com::sun::star::uno::Reference;
41 : using ::com::sun::star::inspection::XObjectInspectorUI;
42 : using ::com::sun::star::inspection::XPropertyControl;
43 : using ::com::sun::star::uno::RuntimeException;
44 : using ::com::sun::star::lang::NoSupportException;
45 : using ::com::sun::star::inspection::XPropertyControlObserver;
46 :
47 : namespace PropertyLineElement = ::com::sun::star::inspection::PropertyLineElement;
48 :
49 : namespace
50 : {
51 : struct HandlerLess : public ::std::binary_function < Reference< XPropertyHandler >
52 : , Reference< XPropertyHandler >
53 : , bool
54 : >
55 : {
56 0 : bool operator()( const Reference< XPropertyHandler >& lhs, const Reference< XPropertyHandler >& rhs) const
57 : {
58 0 : return lhs.get() < rhs.get();
59 : }
60 : };
61 :
62 :
63 : typedef ::std::set< OUString > StringBag;
64 : typedef ::std::map< sal_Int16, StringBag > MapIntToStringBag;
65 : }
66 :
67 :
68 : // callbacks for CachedInspectorUI
69 :
70 : typedef void (ComposedPropertyUIUpdate::*FNotifySingleUIChange)();
71 :
72 : typedef ::cppu::WeakImplHelper1 < ::com::sun::star::inspection::XObjectInspectorUI
73 : > CachedInspectorUI_Base;
74 : struct CachedInspectorUI:
75 : public CachedInspectorUI_Base, private boost::noncopyable
76 : {
77 : private:
78 : ::osl::Mutex m_aMutex;
79 : bool m_bDisposed;
80 : ComposedPropertyUIUpdate&
81 : m_rMaster;
82 : FNotifySingleUIChange m_pUIChangeNotification;
83 :
84 : // enablePropertyUI cache
85 : StringBag aEnabledProperties;
86 : StringBag aDisabledProperties;
87 :
88 : // show/hidePropertyUI cache
89 : StringBag aShownProperties;
90 : StringBag aHiddenProperties;
91 :
92 : // rebuildPropertyUI cache
93 : StringBag aRebuiltProperties;
94 :
95 : // showCategory cache
96 : StringBag aShownCategories;
97 : StringBag aHiddenCategories;
98 :
99 : // enablePropertyUIElements cache
100 : MapIntToStringBag aEnabledElements;
101 : MapIntToStringBag aDisabledElements;
102 :
103 : public:
104 : typedef StringBag& (CachedInspectorUI::*FGetStringBag)();
105 :
106 : // enablePropertyUI cache
107 0 : StringBag& getEnabledProperties() { return aEnabledProperties; }
108 0 : StringBag& getDisabledProperties() { return aDisabledProperties; }
109 :
110 : // show/hidePropertyUI cache
111 0 : StringBag& getShownProperties() { return aShownProperties; }
112 0 : StringBag& getHiddenProperties() { return aHiddenProperties; }
113 :
114 : // rebuildPropertyUI cache
115 0 : StringBag& getRebuiltProperties() { return aRebuiltProperties; }
116 :
117 : // showCategory cache
118 0 : StringBag& getShownCategories() { return aShownCategories; }
119 0 : StringBag& getHiddenCategories() { return aHiddenCategories; }
120 :
121 : // enablePropertyUIElements
122 0 : StringBag& getEnabledInputControls() { return aEnabledElements[ PropertyLineElement::InputControl ]; }
123 0 : StringBag& getDisabledInputControls() { return aDisabledElements[ PropertyLineElement::InputControl ]; }
124 0 : StringBag& getEnabledPrimaryButtons() { return aEnabledElements[ PropertyLineElement::PrimaryButton ]; }
125 0 : StringBag& getDisabledPrimaryButtons() { return aDisabledElements[ PropertyLineElement::PrimaryButton ]; }
126 0 : StringBag& getEnabledSecondaryButtons() { return aEnabledElements[ PropertyLineElement::SecondaryButton ]; }
127 0 : StringBag& getDisabledSecondaryButtons() { return aDisabledElements[ PropertyLineElement::SecondaryButton ]; }
128 :
129 : public:
130 : CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification );
131 :
132 : /// disposes the instance
133 : void dispose();
134 :
135 : // XObjectInspectorUI overridables
136 : virtual void SAL_CALL enablePropertyUI( const OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
137 : virtual void SAL_CALL enablePropertyUIElements( const OUString& _rPropertyName, ::sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
138 : virtual void SAL_CALL rebuildPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
139 : virtual void SAL_CALL showPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
140 : virtual void SAL_CALL hidePropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
141 : virtual void SAL_CALL showCategory( const OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
142 : virtual Reference< XPropertyControl > SAL_CALL getPropertyControl( const OUString& _rPropertyName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
143 : virtual void SAL_CALL registerControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
144 : virtual void SAL_CALL revokeControlObserver( const Reference< XPropertyControlObserver >& Observer ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
145 : virtual void SAL_CALL setHelpSectionText( const OUString& _HelpText ) throw (NoSupportException, RuntimeException, std::exception) SAL_OVERRIDE;
146 :
147 : // UNOCompatibleNonUNOReference overridables
148 : virtual void SAL_CALL acquire() throw() SAL_OVERRIDE;
149 : virtual void SAL_CALL release() throw() SAL_OVERRIDE;
150 :
151 : protected:
152 : virtual ~CachedInspectorUI();
153 :
154 : /// determines whether the instance is already disposed
155 0 : inline bool isDisposed() const { return m_bDisposed; }
156 :
157 : /// throws an exception if the component is already disposed
158 : void checkDisposed() const;
159 :
160 : private:
161 : void impl_markElementEnabledOrDisabled( const OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, bool _bEnable );
162 :
163 : /** calls <member>m_pUIChangeNotification</member> at <member>m_rMaster</member>
164 : */
165 : void impl_notifySingleUIChange() const;
166 :
167 : private:
168 : class MethodGuard;
169 : friend class MethodGuard;
170 0 : class MethodGuard : public ::osl::MutexGuard
171 : {
172 : public:
173 0 : MethodGuard( CachedInspectorUI& rInstance )
174 0 : : ::osl::MutexGuard( rInstance.m_aMutex )
175 : {
176 0 : rInstance.checkDisposed();
177 0 : }
178 : };
179 : };
180 :
181 :
182 0 : CachedInspectorUI::CachedInspectorUI( ComposedPropertyUIUpdate& _rMaster, FNotifySingleUIChange _pUIChangeNotification )
183 : :m_bDisposed( false )
184 : ,m_rMaster( _rMaster )
185 0 : ,m_pUIChangeNotification( _pUIChangeNotification )
186 : {
187 0 : }
188 :
189 :
190 0 : CachedInspectorUI::~CachedInspectorUI()
191 : {
192 0 : }
193 :
194 :
195 0 : void CachedInspectorUI::dispose()
196 : {
197 0 : ::osl::MutexGuard aGuard( m_aMutex );
198 0 : m_bDisposed = true;
199 :
200 0 : clearContainer( aEnabledProperties );
201 0 : clearContainer( aDisabledProperties );
202 0 : clearContainer( aRebuiltProperties );
203 0 : clearContainer( aShownProperties );
204 0 : clearContainer( aHiddenProperties );
205 0 : clearContainer( aShownCategories );
206 0 : clearContainer( aHiddenCategories );
207 0 : clearContainer( aEnabledElements );
208 0 : clearContainer( aDisabledElements );
209 0 : }
210 :
211 :
212 0 : void SAL_CALL CachedInspectorUI::acquire() throw()
213 : {
214 0 : osl_atomic_increment( &m_refCount );
215 0 : }
216 :
217 :
218 0 : void SAL_CALL CachedInspectorUI::release() throw()
219 : {
220 0 : if ( 0 == osl_atomic_decrement( &m_refCount ) )
221 0 : delete this;
222 0 : }
223 :
224 :
225 :
226 0 : void CachedInspectorUI::checkDisposed() const
227 : {
228 0 : if ( isDisposed() )
229 0 : throw DisposedException();
230 0 : }
231 :
232 :
233 : namespace
234 : {
235 0 : void lcl_markStringKeyPositiveOrNegative( const OUString& _rKeyName, StringBag& _rPositives, StringBag& _rNegatives, bool _bMarkPositive )
236 : {
237 0 : if ( _bMarkPositive )
238 : {
239 0 : _rPositives.insert( _rKeyName );
240 : // if the same key has been remember as in the "negative" list before, clear this information, since it's overruled
241 0 : _rNegatives.erase( _rKeyName );
242 : }
243 : else
244 0 : _rNegatives.insert( _rKeyName );
245 0 : }
246 : }
247 :
248 :
249 0 : void CachedInspectorUI::enablePropertyUI( const OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException, std::exception)
250 : {
251 0 : MethodGuard aGuard( *this );
252 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
253 0 : return;
254 :
255 0 : lcl_markStringKeyPositiveOrNegative( _rPropertyName, aEnabledProperties, aDisabledProperties, _bEnable );
256 0 : impl_notifySingleUIChange();
257 : }
258 :
259 :
260 0 : void CachedInspectorUI::impl_markElementEnabledOrDisabled( const OUString& _rPropertyName, sal_Int16 _nElementIdOrZero, bool _bEnable )
261 : {
262 0 : if ( _nElementIdOrZero == 0 )
263 0 : return;
264 :
265 : lcl_markStringKeyPositiveOrNegative(
266 : _rPropertyName,
267 0 : aEnabledElements[ _nElementIdOrZero ],
268 0 : aDisabledElements[ _nElementIdOrZero ],
269 : _bEnable
270 0 : );
271 : }
272 :
273 :
274 0 : void CachedInspectorUI::impl_notifySingleUIChange() const
275 : {
276 0 : (m_rMaster.*m_pUIChangeNotification)();
277 0 : }
278 :
279 :
280 0 : void CachedInspectorUI::enablePropertyUIElements( const OUString& _rPropertyName, sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException, std::exception)
281 : {
282 0 : MethodGuard aGuard( *this );
283 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
284 0 : return;
285 :
286 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::InputControl, _bEnable );
287 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::PrimaryButton, _bEnable );
288 0 : impl_markElementEnabledOrDisabled( _rPropertyName, _nElements & PropertyLineElement::SecondaryButton, _bEnable );
289 :
290 0 : impl_notifySingleUIChange();
291 : }
292 :
293 :
294 0 : void CachedInspectorUI::rebuildPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
295 : {
296 0 : MethodGuard aGuard( *this );
297 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
298 0 : return;
299 :
300 0 : aRebuiltProperties.insert( _rPropertyName );
301 :
302 0 : impl_notifySingleUIChange();
303 : }
304 :
305 :
306 0 : void CachedInspectorUI::showPropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
307 : {
308 0 : MethodGuard aGuard( *this );
309 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
310 0 : return;
311 :
312 0 : aShownProperties.insert( _rPropertyName );
313 : // if the same category has been hidden before, clear this information, since it's overruled
314 0 : aHiddenProperties.erase( _rPropertyName );
315 :
316 0 : impl_notifySingleUIChange();
317 : }
318 :
319 :
320 0 : void CachedInspectorUI::hidePropertyUI( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
321 : {
322 0 : MethodGuard aGuard( *this );
323 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
324 0 : return;
325 :
326 0 : aHiddenProperties.insert( _rPropertyName );
327 0 : impl_notifySingleUIChange();
328 : }
329 :
330 :
331 0 : void CachedInspectorUI::showCategory( const OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException, std::exception)
332 : {
333 0 : MethodGuard aGuard( *this );
334 :
335 0 : lcl_markStringKeyPositiveOrNegative( _rCategory, aShownCategories, aHiddenCategories, _bShow );
336 0 : impl_notifySingleUIChange();
337 0 : }
338 :
339 :
340 0 : Reference< XPropertyControl > SAL_CALL CachedInspectorUI::getPropertyControl( const OUString& _rPropertyName ) throw (RuntimeException, std::exception)
341 : {
342 0 : MethodGuard aGuard( *this );
343 0 : if ( !m_rMaster.shouldContinuePropertyHandling( _rPropertyName ) )
344 0 : return Reference< XPropertyControl >();
345 :
346 0 : return m_rMaster.getDelegatorUI()->getPropertyControl( _rPropertyName );
347 : }
348 :
349 :
350 0 : void SAL_CALL CachedInspectorUI::registerControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException, std::exception)
351 : {
352 : OSL_FAIL( "CachedInspectorUI::registerControlObserver: not expected to be called!" );
353 : // CachedInspectorUI is used as context for the controls, and we don't expect them to
354 : // register listeners themself
355 0 : m_rMaster.getDelegatorUI()->registerControlObserver( _Observer );
356 0 : }
357 :
358 :
359 0 : void SAL_CALL CachedInspectorUI::revokeControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException, std::exception)
360 : {
361 : OSL_FAIL( "CachedInspectorUI::revokeControlObserver: not expected to be called!" );
362 : // CachedInspectorUI is used as context for the controls, and we don't expect them to
363 : // register listeners themself
364 0 : m_rMaster.getDelegatorUI()->revokeControlObserver( _Observer );
365 0 : }
366 :
367 :
368 0 : void SAL_CALL CachedInspectorUI::setHelpSectionText( const OUString& _HelpText ) throw (NoSupportException, RuntimeException, std::exception)
369 : {
370 0 : m_rMaster.getDelegatorUI()->setHelpSectionText( _HelpText );
371 0 : }
372 :
373 :
374 : // HandlerMap
375 :
376 : typedef ::std::map < Reference< XPropertyHandler >
377 : , ::rtl::Reference< CachedInspectorUI >
378 : , HandlerLess
379 : > ImplMapHandlerToUI;
380 12 : struct MapHandlerToUI
381 : {
382 : ImplMapHandlerToUI aHandlers;
383 : };
384 :
385 6 : ComposedPropertyUIUpdate::ComposedPropertyUIUpdate( const Reference< XObjectInspectorUI >& _rxDelegatorUI,
386 : IPropertyExistenceCheck* _pPropertyCheck )
387 6 : :m_pCollectedUIs( new MapHandlerToUI )
388 : ,m_xDelegatorUI( _rxDelegatorUI )
389 : ,m_nSuspendCounter( 0 )
390 12 : ,m_pPropertyCheck( _pPropertyCheck )
391 : {
392 6 : if ( !m_xDelegatorUI.is() )
393 0 : throw NullPointerException();
394 6 : }
395 :
396 :
397 6 : ComposedPropertyUIUpdate::~ComposedPropertyUIUpdate( )
398 : {
399 6 : }
400 :
401 :
402 0 : Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getUIForPropertyHandler( const Reference< XPropertyHandler >& _rxHandler )
403 : {
404 0 : impl_checkDisposed();
405 :
406 0 : ::rtl::Reference< CachedInspectorUI >& rUI = m_pCollectedUIs->aHandlers[ _rxHandler ];
407 0 : if ( !rUI.is() )
408 0 : rUI = new CachedInspectorUI( *this, &ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw );
409 0 : return rUI.get();
410 : }
411 :
412 :
413 : namespace
414 : {
415 :
416 : // an STL-compatible structure which collects strings from a CachedInspectorUI instances
417 : struct StringBagCollector : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
418 : {
419 : private:
420 : StringBag& m_rBag;
421 : CachedInspectorUI::FGetStringBag m_pGetter;
422 :
423 : public:
424 0 : StringBagCollector( StringBag& _rBag, CachedInspectorUI::FGetStringBag _pGetter ) :m_rBag( _rBag ), m_pGetter( _pGetter ) { }
425 :
426 0 : void operator()( const ImplMapHandlerToUI::value_type& _rUI )
427 : {
428 0 : StringBag& rBag( ((_rUI.second.get())->*m_pGetter)() );
429 0 : m_rBag.insert( rBag.begin(), rBag.end() );
430 0 : }
431 :
432 0 : static void collectAll( StringBag& _rAll, const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
433 : {
434 0 : ::std::for_each( _rMap.begin(), _rMap.end(), StringBagCollector( _rAll, _pGetter ) );
435 0 : }
436 : };
437 :
438 :
439 : // an STL-compatible structure which cleans a certain string bag in a CachedInspectorUI instances
440 : struct StringBagClearer : public ::std::unary_function< ImplMapHandlerToUI::value_type, void >
441 : {
442 : private:
443 : CachedInspectorUI::FGetStringBag m_pGetter;
444 :
445 : public:
446 0 : StringBagClearer( CachedInspectorUI::FGetStringBag _pGetter ) :m_pGetter( _pGetter ) { }
447 :
448 0 : void operator()( const ImplMapHandlerToUI::value_type& _rUI )
449 : {
450 0 : clearContainer( ((_rUI.second.get())->*m_pGetter)() );
451 0 : }
452 :
453 0 : static void clearAll( const ImplMapHandlerToUI& _rMap, CachedInspectorUI::FGetStringBag _pGetter )
454 : {
455 0 : ::std::for_each( _rMap.begin(), _rMap.end(), StringBagClearer( _pGetter ) );
456 0 : }
457 : };
458 :
459 : // a typedef for a ->XObjectInspectorUI member function taking a string
460 : typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUISetter )( const OUString& );
461 :
462 :
463 : // an STL-compatible struct which calls a certain member method (taking a string) at a
464 : // given ->XObjectInspectorUI instance
465 0 : struct PropertyUIOperator : public ::std::unary_function< OUString, void >
466 : {
467 : private:
468 : Reference< XObjectInspectorUI > m_xUpdater;
469 : FPropertyUISetter m_pSetter;
470 :
471 : public:
472 0 : PropertyUIOperator( const Reference< XObjectInspectorUI >& _rxInspectorUI, FPropertyUISetter _pSetter )
473 : :m_xUpdater( _rxInspectorUI )
474 0 : ,m_pSetter( _pSetter )
475 : {
476 0 : }
477 :
478 0 : void operator()( const OUString& _rPropertyName )
479 : {
480 0 : ((m_xUpdater.get())->*m_pSetter)( _rPropertyName );
481 0 : }
482 :
483 0 : static void forEach( const StringBag& _rProperties, const Reference< XObjectInspectorUI >& _rxDelegatorUI, FPropertyUISetter _pSetter )
484 : {
485 0 : ::std::for_each( _rProperties.begin(), _rProperties.end(), PropertyUIOperator( _rxDelegatorUI, _pSetter ) );
486 0 : }
487 : };
488 :
489 :
490 : // an interface which encapsulates access to a single aspect of the ->XObjectInspectorUI,
491 : // where this aspect is given by a string key, and has a boolean value.
492 0 : class IStringKeyBooleanUIUpdate
493 : {
494 : public:
495 : virtual void updateUIForKey( const OUString& _rKey, bool _bFlag ) const = 0;
496 :
497 0 : virtual ~IStringKeyBooleanUIUpdate() { }
498 : };
499 :
500 :
501 : // FPropertyUIFlagSetter
502 :
503 : /** an implementation of the ->IStringKeyBooleanUIUpdate interface which,
504 : for a fixed ->XObjectInspectorUI instance and a fixed UI element (->PropertyLineElement),
505 : updates this element for a given property with a given boolean flag
506 : (->XObjectInspectorUI::enablePropertyUIElements)
507 : */
508 0 : class EnablePropertyUIElement : public IStringKeyBooleanUIUpdate
509 : {
510 : private:
511 : Reference< XObjectInspectorUI > m_xUIUpdate;
512 : sal_Int16 m_nElement;
513 :
514 : public:
515 0 : EnablePropertyUIElement( const Reference< XObjectInspectorUI >& _rxUIUpdate, sal_Int16 _nElement )
516 : :m_xUIUpdate( _rxUIUpdate )
517 0 : ,m_nElement( _nElement )
518 : {
519 0 : }
520 : // IStringKeyBooleanUIUpdate
521 : virtual void updateUIForKey( const OUString& _rKey, bool _bFlag ) const SAL_OVERRIDE;
522 : };
523 :
524 :
525 0 : void EnablePropertyUIElement::updateUIForKey( const OUString& _rKey, bool _bFlag ) const
526 : {
527 0 : m_xUIUpdate->enablePropertyUIElements( _rKey, m_nElement, _bFlag );
528 0 : }
529 :
530 :
531 : // a ->XObjectInspectorUI method taking a string and a boolean
532 : typedef void ( SAL_CALL XObjectInspectorUI::*FPropertyUIFlagSetter )( const OUString&, sal_Bool );
533 :
534 :
535 : // an implementaiton of the ->IStringKeyBooleanUIUpdate interface which calls
536 : // am arbitrary ->XObjectInspectorUI method taking a string and a boolean flag
537 0 : class DefaultStringKeyBooleanUIUpdate : public IStringKeyBooleanUIUpdate
538 : {
539 : private:
540 : Reference< XObjectInspectorUI > m_xUIUpdate;
541 : FPropertyUIFlagSetter m_pSetter;
542 :
543 : public:
544 : DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter );
545 : // IStringKeyBooleanUIUpdate
546 : virtual void updateUIForKey( const OUString& _rKey, bool _bFlag ) const SAL_OVERRIDE;
547 : };
548 :
549 :
550 0 : DefaultStringKeyBooleanUIUpdate::DefaultStringKeyBooleanUIUpdate( const Reference< XObjectInspectorUI >& _rxUIUpdate, FPropertyUIFlagSetter _pSetter )
551 : :m_xUIUpdate( _rxUIUpdate )
552 0 : ,m_pSetter( _pSetter )
553 : {
554 0 : }
555 :
556 :
557 0 : void DefaultStringKeyBooleanUIUpdate::updateUIForKey( const OUString& _rKey, bool _bFlag ) const
558 : {
559 0 : ((m_xUIUpdate.get())->*m_pSetter)( _rKey, _bFlag );
560 0 : }
561 :
562 :
563 : // an STL-compatible structure which applies a ->IStringKeyBooleanUIUpdate::updateUIForKey
564 : // operation with a fixed boolean value, for a given string value
565 : struct BooleanUIAspectUpdate : public ::std::unary_function< OUString, void >
566 : {
567 : private:
568 : const IStringKeyBooleanUIUpdate& m_rUpdater;
569 : bool m_bFlag;
570 :
571 : public:
572 0 : BooleanUIAspectUpdate( const IStringKeyBooleanUIUpdate& _rUpdater, bool _bFlag )
573 : :m_rUpdater( _rUpdater )
574 0 : ,m_bFlag( _bFlag )
575 : {
576 0 : }
577 :
578 0 : void operator()( const OUString& _rPropertyName )
579 : {
580 0 : m_rUpdater.updateUIForKey( _rPropertyName, m_bFlag );
581 0 : }
582 :
583 0 : static void forEach( const StringBag& _rProperties, const IStringKeyBooleanUIUpdate& _rUpdater, bool _bFlag )
584 : {
585 0 : ::std::for_each( _rProperties.begin(), _rProperties.end(), BooleanUIAspectUpdate( _rUpdater, _bFlag ) );
586 0 : }
587 : };
588 :
589 :
590 : // BooleanUIAspectUpdate
591 :
592 : // an STL-compatible structure subtracting a given string from a fixed ->StringBag
593 : struct StringBagComplement : public ::std::unary_function< OUString, void >
594 : {
595 : private:
596 : StringBag& m_rMinuend;
597 :
598 : public:
599 0 : StringBagComplement( StringBag& _rMinuend ) :m_rMinuend( _rMinuend ) { }
600 :
601 0 : void operator()( const OUString& _rPropertyToSubtract )
602 : {
603 0 : m_rMinuend.erase( _rPropertyToSubtract );
604 0 : }
605 :
606 0 : static void subtract( StringBag& _rMinuend, const StringBag& _rSubtrahend )
607 : {
608 0 : ::std::for_each( _rSubtrahend.begin(), _rSubtrahend.end(), StringBagComplement( _rMinuend ) );
609 0 : }
610 : };
611 :
612 :
613 : // BooleanUIAspectUpdate
614 :
615 0 : void lcl_fireUIStateFlag(
616 : const IStringKeyBooleanUIUpdate& _rUIUpdate,
617 : const ImplMapHandlerToUI& _rHandlerUIs,
618 : CachedInspectorUI::FGetStringBag _pGetPositives,
619 : CachedInspectorUI::FGetStringBag _pGetNegatives
620 : )
621 : {
622 : // all strings which are in the "positive" list of one handler
623 0 : StringBag aAllPositives;
624 0 : StringBagCollector::collectAll( aAllPositives, _rHandlerUIs, _pGetPositives );
625 :
626 : // all strings which are in the "negative" list of one handler
627 0 : StringBag aAllNegatives;
628 0 : StringBagCollector::collectAll( aAllNegatives, _rHandlerUIs, _pGetNegatives );
629 :
630 : // propagate the "negative" flags to the delegator UI
631 0 : BooleanUIAspectUpdate::forEach( aAllNegatives, _rUIUpdate, false );
632 :
633 : // propagate the "positive" flags to the delegator UI, for all elements where _no_
634 : // "negative" flag exists
635 0 : StringBagComplement::subtract( aAllPositives, aAllNegatives );
636 0 : BooleanUIAspectUpdate::forEach( aAllPositives, _rUIUpdate, true );
637 :
638 : // the "positive" request can be cleared no, only negative requests
639 : // (such as "disable a property" or "hide a category") need to be preserved for the next round
640 0 : StringBagClearer::clearAll( _rHandlerUIs, _pGetPositives );
641 0 : }
642 : }
643 :
644 :
645 0 : void ComposedPropertyUIUpdate::impl_fireEnablePropertyUI_throw()
646 : {
647 : lcl_fireUIStateFlag(
648 : DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::enablePropertyUI ),
649 0 : m_pCollectedUIs->aHandlers,
650 : &CachedInspectorUI::getEnabledProperties,
651 : &CachedInspectorUI::getDisabledProperties
652 0 : );
653 0 : }
654 :
655 :
656 0 : void ComposedPropertyUIUpdate::impl_fireRebuildPropertyUI_throw()
657 : {
658 : // collect all properties for which a rebuild request has been made
659 0 : StringBag aAllRebuilt;
660 0 : StringBagCollector::collectAll( aAllRebuilt, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );
661 :
662 : // rebuild all those properties
663 0 : PropertyUIOperator::forEach( aAllRebuilt, m_xDelegatorUI, &XObjectInspectorUI::rebuildPropertyUI );
664 :
665 : // clear the "properties to rebuild" at all handlers, since the request has been fulfilled now.
666 0 : StringBagClearer::clearAll( m_pCollectedUIs->aHandlers, &CachedInspectorUI::getRebuiltProperties );
667 0 : }
668 :
669 :
670 0 : void ComposedPropertyUIUpdate::impl_fireShowHidePropertyUI_throw()
671 : {
672 : // all properties which have been shown by at least one handler
673 0 : StringBag aAllShown;
674 0 : StringBagCollector::collectAll( aAllShown, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getShownProperties );
675 : // all properties which have been hidden by at least one handler
676 0 : StringBag aAllHidden;
677 0 : StringBagCollector::collectAll( aAllHidden, m_pCollectedUIs->aHandlers, &CachedInspectorUI::getHiddenProperties );
678 :
679 : // hide properties as necessary
680 0 : PropertyUIOperator::forEach( aAllHidden, m_xDelegatorUI, &XObjectInspectorUI::hidePropertyUI );
681 :
682 : // for those properties which are hidden, ignore all "show" requests which other handlers might have had
683 0 : StringBagComplement::subtract( aAllShown, aAllHidden );
684 :
685 : // show properties
686 0 : PropertyUIOperator::forEach( aAllShown, m_xDelegatorUI, &XObjectInspectorUI::showPropertyUI );
687 0 : }
688 :
689 :
690 0 : void ComposedPropertyUIUpdate::impl_fireShowCategory_throw()
691 : {
692 : lcl_fireUIStateFlag(
693 : DefaultStringKeyBooleanUIUpdate( m_xDelegatorUI, &XObjectInspectorUI::showCategory ),
694 0 : m_pCollectedUIs->aHandlers,
695 : &CachedInspectorUI::getShownCategories,
696 : &CachedInspectorUI::getHiddenCategories
697 0 : );
698 0 : }
699 :
700 :
701 0 : void ComposedPropertyUIUpdate::impl_fireEnablePropertyUIElements_throw()
702 : {
703 : lcl_fireUIStateFlag(
704 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::InputControl ),
705 0 : m_pCollectedUIs->aHandlers,
706 : &CachedInspectorUI::getEnabledInputControls,
707 : &CachedInspectorUI::getDisabledInputControls
708 0 : );
709 :
710 : lcl_fireUIStateFlag(
711 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::PrimaryButton ),
712 0 : m_pCollectedUIs->aHandlers,
713 : &CachedInspectorUI::getEnabledPrimaryButtons,
714 : &CachedInspectorUI::getDisabledPrimaryButtons
715 0 : );
716 :
717 : lcl_fireUIStateFlag(
718 : EnablePropertyUIElement( m_xDelegatorUI, PropertyLineElement::SecondaryButton ),
719 0 : m_pCollectedUIs->aHandlers,
720 : &CachedInspectorUI::getEnabledSecondaryButtons,
721 : &CachedInspectorUI::getDisabledSecondaryButtons
722 0 : );
723 0 : }
724 :
725 :
726 0 : void ComposedPropertyUIUpdate::impl_fireAll_throw()
727 : {
728 : OSL_PRECOND( !impl_isDisposed(), "ComposedPropertyUIUpdate::impl_fireAll_throw: already disposed, this will crash!" );
729 :
730 0 : impl_fireEnablePropertyUI_throw();
731 0 : impl_fireShowHidePropertyUI_throw();
732 0 : impl_fireRebuildPropertyUI_throw();
733 0 : impl_fireShowCategory_throw();
734 0 : impl_fireEnablePropertyUIElements_throw();
735 0 : }
736 :
737 :
738 0 : void SAL_CALL ComposedPropertyUIUpdate::suspendAutoFire()
739 : {
740 0 : impl_checkDisposed();
741 0 : osl_atomic_increment( &m_nSuspendCounter );
742 0 : }
743 :
744 :
745 0 : void SAL_CALL ComposedPropertyUIUpdate::resumeAutoFire()
746 : {
747 0 : impl_checkDisposed();
748 0 : if ( 0 == osl_atomic_decrement( &m_nSuspendCounter ) )
749 0 : impl_fireAll_throw();
750 0 : }
751 :
752 :
753 0 : void ComposedPropertyUIUpdate::impl_checkDisposed() const
754 : {
755 0 : if ( impl_isDisposed() )
756 0 : throw DisposedException();
757 0 : }
758 :
759 :
760 0 : void ComposedPropertyUIUpdate::callback_inspectorUIChanged_throw()
761 : {
762 0 : if ( 0 == m_nSuspendCounter )
763 0 : impl_fireAll_throw();
764 0 : }
765 :
766 :
767 0 : Reference< XObjectInspectorUI > ComposedPropertyUIUpdate::getDelegatorUI() const
768 : {
769 0 : impl_checkDisposed();
770 0 : return m_xDelegatorUI;
771 : }
772 :
773 :
774 6 : void SAL_CALL ComposedPropertyUIUpdate::dispose()
775 : {
776 6 : if ( impl_isDisposed() )
777 6 : return;
778 :
779 : OSL_ENSURE( m_nSuspendCounter == 0, "ComposedPropertyUIUpdate::dispose: still suspended, the changes will be lost!" );
780 :
781 18 : for ( ImplMapHandlerToUI::const_iterator singleUI = m_pCollectedUIs->aHandlers.begin();
782 12 : singleUI != m_pCollectedUIs->aHandlers.end();
783 : ++singleUI
784 : )
785 : {
786 0 : singleUI->second->dispose();
787 : }
788 6 : m_pCollectedUIs.reset();
789 6 : m_xDelegatorUI.set( NULL );
790 : }
791 :
792 :
793 0 : bool ComposedPropertyUIUpdate::shouldContinuePropertyHandling( const OUString& _rName ) const
794 : {
795 0 : if ( !m_pPropertyCheck )
796 0 : return true;
797 0 : if ( m_pPropertyCheck->hasPropertyByName( _rName ) )
798 0 : return true;
799 0 : return false;
800 : }
801 :
802 :
803 : } // namespace pcr
804 :
805 :
806 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|