home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / cmdproc.cpp < prev    next >
C/C++ Source or Header  |  2002-06-23  |  9KB  |  305 lines

  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: cmdproc.cpp,v 1.7 2002/06/18 15:57:39 JS Exp $
  8. // Copyright:   (c) wxWindows team
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "cmdproc.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/intl.h"
  33.     #include "wx/string.h"
  34.     #include "wx/menu.h"
  35. #endif //WX_PRECOMP
  36.  
  37. #include "wx/cmdproc.h"
  38.  
  39. // ============================================================================
  40. // implementation
  41. // ============================================================================
  42.  
  43. IMPLEMENT_CLASS(wxCommand, wxObject)
  44. IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor, wxObject)
  45.  
  46. // ----------------------------------------------------------------------------
  47. // wxCommand
  48. // ----------------------------------------------------------------------------
  49.  
  50. wxCommand::wxCommand(bool canUndoIt, const wxString& name)
  51. {
  52.     m_canUndo = canUndoIt;
  53.     m_commandName = name;
  54. }
  55.  
  56. wxCommand::~wxCommand()
  57. {
  58. }
  59.  
  60. // ----------------------------------------------------------------------------
  61. // Command processor
  62. // ----------------------------------------------------------------------------
  63.  
  64. wxCommandProcessor::wxCommandProcessor(int maxCommands)
  65. {
  66.     m_maxNoCommands = maxCommands;
  67.     m_currentCommand = (wxNode *) NULL;
  68. #if wxUSE_MENUS
  69.     m_commandEditMenu = (wxMenu *) NULL;
  70. #endif // wxUSE_MENUS
  71.     m_undoAccelerator = wxT("\tCtrl+Z");
  72.     m_redoAccelerator = wxT("\tCtrl+Y");
  73. }
  74.  
  75. wxCommandProcessor::~wxCommandProcessor()
  76. {
  77.     ClearCommands();
  78. }
  79.  
  80. bool wxCommandProcessor::DoCommand(wxCommand& cmd)
  81. {
  82.     return cmd.Do();
  83. }
  84.  
  85. bool wxCommandProcessor::UndoCommand(wxCommand& cmd)
  86. {
  87.     return cmd.Undo();
  88. }
  89.  
  90. // Pass a command to the processor. The processor calls Do();
  91. // if successful, is appended to the command history unless
  92. // storeIt is FALSE.
  93. bool wxCommandProcessor::Submit(wxCommand *command, bool storeIt)
  94. {
  95.     wxCHECK_MSG( command, FALSE, _T("no command in wxCommandProcessor::Submit") );
  96.  
  97.     if ( !DoCommand(*command) )
  98.     {
  99.         // the user code expects the command to be deleted anyhow
  100.         delete command;
  101.  
  102.         return FALSE;
  103.     }
  104.  
  105.     if ( storeIt )
  106.         Store(command);
  107.  
  108.     return TRUE;
  109. }
  110.  
  111. void wxCommandProcessor::Store(wxCommand *command)
  112. {
  113.     wxCHECK_RET( command, _T("no command in wxCommandProcessor::Store") );
  114.  
  115.     if (m_commands.Number() == m_maxNoCommands)
  116.     {
  117.         wxNode *firstNode = m_commands.First();
  118.         wxCommand *firstCommand = (wxCommand *)firstNode->Data();
  119.         delete firstCommand;
  120.         delete firstNode;
  121.     }
  122.  
  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)
  126.         ClearCommands();
  127.     else
  128.     {
  129.         wxNode *node = m_currentCommand->Next();
  130.         while (node)
  131.         {
  132.             wxNode *next = node->Next();
  133.             delete (wxCommand *)node->Data();
  134.             delete node;
  135.             node = next;
  136.         }
  137.     }
  138.  
  139.     m_commands.Append(command);
  140.     m_currentCommand = m_commands.Last();
  141.     SetMenuStrings();
  142. }
  143.  
  144. bool wxCommandProcessor::Undo()
  145. {
  146.     wxCommand *command = GetCurrentCommand();
  147.     if ( command && command->CanUndo() )
  148.     {
  149.         if ( UndoCommand(*command) )
  150.         {
  151.             m_currentCommand = m_currentCommand->Previous();
  152.             SetMenuStrings();
  153.             return TRUE;
  154.         }
  155.     }
  156.  
  157.     return FALSE;
  158. }
  159.  
  160. bool wxCommandProcessor::Redo()
  161. {
  162.     wxCommand *redoCommand = (wxCommand *) NULL;
  163.     wxNode *redoNode = (wxNode *) NULL;
  164.  
  165.     if ( m_currentCommand )
  166.     {
  167.         // is there anything to redo?
  168.         if ( m_currentCommand->Next() )
  169.         {
  170.             redoCommand = (wxCommand *)m_currentCommand->Next()->Data();
  171.             redoNode = m_currentCommand->Next();
  172.         }
  173.     }
  174.     else // no current command, redo the first one
  175.     {
  176.         if (m_commands.Number() > 0)
  177.         {
  178.             redoCommand = (wxCommand *)m_commands.First()->Data();
  179.             redoNode = m_commands.First();
  180.         }
  181.     }
  182.  
  183.     if (redoCommand)
  184.     {
  185.         bool success = DoCommand(*redoCommand);
  186.         if (success)
  187.         {
  188.             m_currentCommand = redoNode;
  189.             SetMenuStrings();
  190.             return TRUE;
  191.         }
  192.     }
  193.     return FALSE;
  194. }
  195.  
  196. bool wxCommandProcessor::CanUndo() const
  197. {
  198.     wxCommand *command = GetCurrentCommand();
  199.  
  200.     return command && command->CanUndo();
  201. }
  202.  
  203. bool wxCommandProcessor::CanRedo() const
  204. {
  205.     if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() == (wxNode*) NULL))
  206.         return FALSE;
  207.  
  208.     if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() != (wxNode*) NULL))
  209.         return TRUE;
  210.  
  211.     if ((m_currentCommand == (wxNode*) NULL) && (m_commands.Number() > 0))
  212.         return TRUE;
  213.  
  214.     return FALSE;
  215. }
  216.  
  217. void wxCommandProcessor::Initialize()
  218. {
  219.     m_currentCommand = m_commands.Last();
  220.     SetMenuStrings();
  221. }
  222.  
  223. static void wxSetMenuLabel(wxMenu* menu, int id, const wxString& label)
  224. {
  225.     menu->SetLabel(id, label);
  226. }
  227.  
  228. void wxCommandProcessor::SetMenuStrings()
  229. {
  230. #if wxUSE_MENUS
  231.     if (m_commandEditMenu)
  232.     {
  233.         wxString buf;
  234.         if (m_currentCommand)
  235.         {
  236.             wxCommand *command = (wxCommand *)m_currentCommand->Data();
  237.             wxString commandName(command->GetName());
  238.             if (commandName == wxT("")) commandName = _("Unnamed command");
  239.             bool canUndo = command->CanUndo();
  240.             if (canUndo)
  241.                 buf = wxString(_("&Undo ")) + commandName + m_undoAccelerator;
  242.             else
  243.                 buf = wxString(_("Can't &Undo ")) + commandName + m_undoAccelerator;
  244.  
  245.             wxSetMenuLabel(m_commandEditMenu, wxID_UNDO, buf);
  246.             
  247.             m_commandEditMenu->Enable(wxID_UNDO, canUndo);
  248.  
  249.             // We can redo, if we're not at the end of the history.
  250.             if (m_currentCommand->Next())
  251.             {
  252.                 wxCommand *redoCommand = (wxCommand *)m_currentCommand->Next()->Data();
  253.                 wxString redoCommandName(redoCommand->GetName());
  254.                 if (redoCommandName == wxT("")) redoCommandName = _("Unnamed command");
  255.                 buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator;
  256.                 wxSetMenuLabel(m_commandEditMenu, wxID_REDO, buf);
  257.                 m_commandEditMenu->Enable(wxID_REDO, TRUE);
  258.             }
  259.             else
  260.             {
  261.                 wxSetMenuLabel(m_commandEditMenu, wxID_REDO, _("&Redo") + m_redoAccelerator);
  262.                 m_commandEditMenu->Enable(wxID_REDO, FALSE);
  263.             }
  264.         }
  265.         else
  266.         {
  267.             wxSetMenuLabel(m_commandEditMenu, wxID_UNDO, _("&Undo") + m_undoAccelerator);
  268.             m_commandEditMenu->Enable(wxID_UNDO, FALSE);
  269.  
  270.             if (m_commands.Number() == 0)
  271.             {
  272.                 wxSetMenuLabel(m_commandEditMenu, wxID_REDO, _("&Redo") + m_redoAccelerator);
  273.                 m_commandEditMenu->Enable(wxID_REDO, FALSE);
  274.             }
  275.             else
  276.             {
  277.                 // currentCommand is NULL but there are commands: this means that
  278.                 // we've undone to the start of the list, but can redo the first.
  279.                 wxCommand *redoCommand = (wxCommand *)m_commands.First()->Data();
  280.                 wxString redoCommandName(redoCommand->GetName());
  281.                 if (redoCommandName == wxT("")) redoCommandName = _("Unnamed command");
  282.                 buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator;
  283.                 wxSetMenuLabel(m_commandEditMenu, wxID_REDO, buf);
  284.                 m_commandEditMenu->Enable(wxID_REDO, TRUE);
  285.             }
  286.         }
  287.     }
  288. #endif // wxUSE_MENUS
  289. }
  290.  
  291. void wxCommandProcessor::ClearCommands()
  292. {
  293.     wxNode *node = m_commands.First();
  294.     while (node)
  295.     {
  296.         wxCommand *command = (wxCommand *)node->Data();
  297.         delete command;
  298.         delete node;
  299.         node = m_commands.First();
  300.     }
  301.     m_currentCommand = (wxNode *) NULL;
  302. }
  303.  
  304.  
  305.