]> git.saurik.com Git - wxWidgets.git/blob - src/common/cmdproc.cpp
Fix for non-Mac builds.
[wxWidgets.git] / src / common / cmdproc.cpp
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
40 IMPLEMENT_CLASS(wxCommand, wxObject)
41 IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor, wxObject)
42
43 // ----------------------------------------------------------------------------
44 // wxCommand
45 // ----------------------------------------------------------------------------
46
47 wxCommand::wxCommand(bool canUndoIt, const wxString& name)
48 {
49 m_canUndo = canUndoIt;
50 m_commandName = name;
51 }
52
53 // ----------------------------------------------------------------------------
54 // Command processor
55 // ----------------------------------------------------------------------------
56
57 wxCommandProcessor::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
70 wxCommandProcessor::~wxCommandProcessor()
71 {
72 ClearCommands();
73 }
74
75 bool wxCommandProcessor::DoCommand(wxCommand& cmd)
76 {
77 return cmd.Do();
78 }
79
80 bool 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.
88 bool 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
108 void 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
150 bool 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
166 bool 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
206 bool wxCommandProcessor::CanUndo() const
207 {
208 wxCommand *command = GetCurrentCommand();
209
210 return command && command->CanUndo();
211 }
212
213 bool 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
227 void wxCommandProcessor::Initialize()
228 {
229 m_currentCommand = m_commands.GetLast();
230 SetMenuStrings();
231 }
232
233 void 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.
251 wxString 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.
274 wxString 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
311 void 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