NCBI C++ ToolKit
undo_manager.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: undo_manager.cpp 39241 2017-08-28 15:44:36Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Roman Katargin
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
35 #include <gui/core/document.hpp>
36 
38 #include <objects/general/Date.hpp>
39 
40 #include <wx/utils.h>
41 
42 #include "project_locked_dlg.hpp"
43 #include "exclusive_edit_dlg.hpp"
44 
46 
47 /////////////////////////////////////////////////////////////////////////////
48 
49 
50 void CUndoManager::Execute(IEditCommand* pCommand, wxWindow* window)
51 {
52  if (m_ExclusiveEdit && m_ExclusiveEdit != window) {
54  return;
55  }
56 
57  CIRef<IEditCommand> command(pCommand);
58  string errMsg;
59  bool exception = false;
60 
61  try {
62  {{
63  CWriteLockGuard guard(*this);
64  if (x_LockDocument()) {
65  wxBusyCursor wait;
67  command->Execute();
68  }
69  else
70  return;
71  }}
73  m_RedoBuffer.clear();
74 
75  if (m_UndoBuffer.size() > 0 && m_UndoBuffer.front()->CanMerge(command)) {
76  m_UndoBuffer.front()->Merge(command);
77  } else {
79  if (m_MaxBufferSize != 0 && m_UndoBuffer.size() > m_MaxBufferSize) {
80  m_UndoBuffer.pop_back();
81  }
82  }
83  }
84  catch(const CException& e) {
85  exception = true;
86  errMsg = e.GetMsg();
87  }
88 
89  if (exception) {
90  ShowErrorMsg (command, errMsg);
91  }
92 }
93 
94 void CUndoManager::Undo(wxWindow* window)
95 {
96  if (m_ExclusiveEdit && m_ExclusiveEdit != window) {
98  return;
99  }
100 
101  if (m_UndoBuffer.size() == 0) {
102  _ASSERT(false);
103  return;
104  }
105 
107  string errMsg;
108  bool exception = false;
109 
110  try {
111  {{
112  CWriteLockGuard guard(*this);
113  if (x_LockDocument()) {
114  wxBusyCursor wait;
116  command->Unexecute();
117  }
118  else
119  return;
120  }}
122  m_UndoBuffer.pop_front();
123  m_RedoBuffer.push_front(command);
124  }
125  catch (CException& e) {
126  exception = true;
127  errMsg = e.GetMsg();
128  LOG_POST(Error << "failed to Undo: " << e.GetMsg());
129  }
130 
131  if (exception) {
132  ShowErrorMsg (command, errMsg);
133  }
134 }
135 
136 void CUndoManager::Redo(wxWindow* window)
137 {
138  if (m_ExclusiveEdit && m_ExclusiveEdit != window) {
140  return;
141  }
142 
143  if (m_RedoBuffer.size() == 0) {
144  _ASSERT(false);
145  return;
146  }
147 
149  string errMsg;
150  bool exception = false;
151 
152  try {
153  {{
154  CWriteLockGuard guard(*this);
155  if (x_LockDocument()) {
156  wxBusyCursor wait;
158  command->Execute();
159  }
160  else
161  return;
162  }}
164  m_RedoBuffer.pop_front();
165  m_UndoBuffer.push_front(command);
166  }
167  catch (CException& e) {
168  exception = true;
169  errMsg = e.GetMsg();
170  LOG_POST(Error << "failed to Redo: " << e.GetMsg());
171  }
172 
173  if (exception) {
174  ShowErrorMsg (command, errMsg);
175  }
176 }
177 
179 {
180  return (m_UndoBuffer.size() > 0);
181 }
182 
184 {
185  return (m_RedoBuffer.size() > 0);
186 }
187 
189 {
190  _ASSERT(m_UndoBuffer.size() > 0);
191  return (m_UndoBuffer.size() > 0) ? m_UndoBuffer.front()->GetLabel() : "";
192 }
193 
195 {
196  _ASSERT(m_RedoBuffer.size() > 0);
197  return (m_RedoBuffer.size() > 0) ? m_RedoBuffer.front()->GetLabel() : "";
198 }
199 
201 {
202  m_RedoBuffer.clear();
203  m_UndoBuffer.clear();
204 }
205 
206 void CUndoManager::ShowErrorMsg (IEditCommand* pCommand, const string& errMsg)
207 {
208  string cmdName = pCommand->GetLabel();
209 
210  if (cmdName.empty())
211  cmdName = typeid(*pCommand).name();
212 
213  if (cmdName.empty())
214  cmdName = "Unknown command";
215  cmdName += ": ";
216 
217  string msg = errMsg.empty() ? "Unknown error" : errMsg;
218  if (msg[msg.length() - 1] != '.')
219  msg += ".";
220 
221  LOG_POST(Error << cmdName + msg);
222 }
223 
225 {
226  if (m_Document)
228 }
229 
231 {
232  if (m_Document) {
233  m_Document->SetDataModified(true);
235  }
236 }
237 
239 {
241  if (m_LockCounter >= 0) {
242  ++m_LockCounter;
243  return true;
244  }
245  return false;
246 }
247 
249 {
251  if (m_LockCounter > 0) {
252  --m_LockCounter;
253  } else {
254  _ASSERT(false);
255  }
256 }
257 
259 {
261  if (m_LockCounter == 0) {
262  --m_LockCounter;
263  return true;
264  }
265  return false;
266 }
267 
269 {
271  if (m_UndoManager.m_LockCounter == -1) {
273  }
274 }
275 
277 {
278  if (x_WriteLock()) return true;
279 
280  for (;;) {
281  ::wxMilliSleep(500);
282  if (x_WriteLock()) return true;
283 
284  CProjectLockedDlg dlg(NULL);
285  if (dlg.ShowModal() == wxID_CANCEL)
286  return false;
287 
288  if (x_WriteLock()) return true;
289  }
290 }
291 
292 bool CUndoManager::RequestExclusiveEdit(wxWindow* window, const string& descr)
293 {
294  if (m_ExclusiveEdit) {
295  if (window == m_ExclusiveEdit)
296  return true;
298  return false;
299  }
300  m_ExclusiveEdit = window;
301  m_ExclusiveDescr = descr;
302  return true;
303 }
304 
306 {
307  if (m_ExclusiveEdit && m_ExclusiveEdit == window) {
308  m_ExclusiveEdit = 0;
309  m_ExclusiveDescr.clear();
310  return true;
311  }
312 
313  return false;
314 }
315 
317 {
318  CExclusiveEditDlg dlg;
320  dlg.Create(NULL);
321  dlg.ShowModal();
322 }
323 
User-defined methods of the data storage class.
bool Create(wxWindow *parent, wxWindowID id=ID_CEXCLUSIVEEDITDLG, const wxString &caption=_("Exclusive Edit Access"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(400, 300), long style=wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL)
void InitData(wxWindow *exclusiveEdit, const string &exclusiveDescr)
virtual void x_FireProjectChanged(TEvent::EEventSubtype subtype)
Definition: document.cpp:399
CGBDocument * m_Document
void x_SendChangedEvent()
CFastMutex m_RWMutex
wxWindow * m_ExclusiveEdit
virtual void Undo(wxWindow *window=0)
virtual string GetUndoLabel()
virtual bool CanUndo()
void x_ShowExclusiveEditDlg()
TCommands m_RedoBuffer
virtual bool ExecuteLock()
void x_SendChangingEvent()
virtual bool ReleaseExclusiveEdit(wxWindow *window)
virtual void ExecuteUnlock()
virtual void Redo(wxWindow *window=0)
virtual bool RequestExclusiveEdit(wxWindow *window, const string &descr)
size_t m_MaxBufferSize
string m_ExclusiveDescr
bool x_WriteLock()
TCommands m_UndoBuffer
void ShowErrorMsg(IEditCommand *pCommand, const string &errMsg)
virtual bool CanRedo()
virtual void Execute(IEditCommand *command, wxWindow *window=0)
bool x_LockDocument()
virtual string GetRedoLabel()
Interface (functor) for object editing.
virtual string GetLabel()=0
#define NULL
Definition: ncbistd.hpp:225
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
const char * command
#define _ASSERT
Modified on Tue Nov 28 02:20:48 2023 by modify_doxy.py rev. 669887