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