============
Undo manager
============

Overview
========

The ``HUndoManager`` class manages a history of actions in order to enable undo/redo functionality. It comes with the ability to keep track of camera and matrix changes, and can be further enhancedto accept user defined undo actions.


Using the HUndoManager
======================

``HBaseView`` is initialized with an ``HUndoManager`` class already set up. In addition to this, MVO already keeps track of various camera and matrix changes (via the operators).


Traversing the history list
---------------------------

To undo or redo operations, first retrieve a pointer to the ``HUndoManager`` class::

	HUndoManager *hmanager = m_pHView->GetUndoManager();

Once you have the ``HUndoManager`` class, you can call its ``Undo()`` and ``Redo()`` methods to get the desired result.


Enhancing the undo manager
==========================

The undo manager can also accept user defined undo items. In order to do so, the ``HUndoItem`` class must subclassed.  The HUndoItemCamera subclass will be used as an example.


Subclassing HUndoItem
---------------------

The constructor should contain all of the necessary information for undoing (and possibly redoing) an action. For ``HUndoItemCamera``, the state of the (the "before" state,as in the state of the camera right before we change it) is stored. Example::

	HUndoItemCamera::HUndoItemCamera(HBaseView *view)
	{
	m_pView = view;
	view->GetCamera(&m_Camera);
	}

The ``Undo()`` and function must perform everything needed to undo or redo. In the caseof ``HUndoItemCamera``, undo will show the camera state before an undo, and transition the camerato the stored camera state.  Afterwards, it will update the stored camera state to be the state ofthe camera BEFORE the undo, so that the Redo operation will work. Example::

	void HUndoItemCamera::Undo(bool setuponly)
	{
	HCamera oldcamera;
	m_pView->GetCamera(&oldcamera);

	if(!setuponly)
	{
		if (m_pView->GetSmoothTransition())
		{
			HC_Open_Segment_By_Key(m_pView->GetSceneKey());
			HUtility::SmoothTransition(oldcamera, m_Camera, m_pView);
			HC_Close_Segment();
		}
	}

	m_pView->SetCamera(m_Camera);
	m_Camera = oldcamera;
	}

The ``Redo()`` function is similar to the ``Undo()`` function, except it operates in reverse.

Note: Both the ``Undo()`` and ``Redo()`` functions accept a boolean "setuponly" argument. This argument is a flag to indicate whether or not we want to visually display the undo operation.  In "setup only" mode, an undo/redo should do everything as usual EXCEPT for updating the screen.  This "setuponly" flag is necessary for some of the other HUndoManager's features to operate nicely,and allows you to traverse the history list "behind the scenes", if need be. It is, however, mainly used for aesthetics, so not accounting for it should not break the undo manager.

It is also a good idea to override the GetName() function, so that you can identify what sort of ``UndoItem`` you are looking at::

	virtual const char * GetName() { return "HUndoItemCamera"; };


Adding items to the HUndoManager
--------------------------------

Now that you have an HUndoItem all ready to go, you need to add it into the ``HUndoManager``'s history list. If you are at the end of the history list, the item will be appended. If you had previously performed some undos, the item will be inserted at the location, and the rest of history will be discarded. Example::

	hmanager->AddUndoItem(undoitem);
