Files
ThirdParty-6/ParaView-5.0.1/ParaViewCore/ServerManager/Core/vtkSMUndoStack.cxx

207 lines
6.1 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkSMUndoStack.cxx
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkSMUndoStack.h"
#include "vtkCollection.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkProcessModule.h"
#include "vtkPVXMLElement.h"
#include "vtkSMMessage.h"
#include "vtkSMProxyManager.h"
#include "vtkSMSession.h"
#include "vtkSMUndoElement.h"
#include "vtkUndoSet.h"
#include "vtkUndoStackInternal.h"
#include "vtkSMStateLocator.h"
#include "vtkSMProxyLocator.h"
#include "vtkSMProxyManager.h"
#include "vtkSMDeserializerProtobuf.h"
#include "vtkSMRemoteObjectUpdateUndoElement.h"
#include <vtksys/RegularExpression.hxx>
#include <set>
#include "vtkNew.h"
//*****************************************************************************
class vtkSMUndoStack::vtkInternal
{
public:
typedef std::set<vtkSmartPointer<vtkSMSession> > SessionSetType;
SessionSetType Sessions;
vtkNew<vtkSMProxyLocator> UndoSetProxyLocator;
vtkNew<vtkSMDeserializerProtobuf> UndoSetProxyDeserializer;
vtkNew<vtkSMStateLocator> UndoSetStateLocator;
vtkInternal()
{
this->UndoSetProxyDeserializer->SetStateLocator(
this->UndoSetStateLocator.GetPointer());
this->UndoSetProxyLocator->SetDeserializer(
this->UndoSetProxyDeserializer.GetPointer());
this->UndoSetProxyLocator->UseSessionToLocateProxy(true);
}
void FillLocatorWithUndoStates(vtkUndoSet* undoSet, bool useBeforeState)
{
this->UndoSetStateLocator->UnRegisterAllStates(false);
int max = undoSet->GetNumberOfElements();
for (int cc=0; cc < max; ++cc)
{
vtkSMRemoteObjectUpdateUndoElement* elem =
vtkSMRemoteObjectUpdateUndoElement::SafeDownCast(
undoSet->GetElement(cc));
if(elem)
{
elem->SetProxyLocator(this->UndoSetProxyLocator.GetPointer());
if(useBeforeState)
{
this->UndoSetStateLocator->RegisterState(elem->BeforeState);
}
else
{
this->UndoSetStateLocator->RegisterState(elem->AfterState);
}
}
}
}
void UpdateSessions(vtkUndoSet* undoSet)
{
int max = undoSet->GetNumberOfElements();
this->Sessions.clear();
for (int cc=0; cc < max; ++cc)
{
vtkSMUndoElement* elem =
vtkSMUndoElement::SafeDownCast(undoSet->GetElement(cc));
if(elem->GetSession())
{
this->Sessions.insert(elem->GetSession());
}
}
assert("Undo element should not involve more than one session" && this->Sessions.size() < 2);
if(this->Sessions.size() == 1)
{
this->UndoSetStateLocator->SetParentLocator(this->Sessions.begin()->GetPointer()->GetStateLocator());
}
}
void FillSessionsRemoteObjects(vtkCollection* collection)
{
SessionSetType::iterator iter = this->Sessions.begin();
while(iter != this->Sessions.end())
{
iter->GetPointer()->GetAllRemoteObjects(collection);
iter++;
}
}
void Clear()
{
this->ClearProxyLocators();
this->Sessions.clear();
}
void ClearProxyLocators()
{
this->UndoSetProxyLocator->Clear();
SessionSetType::iterator iter = this->Sessions.begin();
while(iter != this->Sessions.end())
{
iter->GetPointer()->GetProxyLocator()->Clear();
iter++;
}
}
};
//*****************************************************************************
vtkStandardNewMacro(vtkSMUndoStack);
//-----------------------------------------------------------------------------
vtkSMUndoStack::vtkSMUndoStack()
{
this->Internal = new vtkInternal();
}
//-----------------------------------------------------------------------------
vtkSMUndoStack::~vtkSMUndoStack()
{
delete this->Internal; this->Internal = NULL;
}
//-----------------------------------------------------------------------------
void vtkSMUndoStack::Push(const char* label, vtkUndoSet* changeSet)
{
this->Superclass::Push(label, changeSet);
this->InvokeEvent(PushUndoSetEvent, changeSet);
}
//-----------------------------------------------------------------------------
int vtkSMUndoStack::Undo()
{
if (!this->CanUndo())
{
vtkErrorMacro("Cannot undo. Nothing on undo stack.");
return 0;
}
// Hold remote objects refs while the UndoSet is processing
vtkNew<vtkCollection> remoteObjectsCollection;
this->FillWithRemoteObjects(this->GetNextUndoSet(), remoteObjectsCollection.GetPointer());
this->Internal->FillLocatorWithUndoStates(this->GetNextUndoSet(), true);
int retValue = this->Superclass::Undo();
this->Internal->Clear();
return retValue;
}
//-----------------------------------------------------------------------------
int vtkSMUndoStack::Redo()
{
if (!this->CanRedo())
{
vtkErrorMacro("Cannot redo. Nothing on redo stack.");
return 0;
}
// Hold remote objects refs while the UndoSet is processing
vtkNew<vtkCollection> remoteObjectsCollection;
this->FillWithRemoteObjects(this->GetNextRedoSet(), remoteObjectsCollection.GetPointer());
this->Internal->FillLocatorWithUndoStates(this->GetNextRedoSet(), false);
int retValue = this->Superclass::Redo();
this->Internal->Clear();
return retValue;
}
//-----------------------------------------------------------------------------
void vtkSMUndoStack::FillWithRemoteObjects( vtkUndoSet *undoSet,
vtkCollection *collection)
{
if(!undoSet || !collection)
return;
this->Internal->UpdateSessions(undoSet);
this->Internal->FillSessionsRemoteObjects(collection);
}
//-----------------------------------------------------------------------------
void vtkSMUndoStack::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}