1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #pragma once
21 
22 #include <com/sun/star/uno/Reference.hxx>
23 #include <vcl/timer.hxx>
24 #include <memory>
25 #include <vector>
26 
27 namespace com::sun::star::drawing::framework
28 {
29 class XConfiguration;
30 }
31 namespace com::sun::star::drawing::framework
32 {
33 class XControllerManager;
34 }
35 namespace com::sun::star::drawing::framework
36 {
37 class XResourceId;
38 }
39 
40 namespace sd::framework
41 {
42 class ConfigurationClassifier;
43 class ConfigurationUpdaterLock;
44 class ConfigurationControllerResourceManager;
45 class ConfigurationControllerBroadcaster;
46 
47 /** This is a helper class for the ConfigurationController.  It handles the
48     update of the current configuration so that it looks like a requested
49     configuration.  An update is made by activating or deactivating drawing
50     framework resources.
51 
52     When an update is not successful, i.e. after the update the current
53     configuration is not equivalent to the requested configuration, then a
54     timer is started to repeat the update after a short time.
55 */
56 class ConfigurationUpdater
57 {
58 public:
59     /** Create a new ConfigurationUpdater object that notifies configuration
60         changes and the start and end of updates via the given broadcaster.
61     */
62     ConfigurationUpdater(
63         const std::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster,
64         const std::shared_ptr<ConfigurationControllerResourceManager>& rpResourceManager,
65         const css::uno::Reference<css::drawing::framework::XControllerManager>&
66             rxControllerManager);
67     ~ConfigurationUpdater();
68 
69     /** Request an update of the current configuration so that it looks like
70         the given requested configuration.  It checks whether an update of
71         the current configuration can be done.  Calls UpdateConfiguration()
72         if that is the case.  Otherwise it schedules a later call to
73         UpdateConfiguration().
74     */
75     void RequestUpdate(const css::uno::Reference<css::drawing::framework::XConfiguration>&
76                            rxRequestedConfiguration);
77 
78     const css::uno::Reference<css::drawing::framework::XConfiguration>&
GetCurrentConfiguration() const79     GetCurrentConfiguration() const
80     {
81         return mxCurrentConfiguration;
82     }
83 
84     friend class ConfigurationUpdaterLock;
85     /** Return a lock of the called ConfigurationUpdater.  While the
86         returned object exists no update of the current configuration is
87         made.
88     */
89     std::shared_ptr<ConfigurationUpdaterLock> GetLock();
90 
91 private:
92     /** A reference to the XControllerManager is kept so that
93         UpdateConfiguration() has access to the other sub controllers.
94     */
95     css::uno::Reference<css::drawing::framework::XControllerManager> mxControllerManager;
96 
97     std::shared_ptr<ConfigurationControllerBroadcaster> mpBroadcaster;
98 
99     /** The current configuration holds the resources that are currently
100         active.  It is modified during an update.
101     */
102     css::uno::Reference<css::drawing::framework::XConfiguration> mxCurrentConfiguration;
103 
104     /** The requested configuration holds the resources that have been
105         requested to activate or to deactivate since the last update.  It is
106         (usually) not modified during an update.  This configuration is
107         maintained by the ConfigurationController and given to the
108         ConfigurationUpdater in the RequestUpdate() method.
109     */
110     css::uno::Reference<css::drawing::framework::XConfiguration> mxRequestedConfiguration;
111 
112     /** This flag is set to </sal_True> when an update of the current
113         configuration was requested (because the last request in the queue
114         was processed) but could not be executed because the
115         ConfigurationController was locked.  A call to UpdateConfiguration()
116         resets the flag to </sal_False>.
117     */
118     bool mbUpdatePending;
119 
120     /** This flag is set to </sal_True> while the UpdateConfiguration() method
121         is running.  It is used to prevent reentrance problems with this
122         method.
123     */
124     bool mbUpdateBeingProcessed;
125 
126     /** The ConfigurationController is locked when this count has a value
127         larger then zero.  If the controller is locked then updates of the
128         current configuration are not made.
129     */
130     sal_Int32 mnLockCount;
131 
132     /** This timer is used to check from time to time whether the requested
133         configuration and the current configuration are identical and request
134         an update when they are not.
135         This is used to overcome problems with resources that become
136         available asynchronously.
137     */
138     Timer maUpdateTimer;
139 
140     /** The number of failed updates (those after which the current
141         configuration is not equivalent to the requested configuration) is
142         used to determine how long to wait before another update is made.
143     */
144     sal_Int32 mnFailedUpdateCount;
145 
146     std::shared_ptr<ConfigurationControllerResourceManager> mpResourceManager;
147 
148     /** This method does the main work of an update.  It calls the sub
149         controllers that are responsible for the various types of resources
150         and tells them to update their active resources.  It notifies
151         listeners about the start and end of the configuration update.
152     */
153     void UpdateConfiguration();
154 
155     /** Basically calls UpdaterStart() andUpdateEnd() and makes some debug
156         output.
157     */
158     void UpdateCore(const ConfigurationClassifier& rClassifier);
159 
160     /** Check for all pure anchors if they have at least one child.
161         Childless pure anchors are deactivated.
162         This affects only the current configuration.
163     */
164     void CheckPureAnchors(
165         const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration,
166         ::std::vector<css::uno::Reference<css::drawing::framework::XResourceId>>&
167             rResourcesToDeactivate);
168 
169     /** Remove from the requested configuration all pure anchors that have no
170         child.  Requested but not yet activated anchors can not be removed
171         because without the actual resource the 'pureness' of an anchor can
172         not be determined.
173     */
174     void CleanRequestedConfiguration();
175 
176     /** Check the success of a recently executed configuration update.
177         When the update failed then start the timer.
178     */
179     void CheckUpdateSuccess();
180 
181     /** This method sets the mbUpdateBeingProcessed member that is used to
182         prevent reentrance problems.  This method allows function objects
183         easily and safely to modify the variable.
184     */
185     void SetUpdateBeingProcessed(bool bValue);
186 
187     /** Return whether it is possible to do an update of the configuration.
188         This takes into account whether another update is currently being
189         executed, the lock count, and whether the configuration controller
190         is still valid.
191     */
192     bool IsUpdatePossible() const;
193 
194     /** Lock updates of the current configuration.  For intermediate requests
195         for updates mbUpdatePending is set to <TRUE/>.
196     */
197     void LockUpdates();
198 
199     /** When an update was requested since the last LockUpdates() call then
200         RequestUpdate() is called.
201     */
202     void UnlockUpdates();
203 
204     DECL_LINK(TimeoutHandler, Timer*, void);
205 };
206 
207 } // end of namespace sd::framework
208 
209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
210