1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_EXTENSIONS_SOURCE_PROPCTRLR_PROPCONTROLLER_HXX
#define INCLUDED_EXTENSIONS_SOURCE_PROPCTRLR_PROPCONTROLLER_HXX

#include "composeduiupdate.hxx"
#include "proplinelistener.hxx"
#include "propcontrolobserver.hxx"
#include "browserview.hxx"

#include <com/sun/star/awt/XFocusListener.hpp>
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/awt/XLayoutConstrains.hpp>
#include <com/sun/star/inspection/XPropertyControlFactory.hpp>
#include <com/sun/star/inspection/XObjectInspector.hpp>
#include <com/sun/star/inspection/XObjectInspectorUI.hpp>
#include <com/sun/star/inspection/XPropertyHandler.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/uno3.hxx>
#include <cppuhelper/implbase.hxx>
#include <comphelper/broadcasthelper.hxx>
#include <vcl/weld.hxx>

#include <map>
#include <memory>
#include <unordered_map>
#include <vector>

namespace pcr
{
    class OPropertyEditor;
    struct OLineDescriptor;

    typedef ::cppu::WeakImplHelper <   css::lang::XServiceInfo
                                    ,   css::awt::XFocusListener
                                    ,   css::awt::XLayoutConstrains
                                    ,   css::beans::XPropertyChangeListener
                                    ,   css::inspection::XPropertyControlFactory
                                    ,   css::inspection::XObjectInspector
                                    ,   css::lang::XInitialization
                                    >   OPropertyBrowserController_Base;

    class OPropertyBrowserController
                :public ::comphelper::OMutexAndBroadcastHelper
                ,public OPropertyBrowserController_Base
                ,public css::inspection::XObjectInspectorUI
                    // that's intentionally *not* part of the OPropertyBrowserController_Base
                    // We do not want this to be available in queryInterface, getTypes, and the like.
                ,public IPropertyLineListener
                ,public IPropertyControlObserver
                ,public IPropertyExistenceCheck
    {
    private:
        typedef std::multimap< sal_Int32, css::beans::Property >  OrderedPropertyMap;
        typedef std::vector< css::uno::Reference< css::uno::XInterface > >
                                                                            InterfaceArray;

    protected:
        css::uno::Reference< css::uno::XComponentContext > m_xContext;

    private:
        css::uno::Reference< css::frame::XFrame > m_xFrame;
        css::uno::Reference< css::awt::XWindow >  m_xView;

        ::comphelper::OInterfaceContainerHelper2   m_aDisposeListeners;
        ::comphelper::OInterfaceContainerHelper2   m_aControlObservers;
        // meta data about the properties
        std::unique_ptr<weld::Builder> m_xBuilder;
        std::unique_ptr<OPropertyBrowserView> m_xPropView;

        OUString                     m_sPageSelection;
        OUString                     m_sLastValidPageSelection;

        typedef css::uno::Reference< css::inspection::XPropertyHandler >
                                                        PropertyHandlerRef;
        typedef std::vector< PropertyHandlerRef >     PropertyHandlerArray;
        typedef std::unordered_map< OUString, PropertyHandlerRef >
                                                        PropertyHandlerRepository;
        typedef std::unordered_multimap< OUString, PropertyHandlerRef >
                                                        PropertyHandlerMultiRepository;
        PropertyHandlerRepository                       m_aPropertyHandlers;
        PropertyHandlerMultiRepository                  m_aDependencyHandlers;
        PropertyHandlerRef                              m_xInteractiveHandler;

        std::unique_ptr< ComposedPropertyUIUpdate >   m_pUIRequestComposer;

        /// our InspectorModel
        css::uno::Reference< css::inspection::XObjectInspectorModel >
                                                        m_xModel;
        /// the object(s) we're currently inspecting
        InterfaceArray                                  m_aInspectedObjects;
        /// the properties of the currently inspected object(s)
        OrderedPropertyMap                              m_aProperties;
        /// the property we're just committing
        OUString                                        m_sCommittingProperty;

        typedef std::unordered_map< OUString, sal_uInt16 >     HashString2Int16;
        HashString2Int16                                m_aPageIds;

        bool        m_bContainerFocusListening;
        bool        m_bSuspendingPropertyHandlers;
        bool        m_bConstructed;
        bool        m_bBindingIntrospectee;

    protected:
        DECLARE_XINTERFACE()<--- There is an unknown macro here somewhere. Configuration is required. If DECLARE_XINTERFACE is a macro then please configure it.<--- There is an unknown macro here somewhere. Configuration is required. If DECLARE_XINTERFACE is a macro then please configure it.

        // XServiceInfo
        virtual OUString SAL_CALL getImplementationName(  ) override;
        virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
        virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;

        // XController
        virtual void SAL_CALL attachFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) override;
        virtual sal_Bool SAL_CALL attachModel( const css::uno::Reference< css::frame::XModel >& xModel ) override;
        virtual sal_Bool SAL_CALL suspend( sal_Bool bSuspend ) override;
        virtual css::uno::Any SAL_CALL getViewData(  ) override;
        virtual void SAL_CALL restoreViewData( const css::uno::Any& Data ) override;
        virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel(  ) override;
        virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getFrame(  ) override;

        // XComponent
        virtual void SAL_CALL dispose(  ) override;
        virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
        virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;

        // XFocusListener
        virtual void SAL_CALL focusGained( const css::awt::FocusEvent& _rSource ) override;
        virtual void SAL_CALL focusLost( const css::awt::FocusEvent& _rSource ) override;

        // XEventListener
        virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;

        // XLayoutConstrains
        virtual css::awt::Size SAL_CALL getMinimumSize(  ) override;
        virtual css::awt::Size SAL_CALL getPreferredSize(  ) override;
        virtual css::awt::Size SAL_CALL calcAdjustedSize( const css::awt::Size& rNewSize ) override;

        // XPropertyChangeListener
        virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& _rEvent ) override;

        /** XPropertyControlFactory
        */
        virtual css::uno::Reference< css::inspection::XPropertyControl > SAL_CALL createPropertyControl( ::sal_Int16 ControlType, sal_Bool CreateReadOnly ) override;

    public:
        explicit OPropertyBrowserController(
            const css::uno::Reference< css::uno::XComponentContext >& _rxContext);

    protected:
        virtual ~OPropertyBrowserController() override;

    public:
        // XServiceInfo - static versions
        /// @throws css::uno::RuntimeException
        static OUString getImplementationName_static(  );
        /// @throws css::uno::RuntimeException
        static css::uno::Sequence< OUString > getSupportedServiceNames_static(  );
        static css::uno::Reference< css::uno::XInterface >
                        Create(const css::uno::Reference< css::uno::XComponentContext >&);

    protected:
        // IPropertyLineListener
        virtual void    Clicked(    const OUString& _rName, bool _bPrimary ) override;
        virtual void    Commit(     const OUString& _rName, const css::uno::Any& _rVal ) override;

        // IPropertyControlObserver
        virtual void    focusGained( const css::uno::Reference< css::inspection::XPropertyControl >& Control ) override;
        virtual void    valueChanged( const css::uno::Reference< css::inspection::XPropertyControl >& Control ) override;

        // IPropertyExistenceCheck
        virtual bool hasPropertyByName( const OUString& _rName ) override;

        // XObjectInspectorUI
        virtual void SAL_CALL enablePropertyUI( const OUString& _rPropertyName, sal_Bool _bEnable ) override;
        virtual void SAL_CALL enablePropertyUIElements( const OUString& _rPropertyName, ::sal_Int16 _nElements, sal_Bool _bEnable ) override;
        virtual void SAL_CALL rebuildPropertyUI( const OUString& _rPropertyName ) override;
        virtual void SAL_CALL showPropertyUI( const OUString& _rPropertyName ) override;
        virtual void SAL_CALL hidePropertyUI( const OUString& _rPropertyName ) override;
        virtual void SAL_CALL showCategory( const OUString& _rCategory, sal_Bool _bShow ) override;
        virtual css::uno::Reference< css::inspection::XPropertyControl > SAL_CALL getPropertyControl( const OUString& _rPropertyName ) override;
        virtual void SAL_CALL registerControlObserver( const css::uno::Reference< css::inspection::XPropertyControlObserver >& Observer ) override;
        virtual void SAL_CALL revokeControlObserver( const css::uno::Reference< css::inspection::XPropertyControlObserver >& Observer ) override;
        virtual void SAL_CALL setHelpSectionText( const OUString& HelpText ) override;

        // XObjectInspector
        virtual css::uno::Reference< css::inspection::XObjectInspectorModel > SAL_CALL getInspectorModel() override;
        virtual void SAL_CALL setInspectorModel( const css::uno::Reference< css::inspection::XObjectInspectorModel >& _inspectormodel ) override;
        virtual css::uno::Reference< css::inspection::XObjectInspectorUI > SAL_CALL getInspectorUI() override;
        virtual void SAL_CALL inspect( const css::uno::Sequence< css::uno::Reference< css::uno::XInterface > >& Objects ) override;

        // XDispatchProvider
        virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& URL, const OUString& TargetFrameName, ::sal_Int32 SearchFlags ) override;
        virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& Requests ) override;

        // XInitialization
        virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;

    private:
        void UpdateUI();

        void startContainerWindowListening();
        void stopContainerWindowListening();

        // stop the inspection
        void stopInspection( bool _bCommitModified );

        bool haveView() const { return bool(m_xPropView); }
        OPropertyEditor&    getPropertyBox() { return m_xPropView->getPropertyBox(); }

        // does the inspection of the objects as indicated by our model
        void doInspection();

        // bind the browser to m_xIntrospecteeAsProperty
        void    impl_rebindToInspectee_nothrow( const InterfaceArray& _rObjects );

        /** retrieves special property handlers for our introspectee
        */
        void    getPropertyHandlers( const InterfaceArray& _rObjects, PropertyHandlerArray& _rHandlers );

        /** called when a property changed, to broadcast any handlers which might have
            registered for this property

            @param _bFirstTimeInit
                if set to <FALSE/>, this is a real change in the property value, not just a call
                for purposes of initialization.
        */
        void    impl_broadcastPropertyChange_nothrow( const OUString& _rPropertyName, const css::uno::Any& _rNewValue, const css::uno::Any& _rOldValue, bool _bFirstTimeInit ) const;

        /** determines whether the given property is an actuating property, that is, at least one
            handler expressed interest in changes to this property's value.
        */
        bool impl_isActuatingProperty_nothrow( const OUString& _rPropertyName ) const
        {
            return ( m_aDependencyHandlers.find( _rPropertyName ) != m_aDependencyHandlers.end() );
        }

        /** retrieves the value of the given property, by asking the appropriate XPropertyHandler
            @param  _rPropertyName
                the name whose handler is to be obtained. Must be the name of a property
                for which a handler is registered.
            @throws
                RuntimeException if there is no handler for the given property
            @return
                the value of this property
        */
        css::uno::Any
                        impl_getPropertyValue_throw( const OUString& _rPropertyName );

        /// calls XPropertyHandler::suspend for all our property handlers
        bool    suspendPropertyHandlers_nothrow( bool _bSuspend );

        /// suspends the complete inspector
        bool    suspendAll_nothrow();

        /** selects a page according to our current view data
        */
        void selectPageFromViewData();

        /** updates our view data from the currently active page
        */
        void updateViewDataFromActivePage();

        /// describes the UI for the given property
        void describePropertyLine( const css::beans::Property& _rPropertyName, OLineDescriptor& _rDescriptor );

        /** retrieves the position of the property given by name in m_aProperties
            @return
                <TRUE/> if and only if the property could be found. In this case, <arg>_pProperty</arg> (if
                not <NULL/> contains the iterator pointing to this property.
        */
        bool impl_findObjectProperty_nothrow( const OUString& _rName, OrderedPropertyMap::const_iterator* _pProperty = nullptr );

        void Construct(const css::uno::Reference<css::awt::XWindow>& rContainerWindow, std::unique_ptr<weld::Builder> xBuilder);

        /** retrieves the property handler for a given property name
            @param  _rPropertyName
                the name whose handler is to be obtained. Must be the name of a property
                for which a handler is registered.
            @throws
                RuntimeException if there is no handler for the given property
            @return
                the handler which is responsible for the given property
        */
        PropertyHandlerRef const &
            impl_getHandlerForProperty_throw( const OUString& _rPropertyName ) const;

        /** determines whether we have a handler for the given property
            @param _rPropertyName
                the name of the property for which the existence of a handler should be checked
        */
        bool
            impl_hasPropertyHandlerFor_nothrow( const OUString& _rPropertyName ) const;

        /** builds up m_aPageIds from InspectorModel::describeCategories, and insert all the
            respective tab pages into our view
            @precond
                m_aPageIds is empty
            @throws css::uno::RuntimeException
                if one of the callees of this method throws this exception
        */
        void
            impl_buildCategories_throw();

        /** retrieves the id of the tab page which represents a given category.
            @param  _rCategoryName
                the programmatic name of a category.
            @return
                the id of the tab page, or <code>(sal_uInt16)-1</code> if there
                is no tab page for the given category
        */
        sal_uInt16
            impl_getPageIdForCategory_nothrow( const OUString& _rCategoryName ) const;

        /** adds or removes ourself as XEventListener to/from all our inspectees
        */
        void    impl_toggleInspecteeListening_nothrow( bool _bOn );

        /** binds the instance to a new model
        */
        void    impl_bindToNewModel_nothrow( const css::uno::Reference< css::inspection::XObjectInspectorModel >& _rxInspectorModel );

        /** initializes our view, as indicated by the model's view-relevant properties

            It's allowed to call this method when no model exists, yet. In this case, nothing
            happens.
        */
        void    impl_initializeView_nothrow();

        /** determines whether the view should be readonly.

            Effectively, this means that the method simply checks the IsReadOnly attribute of the model.
            If there is no model, <FALSE/> is returned.

            @throws css::uno::RuntimeException
                in case asking the model for its IsReadOnly attribute throws a css::uno::RuntimeException
                itself.
        */
        bool    impl_isReadOnlyModel_throw() const;

        /** starts or stops listening at the model
        */
        void    impl_startOrStopModelListening_nothrow( bool _bDoListen ) const;

    private:
        DECL_LINK(OnPageActivation, LinkParamNone*, void);

    private:
        // constructors
        void    createWithModel( const css::uno::Reference< css::inspection::XObjectInspectorModel >& _rxModel );
    };


} // namespace pcr


#endif // INCLUDED_EXTENSIONS_SOURCE_PROPCTRLR_PROPCONTROLLER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */