/** * @file XTPTrackUndoManager.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPCustomHeap.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSmartPtrInternalT.h" #include "GridControl/XTPGridDefines.h" #include "GridControl/XTPGridAllocators.h" #include "GridControl/XTPGridRecordItem.h" #include "GridControl/XTPGridControl.h" #include "GridControl/TrackControl/XTPTrackControl.h" #include "GridControl/TrackControl/XTPTrackControlItem.h" #include "GridControl/TrackControl/XTPTrackUndoManager.h" #include "GridControl/TrackControl/XTPTrackBlock.h" #include "GridControl/XTPGridControlIIDs.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif const int CONTEXT_NONE = 0; const int CONTEXT_UNDO = 1; // const int CONTEXT_REDO = 2; ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoCommand CXTPTrackUndoCommand::CXTPTrackUndoCommand(int nID) : m_nID(nID) { } CXTPTrackUndoCommand::~CXTPTrackUndoCommand() { } void CXTPTrackUndoCommand::Undo() { _ASSERTE(FALSE); } ///////////////////////////////////////////////////////////////////////// // CXTPTrackUndoManager CXTPTrackUndoManager::CXTPTrackUndoManager() { m_nUndoContext = CONTEXT_NONE; m_pUndoGroup = NULL; #ifdef _XTP_ACTIVEX EnableAutomation(); EnableTypeLib(); #endif } CXTPTrackUndoManager::~CXTPTrackUndoManager() { Clear(); SAFE_DELETE(m_pUndoGroup); } void CXTPTrackUndoManager::Clear() { int i; for (i = 0; i < m_arrUndoCommands.GetSize(); i++) { delete m_arrUndoCommands[i]; } m_arrUndoCommands.RemoveAll(); for (i = 0; i < m_arrRedoCommands.GetSize(); i++) { delete m_arrRedoCommands[i]; } m_arrRedoCommands.RemoveAll(); SAFE_DELETE(m_pUndoGroup); } void CXTPTrackUndoManager::StartGroup() { _ASSERTE(m_pUndoGroup == NULL); m_pUndoGroup = new CXTPTrackUndoGroupCommand(this); } void CXTPTrackUndoManager::EndGroup() { if (m_pUndoGroup->GetCount() == 0) { delete m_pUndoGroup; } else { if (m_nUndoContext != CONTEXT_UNDO) m_arrUndoCommands.Add(m_pUndoGroup); else m_arrRedoCommands.Add(m_pUndoGroup); } m_pUndoGroup = NULL; } void CXTPTrackUndoManager::AddUndoCommand(CXTPTrackUndoCommand* pCommand) { if (m_pUndoGroup) { m_pUndoGroup->Add(pCommand); } else if (m_nUndoContext != CONTEXT_UNDO) { m_arrUndoCommands.Add(pCommand); } else { m_arrRedoCommands.Add(pCommand); } if (m_nUndoContext == CONTEXT_NONE) { for (int i = 0; i < m_arrRedoCommands.GetSize(); i++) { delete m_arrRedoCommands[i]; } m_arrRedoCommands.RemoveAll(); } } BOOL CXTPTrackUndoManager::CanUndo() const { return m_arrUndoCommands.GetSize() > 0; } BOOL CXTPTrackUndoManager::CanRedo() const { return m_arrRedoCommands.GetSize() > 0; } void CXTPTrackUndoManager::Undo() { if (m_arrUndoCommands.GetSize() > 0) { m_nUndoContext = 1; CXTPTrackUndoCommand* pUndoCommand = m_arrUndoCommands[m_arrUndoCommands.GetSize() - 1]; pUndoCommand->Undo(); delete pUndoCommand; m_arrUndoCommands.RemoveAt(m_arrUndoCommands.GetSize() - 1); m_nUndoContext = 0; } } void CXTPTrackUndoManager::Redo() { if (m_arrRedoCommands.GetSize() > 0) { m_nUndoContext = 2; CXTPTrackUndoCommand* pUndoCommand = m_arrRedoCommands[m_arrRedoCommands.GetSize() - 1]; pUndoCommand->Undo(); delete pUndoCommand; m_arrRedoCommands.RemoveAt(m_arrRedoCommands.GetSize() - 1); m_nUndoContext = 0; } } ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoGroupCommand CXTPTrackUndoGroupCommand::CXTPTrackUndoGroupCommand(CXTPTrackUndoManager* pManager) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_GROUP) { m_pManager = pManager; } CXTPTrackUndoGroupCommand::~CXTPTrackUndoGroupCommand() { for (int i = (int)m_arrUndoCommands.GetSize() - 1; i >= 0; i--) { delete m_arrUndoCommands[i]; } m_arrUndoCommands.RemoveAll(); } void CXTPTrackUndoGroupCommand::Add(CXTPTrackUndoCommand* pCommand) { m_arrUndoCommands.Add(pCommand); } void CXTPTrackUndoGroupCommand::Undo() { m_pManager->StartGroup(); for (int i = (int)m_arrUndoCommands.GetSize() - 1; i >= 0; i--) { m_arrUndoCommands[i]->Undo(); delete m_arrUndoCommands[i]; } m_arrUndoCommands.RemoveAll(); m_pManager->EndGroup(); } int CXTPTrackUndoGroupCommand::GetCount() const { return (int)m_arrUndoCommands.GetSize(); } ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoAddMarkerCommand CXTPTrackUndoAddMarkerCommand::CXTPTrackUndoAddMarkerCommand(CXTPTrackMarker* pMarker) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_ADDMARKER) { m_pMarker = pMarker; m_pMarker->InternalAddRef(); } CXTPTrackUndoAddMarkerCommand::~CXTPTrackUndoAddMarkerCommand() { m_pMarker->InternalRelease(); } void CXTPTrackUndoAddMarkerCommand::Undo() { m_pMarker->Remove(); } ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoDeleteMarkerCommand CXTPTrackUndoDeleteMarkerCommand::CXTPTrackUndoDeleteMarkerCommand(CXTPTrackMarker* pMarker) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_DELETEMARKER) { m_pMarker = pMarker; m_pMarker->InternalAddRef(); } CXTPTrackUndoDeleteMarkerCommand::~CXTPTrackUndoDeleteMarkerCommand() { m_pMarker->InternalRelease(); } void CXTPTrackUndoDeleteMarkerCommand::Undo() { m_pMarker->InternalAddRef(); m_pMarker->GetControl()->GetMarkers()->Add(m_pMarker); } /////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoSetMarkerPositionCommand CXTPTrackUndoSetMarkerPositionCommand::CXTPTrackUndoSetMarkerPositionCommand( CXTPTrackMarker* pMarker, int nOldPosition) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_SETMARKERPOSITION) { m_nOldPosition = nOldPosition; m_pMarker = pMarker; m_pMarker->InternalAddRef(); } CXTPTrackUndoSetMarkerPositionCommand::~CXTPTrackUndoSetMarkerPositionCommand() { m_pMarker->InternalRelease(); } void CXTPTrackUndoSetMarkerPositionCommand::Undo() { m_pMarker->SetPosition(m_nOldPosition); } ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoAddBlockCommand CXTPTrackUndoAddBlockCommand::CXTPTrackUndoAddBlockCommand(CXTPTrackBlock* pBlock) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_ADDBLOCK) { m_pBlock = pBlock; m_pBlock->InternalAddRef(); } CXTPTrackUndoAddBlockCommand::~CXTPTrackUndoAddBlockCommand() { m_pBlock->InternalRelease(); } void CXTPTrackUndoAddBlockCommand::Undo() { m_pBlock->Remove(); } ////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoDeleteBlockCommand CXTPTrackUndoDeleteBlockCommand::CXTPTrackUndoDeleteBlockCommand(CXTPTrackBlock* pBlock) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_DELETEBLOCK) { m_pBlock = pBlock; m_pBlock->InternalAddRef(); m_pOldItem = pBlock->GetItem(); m_pOldItem->InternalAddRef(); } CXTPTrackUndoDeleteBlockCommand::~CXTPTrackUndoDeleteBlockCommand() { m_pBlock->InternalRelease(); m_pOldItem->InternalRelease(); } void CXTPTrackUndoDeleteBlockCommand::Undo() { m_pBlock->InternalAddRef(); m_pOldItem->Add(m_pBlock); } /////////////////////////////////////////////////////////////////////////// // CXTPTrackUndoSetMarkerPositionCommand CXTPTrackUndoSetBlockPositionCommand::CXTPTrackUndoSetBlockPositionCommand(CXTPTrackBlock* pBlock, int nOldPosition, int nOldLength) : CXTPTrackUndoCommand(XTP_ID_TRACKUNDO_SETBLOCKPOSITION) { m_nOldPosition = nOldPosition; m_nOldLength = nOldLength; m_pBlock = pBlock; m_pBlock->InternalAddRef(); } CXTPTrackUndoSetBlockPositionCommand::~CXTPTrackUndoSetBlockPositionCommand() { m_pBlock->InternalRelease(); } void CXTPTrackUndoSetBlockPositionCommand::Undo() { m_pBlock->SetPosition(m_nOldPosition); m_pBlock->SetLength(m_nOldLength); m_pBlock->GetItem()->RecalcLayout(); } #ifdef _XTP_ACTIVEX BEGIN_DISPATCH_MAP(CXTPTrackUndoManager, CXTPCmdTarget) DISP_FUNCTION_ID(CXTPTrackUndoManager, "Undo", 1000, Undo, VT_EMPTY, VTS_NONE) DISP_FUNCTION_ID(CXTPTrackUndoManager, "Redo", 1001, Redo, VT_EMPTY, VTS_NONE) DISP_PROPERTY_EX_ID(CXTPTrackUndoManager, "CanUndo", 1002, CanUndo, SetNotSupported, VT_BOOL) DISP_PROPERTY_EX_ID(CXTPTrackUndoManager, "CanRedo", 1003, CanRedo, SetNotSupported, VT_BOOL) DISP_FUNCTION_ID(CXTPTrackUndoManager, "Clear", 1004, Clear, VT_EMPTY, VTS_NONE) DISP_FUNCTION_ID(CXTPTrackUndoManager, "StartGroup", 1015, StartGroup, VT_EMPTY, VTS_NONE) DISP_FUNCTION_ID(CXTPTrackUndoManager, "EndGroup", 1016, EndGroup, VT_EMPTY, VTS_NONE) END_DISPATCH_MAP() BEGIN_INTERFACE_MAP(CXTPTrackUndoManager, CXTPCmdTarget) INTERFACE_PART(CXTPTrackUndoManager, XTPDIID_TrackUndoManager, Dispatch) END_INTERFACE_MAP() IMPLEMENT_OLETYPELIB_EX(CXTPTrackUndoManager, XTPDIID_TrackUndoManager) #endif