]>
git.saurik.com Git - wxWidgets.git/blob - src/common/cmdproc.cpp
4326cda8093744de433fed184961a292363e27ba
   1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/cmdproc.cpp 
   3 // Purpose:     wxCommand and wxCommandProcessor classes 
   4 // Author:      Julian Smart (extracted from docview.h by VZ) 
   8 // Copyright:   (c) wxWindows team 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "cmdproc.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/string.h" 
  37 #include "wx/cmdproc.h" 
  39 // ============================================================================ 
  41 // ============================================================================ 
  43 IMPLEMENT_CLASS(wxCommand
, wxObject
) 
  44 IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor
, wxObject
) 
  46 // ---------------------------------------------------------------------------- 
  48 // ---------------------------------------------------------------------------- 
  50 wxCommand::wxCommand(bool canUndoIt
, const wxString
& name
) 
  52     m_canUndo 
= canUndoIt
; 
  56 wxCommand::~wxCommand() 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  64 wxCommandProcessor::wxCommandProcessor(int maxCommands
) 
  66     m_maxNoCommands 
= maxCommands
; 
  67     m_currentCommand 
= (wxNode 
*) NULL
; 
  69     m_commandEditMenu 
= (wxMenu 
*) NULL
; 
  71     m_undoAccelerator 
= wxT("\tCtrl+Z"); 
  72     m_redoAccelerator 
= wxT("\tCtrl+Y"); 
  75 wxCommandProcessor::~wxCommandProcessor() 
  80 bool wxCommandProcessor::DoCommand(wxCommand
& cmd
) 
  85 bool wxCommandProcessor::UndoCommand(wxCommand
& cmd
) 
  90 // Pass a command to the processor. The processor calls Do(); 
  91 // if successful, is appended to the command history unless 
  93 bool wxCommandProcessor::Submit(wxCommand 
*command
, bool storeIt
) 
  95     wxCHECK_MSG( command
, FALSE
, _T("no command in wxCommandProcessor::Submit") ); 
  97     if ( !DoCommand(*command
) ) 
  99         // the user code expects the command to be deleted anyhow 
 111 void wxCommandProcessor::Store(wxCommand 
*command
) 
 113     wxCHECK_RET( command
, _T("no command in wxCommandProcessor::Store") ); 
 115     if (m_commands
.Number() == m_maxNoCommands
) 
 117         wxNode 
*firstNode 
= m_commands
.First(); 
 118         wxCommand 
*firstCommand 
= (wxCommand 
*)firstNode
->Data(); 
 123     // Correct a bug: we must chop off the current 'branch' 
 124     // so that we're at the end of the command list. 
 125     if (!m_currentCommand
) 
 129         wxNode 
*node 
= m_currentCommand
->Next(); 
 132             wxNode 
*next 
= node
->Next(); 
 133             delete (wxCommand 
*)node
->Data(); 
 139     m_commands
.Append(command
); 
 140     m_currentCommand 
= m_commands
.Last(); 
 144 bool wxCommandProcessor::Undo() 
 146     wxCommand 
*command 
= GetCurrentCommand(); 
 147     if ( command 
&& command
->CanUndo() ) 
 149         if ( UndoCommand(*command
) ) 
 151             m_currentCommand 
= m_currentCommand
->Previous(); 
 160 bool wxCommandProcessor::Redo() 
 162     wxCommand 
*redoCommand 
= (wxCommand 
*) NULL
; 
 163     wxNode 
*redoNode 
= (wxNode 
*) NULL
; 
 165     if ( m_currentCommand 
) 
 167         // is there anything to redo? 
 168         if ( m_currentCommand
->Next() ) 
 170             redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
 171             redoNode 
= m_currentCommand
->Next(); 
 174     else // no current command, redo the first one 
 176         if (m_commands
.Number() > 0) 
 178             redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
 179             redoNode 
= m_commands
.First(); 
 185         bool success 
= DoCommand(*redoCommand
); 
 188             m_currentCommand 
= redoNode
; 
 196 bool wxCommandProcessor::CanUndo() const 
 198     wxCommand 
*command 
= GetCurrentCommand(); 
 200     return command 
&& command
->CanUndo(); 
 203 bool wxCommandProcessor::CanRedo() const 
 205     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() == (wxNode
*) NULL
)) 
 208     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() != (wxNode
*) NULL
)) 
 211     if ((m_currentCommand 
== (wxNode
*) NULL
) && (m_commands
.Number() > 0)) 
 217 void wxCommandProcessor::Initialize() 
 219     m_currentCommand 
= m_commands
.Last(); 
 223 // This reduces flicker in wxGTK+ 
 224 static void wxSetMenuLabelOptimally(wxMenu
* menu
, int id
, const wxString
& label
) 
 226     wxString oldLabel 
= menu
->GetLabel(id
); 
 227     oldLabel 
= wxStripMenuCodes(oldLabel
.BeforeFirst('\t')); 
 229     oldLabel
.Replace(wxT("_"), wxT("")); // GTK+ only 
 231     wxString label1 
= wxStripMenuCodes(label
.BeforeFirst('\t')); 
 232     if (oldLabel 
!= label1
) 
 233         menu
->SetLabel(id
, label
); 
 236 void wxCommandProcessor::SetMenuStrings() 
 239     if (m_commandEditMenu
) 
 242         if (m_currentCommand
) 
 244             wxCommand 
*command 
= (wxCommand 
*)m_currentCommand
->Data(); 
 245             wxString 
commandName(command
->GetName()); 
 246             if (commandName 
== wxT("")) commandName 
= _("Unnamed command"); 
 247             bool canUndo 
= command
->CanUndo(); 
 249                 buf 
= wxString(_("&Undo ")) + commandName 
+ m_undoAccelerator
; 
 251                 buf 
= wxString(_("Can't &Undo ")) + commandName 
+ m_undoAccelerator
; 
 253             //m_commandEditMenu->SetLabel(wxID_UNDO, buf); 
 254             wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_UNDO
, buf
); 
 256             m_commandEditMenu
->Enable(wxID_UNDO
, canUndo
); 
 258             // We can redo, if we're not at the end of the history. 
 259             if (m_currentCommand
->Next()) 
 261                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
 262                 wxString 
redoCommandName(redoCommand
->GetName()); 
 263                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
 264                 buf 
= wxString(_("&Redo ")) + redoCommandName 
+ m_redoAccelerator
; 
 265                 wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_REDO
, buf
); 
 266                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
 270                 wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_REDO
, _("&Redo") + m_redoAccelerator
); 
 271                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
 276             wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_UNDO
, _("&Undo") + m_undoAccelerator
); 
 277             m_commandEditMenu
->Enable(wxID_UNDO
, FALSE
); 
 279             if (m_commands
.Number() == 0) 
 281                 wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_REDO
, _("&Redo") + m_redoAccelerator
); 
 282                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
 286                 // currentCommand is NULL but there are commands: this means that 
 287                 // we've undone to the start of the list, but can redo the first. 
 288                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
 289                 wxString 
redoCommandName(redoCommand
->GetName()); 
 290                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
 291                 buf 
= wxString(_("&Redo ")) + redoCommandName 
+ m_redoAccelerator
; 
 292                 wxSetMenuLabelOptimally(m_commandEditMenu
, wxID_REDO
, buf
); 
 293                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
 297 #endif // wxUSE_MENUS 
 300 void wxCommandProcessor::ClearCommands() 
 302     wxNode 
*node 
= m_commands
.First(); 
 305         wxCommand 
*command 
= (wxCommand 
*)node
->Data(); 
 308         node 
= m_commands
.First(); 
 310     m_currentCommand 
= (wxNode 
*) NULL
;