1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef EXTENSIONS_SOURCE_PROPCTRLR_COMPOSEDUIUPDATE_HXX
29 #define EXTENSIONS_SOURCE_PROPCTRLR_COMPOSEDUIUPDATE_HXX
30 
31 #include "propertyhandler.hxx"
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
35 /** === end UNO includes === **/
36 
37 #include <map>
38 #include <set>
39 #include <memory>
40 
41 //........................................................................
42 namespace pcr
43 {
44 //........................................................................
45 
46     //====================================================================
47 	//= some helper types
48 	//====================================================================
49 
50     struct MapHandlerToUI;
51 
52     /** callback for an ComposedPropertyUIUpdate checking a given property for existence
53     */
54     class SAL_NO_VTABLE IPropertyExistenceCheck
55     {
56     public:
57         virtual ::sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw (::com::sun::star::uno::RuntimeException) = 0;
58     };
59 
60     //====================================================================
61 	//= ComposedPropertyUIUpdate
62 	//====================================================================
63     /** helper class composing requests to a ->XObjectInspectorUI interface, coming
64         from multiple sources
65 
66         Usually, a handler tells the browser UI to enable to disable, or show or hide, certain
67         elements. Now when multiple handlers do this, their instructions must be combined:
68         If one handler disables a certain element, but others enable it, it must in the
69         result still be disabled. Similar for showing/hiding elements.
70 
71         ->ComposedPropertyUIUpdate implements this combination. It does so by providing a dedicated
72         ->XObjectInspectorUI instance for every participating handler, and remembering the UI
73         state on a per-handler basis. Upon request (->fire), the combined UI state is
74         forwarded to another ->XObjectInspectorUI instance, the so-called delegator UI.
75     */
76     class ComposedPropertyUIUpdate
77     {
78     private:
79         ::std::auto_ptr< MapHandlerToUI >       m_pCollectedUIs;
80         ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >
81                                                 m_xDelegatorUI;
82         oslInterlockedCount                     m_nSuspendCounter;
83         IPropertyExistenceCheck*                m_pPropertyCheck;
84 
85     public:
86         /** constructs a ->ComposedPropertyUIUpdate instance
87             @param _rxDelegatorUI
88                 a ->XObjectInspectorUI instance to which composed UI requests should be forwarded. Must
89                 not be <NULL/>.
90             @param _pPropertyCheck
91                 an instance checking properties for existence. If this is not <NULL/>, it will be invoked
92                 whenever one of the ->XObjectInspectorUI methods is called, to check the passed property
93                 name.<br/>
94                 Beware of lifetime issues. The instance pointed to by <arg>_pPropertyCheck</arg> must
95                 live at least as long as the ->ComposedPropertyUIUpdate instance you're going to create.
96             @throws ::com::sun::star::lang::NullPointerException
97                 if ->_rxDelegatorUI is <NULL/>
98         */
99         ComposedPropertyUIUpdate(
100             const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxDelegatorUI,
101             IPropertyExistenceCheck* _pPropertyCheck );
102         ~ComposedPropertyUIUpdate();
103 
104         /** returns the delegator UI
105             @throw ::com::sun::star::lang::DisposedException
106         */
107         ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI > getDelegatorUI() const;
108 
109         /** returns a ->XObjectInspectorUI instance belonging to a given property handler
110 
111             In every call to an ->XPropertyHandler method which requires a ->XObjectInspectorUI,
112             the same UI instance should be used. The instance here will cache all requests passed
113             to it, and ->ComposedPropertyUIUpdate::fire will use the combination of all
114             cached UI states of all handlers to update the delegator UI.
115         */
116         ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >
117             getUIForPropertyHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyHandler >& _rxHandler );
118 
119         /** Suspends automatic firing of UI changes
120 
121             normally, as soon as any of the property handlers does a request for an
122             arbitrary UI change, the set of collected UI changes is evaluated, and the combined
123             UI state is fired to the delegator UI.
124 
125             You can disable this automatic firing by calling ->suspendAutoFire. As longs as auto
126             firing is suspended, only explicit ->fire calls trigger the notification to the
127             delegator UI.
128 
129             Note that calls to ->suspendAutoFire are culmulative, that is, if you make multiple calls
130             they must be accompanied by an equal number of calls to ->resumeAutoFire, to enable
131             auto-firing again.
132 
133             @seealso resumeAutoFire
134         */
135         void SAL_CALL suspendAutoFire();
136 
137         /** Suspends automatic firing of UI changes
138 
139             @seealso suspendAutoFire
140         */
141         void SAL_CALL resumeAutoFire();
142 
143         /** disposes the instance, so it becomes non-functional.
144 
145             All cached handlers and cached ->XObjectInspectorUI instances will be released,
146             the latter will also be disposed, so that if anybody still holds a reference to them
147             and tries to operate them will get a DisposedException.
148         */
149         void SAL_CALL dispose();
150 
151         /** invokes m_pPropertyCheck to check whether a given property should be handled
152         */
153         bool shouldContinuePropertyHandling( const ::rtl::OUString& _rName ) const;
154 
155     private:
156         /// determines whether the instance is already disposed
157         inline  bool impl_isDisposed() const { return m_pCollectedUIs.get() == NULL; }
158 
159         /// throws an exception if the component is already disposed
160                 void impl_checkDisposed() const;
161 
162         /** fires the collected UI changes to our delegator UI
163 
164             All operations for any elements are forwarded:
165             <ul><li>If an element has been hidden at least once, it's also hidden at the delegator UI.</li>
166                 <li>If an element has been shown at least once, and never been hidden, it's also
167                     shown at the delegator UI.</li>
168                 <li>If an element has never been shown or hidden, it's also not touched at the delegator UI.</li>
169                 <li>The same holds if you replace "hidden" in the last three items with "disabled",
170                     and "shown" with "enabled".</li>
171                 <li>If an element should have been rebuilt (->XObjectInspectorUI::rebuiltPropertyUI)
172                     at least once, it's rebuilt at the delegator UI, too.<br/>
173                     After that, the request to rebuild the UI for this property is cleared, so subsequent
174                     calls to ->fire will not trigger an new rebuilt request.
175             </ul>
176 
177             @precond
178                 instance is not disposed
179         */
180         void    impl_fireAll_throw();
181 
182         /// fires the combination of ->XObjectInspectorUI::enablePropertyUI calls
183         void    impl_fireEnablePropertyUI_throw();
184 
185         /// fires the combination of ->XObjectInspectorUI::enablePropertyUIElements calls
186         void    impl_fireEnablePropertyUIElements_throw();
187 
188         /// fires the combination of ->XObjectInspectorUI::rebuildPropertyUI calls
189         void    impl_fireRebuildPropertyUI_throw();
190 
191         /// fires the combination of ->XObjectInspectorUI::showPropertyUI and ->XObjectInspectorUI::hidePropertyUI calls
192         void    impl_fireShowHidePropertyUI_throw();
193 
194         /// fires the combination of ->XObjectInspectorUI::showCategory calls
195         void    impl_fireShowCategory_throw();
196 
197         /** callback for when a single property handler requested any change in the inspector UI
198         */
199         void    callback_inspectorUIChanged_throw();
200 
201     private:
202         ComposedPropertyUIUpdate();                                             // never implemented
203         ComposedPropertyUIUpdate( const ComposedPropertyUIUpdate& );            // never implemented
204         ComposedPropertyUIUpdate& operator=( const ComposedPropertyUIUpdate& ); // never implemented
205     };
206 
207     //====================================================================
208 	//= ComposedUIAutoFireGuard
209 	//====================================================================
210     class ComposedUIAutoFireGuard
211     {
212     private:
213         ComposedPropertyUIUpdate&   m_rUIUpdate;
214     public:
215         ComposedUIAutoFireGuard( ComposedPropertyUIUpdate& _rUIUpdate )
216             :m_rUIUpdate( _rUIUpdate )
217         {
218             m_rUIUpdate.suspendAutoFire();
219         }
220         ~ComposedUIAutoFireGuard()
221         {
222             m_rUIUpdate.resumeAutoFire();
223         }
224     };
225 
226 //........................................................................
227 } // namespace pcr
228 //........................................................................
229 
230 #endif // EXTENSIONS_SOURCE_PROPCTRLR_COMPOSEDUIUPDATE_HXX
231 
232