1 /*
2  *  Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_command_utils.h"
20 
21 namespace KisCommandUtils
22 {
AggregateCommand(KUndo2Command * parent)23     AggregateCommand::AggregateCommand(KUndo2Command *parent)
24         : KUndo2Command(parent),
25           m_firstRedo(true) {}
26 
AggregateCommand(const KUndo2MagicString & text,KUndo2Command * parent)27     AggregateCommand::AggregateCommand(const KUndo2MagicString &text, KUndo2Command *parent)
28         : KUndo2Command(text, parent),
29           m_firstRedo(true) {}
30 
redo()31     void AggregateCommand::redo()
32     {
33         if (m_firstRedo) {
34             m_firstRedo = false;
35 
36             populateChildCommands();
37         }
38 
39         m_store.redoAll();
40     }
41 
undo()42     void AggregateCommand::undo()
43     {
44         m_store.undoAll();
45     }
46 
addCommand(KUndo2Command * cmd)47     void AggregateCommand::addCommand(KUndo2Command *cmd)
48     {
49         if (!cmd) return;
50         m_store.addCommand(cmd);
51     }
52 
LambdaCommand(std::function<KUndo2Command * ()> createCommandFunc)53     LambdaCommand::LambdaCommand(std::function<KUndo2Command*()> createCommandFunc)
54         : m_createCommandFunc(createCommandFunc)
55     {
56 
57     }
58 
LambdaCommand(const KUndo2MagicString & text,std::function<KUndo2Command * ()> createCommandFunc)59     LambdaCommand::LambdaCommand(const KUndo2MagicString &text,
60                                  std::function<KUndo2Command*()> createCommandFunc)
61         : AggregateCommand(text),
62           m_createCommandFunc(createCommandFunc)
63     {
64 
65     }
66 
LambdaCommand(const KUndo2MagicString & text,KUndo2Command * parent,std::function<KUndo2Command * ()> createCommandFunc)67     LambdaCommand::LambdaCommand(const KUndo2MagicString &text,
68                                  KUndo2Command *parent,
69                                  std::function<KUndo2Command*()> createCommandFunc)
70         : AggregateCommand(text, parent),
71           m_createCommandFunc(createCommandFunc)
72     {
73     }
74 
LambdaCommand(KUndo2Command * parent,std::function<KUndo2Command * ()> createCommandFunc)75     LambdaCommand::LambdaCommand(KUndo2Command *parent,
76                                  std::function<KUndo2Command*()> createCommandFunc)
77         : AggregateCommand(parent),
78           m_createCommandFunc(createCommandFunc)
79     {
80     }
81 
populateChildCommands()82     void LambdaCommand::populateChildCommands()
83     {
84         if (m_createCommandFunc) {
85             addCommand(m_createCommandFunc());
86         }
87     }
88 
SkipFirstRedoWrapper(KUndo2Command * child,KUndo2Command * parent)89     SkipFirstRedoWrapper::SkipFirstRedoWrapper(KUndo2Command *child, KUndo2Command *parent)
90         : KUndo2Command(child ? child->text() : kundo2_noi18n("<bug: unnamed command>"), parent), m_firstRedo(true), m_child(child) {}
91 
redo()92     void SkipFirstRedoWrapper::redo()
93     {
94         if (m_firstRedo) {
95             m_firstRedo = false;
96         } else {
97             if (m_child) {
98                 m_child->redo();
99             }
100             KUndo2Command::redo();
101         }
102     }
103 
undo()104     void SkipFirstRedoWrapper::undo()
105     {
106         KUndo2Command::undo();
107         if (m_child) {
108             m_child->undo();
109         }
110     }
111 
SkipFirstRedoBase(bool skipFirstRedo,KUndo2Command * parent)112     SkipFirstRedoBase::SkipFirstRedoBase(bool skipFirstRedo, KUndo2Command *parent)
113         : KUndo2Command(parent),
114           m_firstRedo(skipFirstRedo)
115     {
116     }
117 
SkipFirstRedoBase(bool skipFirstRedo,const KUndo2MagicString & text,KUndo2Command * parent)118     SkipFirstRedoBase::SkipFirstRedoBase(bool skipFirstRedo, const KUndo2MagicString &text, KUndo2Command *parent)
119         : KUndo2Command(text, parent),
120           m_firstRedo(skipFirstRedo)
121     {
122     }
123 
redo()124     void SkipFirstRedoBase::redo()
125     {
126         if (m_firstRedo) {
127             m_firstRedo = false;
128         } else {
129             redoImpl();
130             KUndo2Command::redo();
131         }
132     }
133 
undo()134     void SkipFirstRedoBase::undo()
135     {
136         KUndo2Command::undo();
137         undoImpl();
138     }
139 
setSkipOneRedo(bool value)140     void SkipFirstRedoBase::setSkipOneRedo(bool value)
141     {
142         m_firstRedo = value;
143     }
144 
FlipFlopCommand(bool finalizing,KUndo2Command * parent)145     FlipFlopCommand::FlipFlopCommand(bool finalizing, KUndo2Command *parent)
146         : KUndo2Command(parent)
147     {
148         m_currentState = finalizing ? State::FINALIZING : State::INITIALIZING;
149     }
150 
FlipFlopCommand(State initialState,KUndo2Command * parent)151     FlipFlopCommand::FlipFlopCommand(State initialState, KUndo2Command *parent)
152         : KUndo2Command(parent),
153           m_currentState(initialState)
154     {}
155 
redo()156     void FlipFlopCommand::redo()
157     {
158         if (m_currentState == FlipFlopCommand::State::INITIALIZING) {
159             partA();
160         } else {
161             partB();
162         }
163 
164         m_firstRedo = false;
165     }
166 
undo()167     void FlipFlopCommand::undo()
168     {
169         if (m_currentState == FlipFlopCommand::State::FINALIZING) {
170             partA();
171         } else {
172             partB();
173         }
174     }
175 
partA()176     void FlipFlopCommand::partA() {}
partB()177     void FlipFlopCommand::partB() {}
178 
CompositeCommand(KUndo2Command * parent)179     CompositeCommand::CompositeCommand(KUndo2Command *parent)
180         : KUndo2Command(parent) {}
181 
~CompositeCommand()182     CompositeCommand::~CompositeCommand() {
183         qDeleteAll(m_commands);
184     }
185 
addCommand(KUndo2Command * cmd)186     void CompositeCommand::addCommand(KUndo2Command *cmd) {
187         if (cmd) {
188             m_commands << cmd;
189         }
190     }
191 
redo()192     void CompositeCommand::redo() {
193         KUndo2Command::redo();
194         Q_FOREACH (KUndo2Command *cmd, m_commands) {
195             cmd->redo();
196         }
197     }
198 
undo()199     void CompositeCommand::undo() {
200         for (auto it = m_commands.rbegin(); it != m_commands.rend(); ++it) {
201             (*it)->undo();
202         }
203         KUndo2Command::undo();
204     }
205 
206 }
207