]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/cmdproc.cpp
Remove unnecessary comparison of unsigned variable with 0.
[wxWidgets.git] / src / common / cmdproc.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/cmdproc.cpp
3// Purpose: wxCommand and wxCommandProcessor classes
4// Author: Julian Smart (extracted from docview.h by VZ)
5// Modified by:
6// Created: 05.11.00
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/intl.h"
29 #include "wx/string.h"
30 #include "wx/menu.h"
31 #include "wx/accel.h"
32#endif //WX_PRECOMP
33
34#include "wx/cmdproc.h"
35
36// ============================================================================
37// implementation
38// ============================================================================
39
40IMPLEMENT_CLASS(wxCommand, wxObject)
41IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor, wxObject)
42
43// ----------------------------------------------------------------------------
44// wxCommand
45// ----------------------------------------------------------------------------
46
47wxCommand::wxCommand(bool canUndoIt, const wxString& name)
48{
49 m_canUndo = canUndoIt;
50 m_commandName = name;
51}
52
53// ----------------------------------------------------------------------------
54// Command processor
55// ----------------------------------------------------------------------------
56
57wxCommandProcessor::wxCommandProcessor(int maxCommands)
58{
59 m_maxNoCommands = maxCommands;
60#if wxUSE_MENUS
61 m_commandEditMenu = NULL;
62#endif // wxUSE_MENUS
63 m_undoAccelerator = '\t' + wxAcceleratorEntry(wxACCEL_CTRL, 'Z').ToString();
64 m_redoAccelerator = '\t' + wxAcceleratorEntry(wxACCEL_CTRL, 'Y').ToString();
65
66 m_lastSavedCommand =
67 m_currentCommand = wxList::compatibility_iterator();
68}
69
70wxCommandProcessor::~wxCommandProcessor()
71{
72 ClearCommands();
73}
74
75bool wxCommandProcessor::DoCommand(wxCommand& cmd)
76{
77 return cmd.Do();
78}
79
80bool wxCommandProcessor::UndoCommand(wxCommand& cmd)
81{
82 return cmd.Undo();
83}
84
85// Pass a command to the processor. The processor calls Do();
86// if successful, is appended to the command history unless
87// storeIt is false.
88bool wxCommandProcessor::Submit(wxCommand *command, bool storeIt)
89{
90 wxCHECK_MSG( command, false, wxT("no command in wxCommandProcessor::Submit") );
91
92 if ( !DoCommand(*command) )
93 {
94 // the user code expects the command to be deleted anyhow
95 delete command;
96
97 return false;
98 }
99
100 if ( storeIt )
101 Store(command);
102 else
103 delete command;
104
105 return true;
106}
107
108void wxCommandProcessor::Store(wxCommand *command)
109{
110 wxCHECK_RET( command, wxT("no command in wxCommandProcessor::Store") );
111
112 if ( (int)m_commands.GetCount() == m_maxNoCommands )
113 {
114 wxList::compatibility_iterator firstNode = m_commands.GetFirst();
115 wxCommand *firstCommand = (wxCommand *)firstNode->GetData();
116 delete firstCommand;
117 m_commands.Erase(firstNode);
118
119 // Make sure m_lastSavedCommand won't point to freed memory
120 if ( m_lastSavedCommand == firstNode )
121 m_lastSavedCommand = wxList::compatibility_iterator();
122 }
123
124 // Correct a bug: we must chop off the current 'branch'
125 // so that we're at the end of the command list.
126 if (!m_currentCommand)
127 ClearCommands();
128 else
129 {
130 wxList::compatibility_iterator node = m_currentCommand->GetNext();
131 while (node)
132 {
133 wxList::compatibility_iterator next = node->GetNext();
134 delete (wxCommand *)node->GetData();
135 m_commands.Erase(node);
136
137 // Make sure m_lastSavedCommand won't point to freed memory
138 if ( m_lastSavedCommand == node )
139 m_lastSavedCommand = wxList::compatibility_iterator();
140
141 node = next;
142 }
143 }
144
145 m_commands.Append(command);
146 m_currentCommand = m_commands.GetLast();
147 SetMenuStrings();
148}
149
150bool wxCommandProcessor::Undo()
151{
152 wxCommand *command = GetCurrentCommand();
153 if ( command && command->CanUndo() )
154 {
155 if ( UndoCommand(*command) )
156 {
157 m_currentCommand = m_currentCommand->GetPrevious();
158 SetMenuStrings();
159 return true;
160 }
161 }
162
163 return false;
164}
165
166bool wxCommandProcessor::Redo()
167{
168 wxCommand *redoCommand = NULL;
169 wxList::compatibility_iterator redoNode
170#if !wxUSE_STL
171 = NULL // just to avoid warnings
172#endif // !wxUSE_STL
173 ;
174
175 if ( m_currentCommand )
176 {
177 // is there anything to redo?
178 if ( m_currentCommand->GetNext() )
179 {
180 redoCommand = (wxCommand *)m_currentCommand->GetNext()->GetData();
181 redoNode = m_currentCommand->GetNext();
182 }
183 }
184 else // no current command, redo the first one
185 {
186 if (m_commands.GetCount() > 0)
187 {
188 redoCommand = (wxCommand *)m_commands.GetFirst()->GetData();
189 redoNode = m_commands.GetFirst();
190 }
191 }
192
193 if (redoCommand)
194 {
195 bool success = DoCommand(*redoCommand);
196 if (success)
197 {
198 m_currentCommand = redoNode;
199 SetMenuStrings();
200 return true;
201 }
202 }
203 return false;
204}
205
206bool wxCommandProcessor::CanUndo() const
207{
208 wxCommand *command = GetCurrentCommand();
209
210 return command && command->CanUndo();
211}
212
213bool wxCommandProcessor::CanRedo() const
214{
215 if (m_currentCommand && !m_currentCommand->GetNext())
216 return false;
217
218 if (m_currentCommand && m_currentCommand->GetNext())
219 return true;
220
221 if (!m_currentCommand && (m_commands.GetCount() > 0))
222 return true;
223
224 return false;
225}
226
227void wxCommandProcessor::Initialize()
228{
229 m_currentCommand = m_commands.GetLast();
230 SetMenuStrings();
231}
232
233void wxCommandProcessor::SetMenuStrings()
234{
235#if wxUSE_MENUS
236 if (m_commandEditMenu)
237 {
238 wxString undoLabel = GetUndoMenuLabel();
239 wxString redoLabel = GetRedoMenuLabel();
240
241 m_commandEditMenu->SetLabel(wxID_UNDO, undoLabel);
242 m_commandEditMenu->Enable(wxID_UNDO, CanUndo());
243
244 m_commandEditMenu->SetLabel(wxID_REDO, redoLabel);
245 m_commandEditMenu->Enable(wxID_REDO, CanRedo());
246 }
247#endif // wxUSE_MENUS
248}
249
250// Gets the current Undo menu label.
251wxString wxCommandProcessor::GetUndoMenuLabel() const
252{
253 wxString buf;
254 if (m_currentCommand)
255 {
256 wxCommand *command = (wxCommand *)m_currentCommand->GetData();
257 wxString commandName(command->GetName());
258 if (commandName.empty()) commandName = _("Unnamed command");
259 bool canUndo = command->CanUndo();
260 if (canUndo)
261 buf = wxString(_("&Undo ")) + commandName + m_undoAccelerator;
262 else
263 buf = wxString(_("Can't &Undo ")) + commandName + m_undoAccelerator;
264 }
265 else
266 {
267 buf = _("&Undo") + m_undoAccelerator;
268 }
269
270 return buf;
271}
272
273// Gets the current Undo menu label.
274wxString wxCommandProcessor::GetRedoMenuLabel() const
275{
276 wxString buf;
277 if (m_currentCommand)
278 {
279 // We can redo, if we're not at the end of the history.
280 if (m_currentCommand->GetNext())
281 {
282 wxCommand *redoCommand = (wxCommand *)m_currentCommand->GetNext()->GetData();
283 wxString redoCommandName(redoCommand->GetName());
284 if (redoCommandName.empty()) redoCommandName = _("Unnamed command");
285 buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator;
286 }
287 else
288 {
289 buf = _("&Redo") + m_redoAccelerator;
290 }
291 }
292 else
293 {
294 if (m_commands.GetCount() == 0)
295 {
296 buf = _("&Redo") + m_redoAccelerator;
297 }
298 else
299 {
300 // currentCommand is NULL but there are commands: this means that
301 // we've undone to the start of the list, but can redo the first.
302 wxCommand *redoCommand = (wxCommand *)m_commands.GetFirst()->GetData();
303 wxString redoCommandName(redoCommand->GetName());
304 if (redoCommandName.empty()) redoCommandName = _("Unnamed command");
305 buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator;
306 }
307 }
308 return buf;
309}
310
311void wxCommandProcessor::ClearCommands()
312{
313 wxList::compatibility_iterator node = m_commands.GetFirst();
314 while (node)
315 {
316 wxCommand *command = (wxCommand *)node->GetData();
317 delete command;
318 m_commands.Erase(node);
319 node = m_commands.GetFirst();
320 }
321
322 m_currentCommand = wxList::compatibility_iterator();
323 m_lastSavedCommand = wxList::compatibility_iterator();
324}
325
326