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 #ifndef INCLUDED_FRAMEWORK_UNDOMANAGERHELPER_HXX
21 #define INCLUDED_FRAMEWORK_UNDOMANAGERHELPER_HXX
22 
23 #include <framework/fwedllapi.h>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/uno/Reference.hxx>
26 
27 #include <memory>
28 
29 namespace com::sun::star::document { class XUndoAction; }
30 namespace com::sun::star::document { class XUndoManager; }
31 namespace com::sun::star::document { class XUndoManagerListener; }
32 namespace com::sun::star::util { class XModifyListener; }
33 namespace framework { class IMutex; }
34 
35 class SfxUndoManager;
36 
37 
38 namespace framework
39 {
40 
41 
42     //= IMutexGuard
43 
44     class SAL_NO_VTABLE IMutexGuard
45     {
46     public:
47         /** clears the lock. If the guard does not currently hold the lock, nothing happens.
48         */
49         virtual void clear() = 0;
50 
51         /** returns the mutex guarded by the instance.
52 
53             Even if the guard currently has not a lock on the mutex, this method must succeed.
54         */
55         virtual IMutex& getGuardedMutex() = 0;
56 
57     protected:
~IMutexGuard()58         ~IMutexGuard() {}
59     };
60 
61 
62     //= IUndoManagerImplementation
63 
64     class SAL_NO_VTABLE IUndoManagerImplementation
65     {
66     public:
67         /** returns the SfxUndoManager interface to the actual Undo stack
68 
69             @throws css::lang::DisposedException
70                 when the instance is already disposed, and no SfxUndoManager can be provided
71 
72             @throws css::lang::NotInitializedException
73                 when the instance is not initialized, yet, and no SfxUndoManager can be provided
74         */
75         virtual SfxUndoManager&        getImplUndoManager() = 0;
76 
77         /** provides access to a UNO interface for the XUndoManager implementation. Used when throwing exceptions.
78         */
79         virtual css::uno::Reference< css::document::XUndoManager >
80                                         getThis() = 0;
81 
82     protected:
~IUndoManagerImplementation()83         ~IUndoManagerImplementation() {}
84     };
85 
86 
87     //= UndoManagerHelper
88 
89     class UndoManagerHelper_Impl;
90     /** helper class for implementing an XUndoManager
91 
92         Several of the methods of the class take an IMutexGuard instance. It is assumed that this guard has a lock on
93         its mutex at the moment the method is entered. The lock will be released before any notifications to the
94         registered XUndoManagerListeners happen.
95 
96         The following locking strategy is used for this mutex:
97         <ul><li>Any notifications to the registered XUndoManagerListeners are after the guard has been cleared. i.e.
98                 without the mutex being locked.</p>
99             <li>Any calls into the <code>SfxUndoManager</code> implementation is made without the mutex being locked.
100                 Note that this implies that the <code>SfxUndoManager</code> implementation must be thread-safe in itself
101                 (which is true for the default implementation, SfxUndoManager).</li>
102             <li>An exception to the previous item are the <member>SfxUndoManager::Undo</member> and
103                 <member>SfxUndoManager::Redo</member> methods: They're called with the given external mutex being
104                 locked.</li>
105         </ul>
106 
107         The reason for the exception for SfxUndoManager::Undo and SfxUndoManager::Redo is that those are expected to
108         modify the actual document which the UndoManager works for. And as long as our documents are not thread-safe,
109         and as long as we do not re-fit <strong>all</strong> existing SfxUndoImplementations to <em>not</em> expect
110         the dreaded SolarMutex being locked when they're called, the above behavior is a compromise between "how it should
111         be" and "how it can realistically be".
112     */
113     class FWE_DLLPUBLIC UndoManagerHelper
114     {
115     public:
116         UndoManagerHelper( IUndoManagerImplementation& i_undoManagerImpl );
117         ~UndoManagerHelper();
118 
119         // life time control
120         void disposing();
121 
122         // XUndoManager equivalents
123         void            enterUndoContext( const OUString& i_title, IMutexGuard& i_instanceLock );
124         void            enterHiddenUndoContext( IMutexGuard& i_instanceLock );
125         void            leaveUndoContext( IMutexGuard& i_instanceLock );
126         void            addUndoAction( const css::uno::Reference< css::document::XUndoAction >& i_action, IMutexGuard& i_instanceLock );
127         void            undo( IMutexGuard& i_instanceLock );
128         void            redo( IMutexGuard& i_instanceLock );
129         bool            isUndoPossible() const;
130         bool            isRedoPossible() const;
131         OUString getCurrentUndoActionTitle() const;
132         OUString getCurrentRedoActionTitle() const;
133         css::uno::Sequence< OUString >
134                         getAllUndoActionTitles() const;
135         css::uno::Sequence< OUString >
136                         getAllRedoActionTitles() const;
137         void            clear( IMutexGuard& i_instanceLock );
138         void            clearRedo( IMutexGuard& i_instanceLock );
139         void            reset( IMutexGuard& i_instanceLock );
140         void            addUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener );
141         void            removeUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener );
142 
143         // XLockable, base of XUndoManager, equivalents
144         void            lock();
145         void            unlock();
146         bool            isLocked();
147 
148         // XModifyBroadcaster equivalents
149         void            addModifyListener( const css::uno::Reference< css::util::XModifyListener >& i_listener );
150         void            removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& i_listener );
151 
152     private:
153         std::unique_ptr< UndoManagerHelper_Impl >   m_xImpl;
154     };
155 
156 
157 } // namespace framework
158 
159 
160 #endif // INCLUDED_FRAMEWORK_UNDOMANAGERHELPER_HXX
161 
162 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
163