diff options
Diffstat (limited to 'extensions/source/propctrlr/composeduiupdate.hxx')
-rw-r--r-- | extensions/source/propctrlr/composeduiupdate.hxx | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/extensions/source/propctrlr/composeduiupdate.hxx b/extensions/source/propctrlr/composeduiupdate.hxx new file mode 100644 index 000000000..5e356af1f --- /dev/null +++ b/extensions/source/propctrlr/composeduiupdate.hxx @@ -0,0 +1,208 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/inspection/XObjectInspectorUI.hpp> +#include <com/sun/star/inspection/XPropertyHandler.hpp> + +#include <memory> + + +namespace pcr +{ + + struct MapHandlerToUI; + + /** callback for a ComposedPropertyUIUpdate checking a given property for existence + */ + class SAL_NO_VTABLE IPropertyExistenceCheck + { + public: + /// @throws css::uno::RuntimeException + virtual bool hasPropertyByName( const OUString& _rName ) = 0; + + protected: + ~IPropertyExistenceCheck() {} + }; + + /** helper class composing requests to a ->XObjectInspectorUI interface, coming + from multiple sources + + Usually, a handler tells the browser UI to enable to disable, or show or hide, certain + elements. Now when multiple handlers do this, their instructions must be combined: + If one handler disables a certain element, but others enable it, it must in the + result still be disabled. Similar for showing/hiding elements. + + ->ComposedPropertyUIUpdate implements this combination. It does so by providing a dedicated + ->XObjectInspectorUI instance for every participating handler, and remembering the UI + state on a per-handler basis. Upon request (->fire), the combined UI state is + forwarded to another ->XObjectInspectorUI instance, the so-called delegator UI. + */ + class ComposedPropertyUIUpdate + { + private: + std::unique_ptr< MapHandlerToUI > m_pCollectedUIs; + css::uno::Reference< css::inspection::XObjectInspectorUI > + m_xDelegatorUI; + oslInterlockedCount m_nSuspendCounter; + IPropertyExistenceCheck* m_pPropertyCheck; + + public: + /** constructs a ->ComposedPropertyUIUpdate instance + @param _rxDelegatorUI + a ->XObjectInspectorUI instance to which composed UI requests should be forwarded. Must + not be <NULL/>. + @param _pPropertyCheck + an instance checking properties for existence. If this is not <NULL/>, it will be invoked + whenever one of the ->XObjectInspectorUI methods is called, to check the passed property + name.<br/> + Beware of lifetime issues. The instance pointed to by <arg>_pPropertyCheck</arg> must + live at least as long as the ->ComposedPropertyUIUpdate instance you're going to create. + @throws css::lang::NullPointerException + if ->_rxDelegatorUI is <NULL/> + */ + ComposedPropertyUIUpdate( + const css::uno::Reference< css::inspection::XObjectInspectorUI >& _rxDelegatorUI, + IPropertyExistenceCheck* _pPropertyCheck ); + ~ComposedPropertyUIUpdate(); + + /** returns the delegator UI + @throw css::lang::DisposedException + */ + css::uno::Reference< css::inspection::XObjectInspectorUI > const & getDelegatorUI() const; + + /** returns a ->XObjectInspectorUI instance belonging to a given property handler + + In every call to an ->XPropertyHandler method which requires a ->XObjectInspectorUI, + the same UI instance should be used. The instance here will cache all requests passed + to it, and ->ComposedPropertyUIUpdate::fire will use the combination of all + cached UI states of all handlers to update the delegator UI. + */ + css::uno::Reference< css::inspection::XObjectInspectorUI > + getUIForPropertyHandler( const css::uno::Reference< css::inspection::XPropertyHandler >& _rxHandler ); + + /** Suspends automatic firing of UI changes + + normally, as soon as any of the property handlers does a request for an + arbitrary UI change, the set of collected UI changes is evaluated, and the combined + UI state is fired to the delegator UI. + + You can disable this automatic firing by calling ->suspendAutoFire. As longs as auto + firing is suspended, only explicit ->fire calls trigger the notification to the + delegator UI. + + Note that calls to ->suspendAutoFire are cumulative, that is, if you make multiple calls + they must be accompanied by an equal number of calls to ->resumeAutoFire, to enable + auto-firing again. + + @seealso resumeAutoFire + */ + void suspendAutoFire(); + + /** Suspends automatic firing of UI changes + + @seealso suspendAutoFire + */ + void resumeAutoFire(); + + /** disposes the instance, so it becomes non-functional. + + All cached handlers and cached ->XObjectInspectorUI instances will be released, + the latter will also be disposed, so that if anybody still holds a reference to them + and tries to operate them will get a DisposedException. + */ + void dispose(); + + /** invokes m_pPropertyCheck to check whether a given property should be handled + */ + bool shouldContinuePropertyHandling( const OUString& _rName ) const; + + private: + /// determines whether the instance is already disposed + bool impl_isDisposed() const { return !m_pCollectedUIs; } + + /// throws an exception if the component is already disposed + void impl_checkDisposed() const; + + /** fires the collected UI changes to our delegator UI + + All operations for any elements are forwarded: + <ul><li>If an element has been hidden at least once, it's also hidden at the delegator UI.</li> + <li>If an element has been shown at least once, and never been hidden, it's also + shown at the delegator UI.</li> + <li>If an element has never been shown or hidden, it's also not touched at the delegator UI.</li> + <li>The same holds if you replace "hidden" in the last three items with "disabled", + and "shown" with "enabled".</li> + <li>If an element should have been rebuilt (->XObjectInspectorUI::rebuiltPropertyUI) + at least once, it's rebuilt at the delegator UI, too.<br/> + After that, the request to rebuild the UI for this property is cleared, so subsequent + calls to ->fire will not trigger a new rebuilt request. + </ul> + + @precond + instance is not disposed + */ + void impl_fireAll_throw(); + + /// fires the combination of ->XObjectInspectorUI::enablePropertyUI calls + void impl_fireEnablePropertyUI_throw(); + + /// fires the combination of ->XObjectInspectorUI::enablePropertyUIElements calls + void impl_fireEnablePropertyUIElements_throw(); + + /// fires the combination of ->XObjectInspectorUI::rebuildPropertyUI calls + void impl_fireRebuildPropertyUI_throw(); + + /// fires the combination of ->XObjectInspectorUI::showPropertyUI and ->XObjectInspectorUI::hidePropertyUI calls + void impl_fireShowHidePropertyUI_throw(); + + /// fires the combination of ->XObjectInspectorUI::showCategory calls + void impl_fireShowCategory_throw(); + + /** callback for when a single property handler requested any change in the inspector UI + */ + void callback_inspectorUIChanged_throw(); + + private: + ComposedPropertyUIUpdate( const ComposedPropertyUIUpdate& ) = delete; + ComposedPropertyUIUpdate& operator=( const ComposedPropertyUIUpdate& ) = delete; + }; + + class ComposedUIAutoFireGuard + { + private: + ComposedPropertyUIUpdate& m_rUIUpdate; + public: + explicit ComposedUIAutoFireGuard( ComposedPropertyUIUpdate& _rUIUpdate ) + :m_rUIUpdate( _rUIUpdate ) + { + m_rUIUpdate.suspendAutoFire(); + } + ~ComposedUIAutoFireGuard() COVERITY_NOEXCEPT_FALSE + { + m_rUIUpdate.resumeAutoFire(); + } + }; + + +} // namespace pcr + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |