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