[vtk-developers] undo / redo for widgets

Dean Inglis dean.inglis at camris.ca
Thu Nov 26 08:12:43 EST 2009


We also have implemented serialization wherein objects (parents
and there child classes and all their ivars) are serialized to a file on
disk.  So far, since our library focuses heavily on image processing
and interaction, we only implemented undo / redo for contours (storing
the bare essential node coordinates and no properties), but not
using a serialization scheme.


>1. I wonder about the implications on widgets that manipulate data in
>an irreversible fashion... But I guess given that the Undo/Redo can be
>disabled, its ok.

hadn’t thought of that, but disabling or not implementing unde / redo would
work.


>2. Then there is the question of what's popped into the HistoryQueue.
>For instance on the contourWidget, I guess we would take a snapshot of
>all the control points. Do we take a snapshot of the contour node
>properties as well, so if one were to change the contour color, that's
>undone ?

I think only the bare essentials that define the widget geometry
would be desirable but perhaps there could be a depth controlling
ivar.

>3. Then there is question of how often we take snapshots of the
>widget. Is this done at each invocation of EndInteractionEvent ? Or
>every couple 5th EndInteractionEvent ? Or do we let the user do this
>explicitly ?

I think it depends on the widget, for example, with vtkContourWidget,
one can Initialize its representation geometry using a vtkPolyData.
One would likely want a shapshot taken after initializing.

>4. At some point, I had the idea of adding XML IO to all the widgets.
>This is how we VolView creates session files. So every widget and
>representation used in VolView has a corresponding XML reader/writer
>for instance :
>At any point the application can ask the widget to serialize itself
>and restore it exactly to that state when needed. This framework could
>be useful for maintaining state in a stream, or serializing to a file.

I like serialization!  We use a parent vtkSerialObject that a number of
classes inherit from each reimplementing 
  virtual void Serialize( vtksys_ios::ostream& stream );
  virtual void UnSerialize( vtksys_ios::istream& stream );
and for VTK classes we have vtkObjectSerializer inheriting from
vtkSerialObject that takes a VTK class as an arg and then serializes
it according to that specific class's ivars: for example
vtkMatrix4x4Serializer, vtkPropertySerializer etc.

>  class vtkAbstractWidgetStates< class TAbstractWidget >
>    {
>    void SetWidget( TAbstractWidget * );
>
>    vtkTimeStamp Serialize( std::ostringstream &os );
>    bool UnSerialize( std::ostringstream &os );
>
>    void Undo() { --pos; UnSerialize( pos->second ); }
>    void Redo()..
>
>    void RecordState() { // Create new stringstream. Serialize, pushback }
>
>    std::map< vtkTimeStamp, std::ostringstream * > History;
>    HistoryIterator pos;
>    }

>This takes care of Issue (2), since serialization means that the
>widget should be entirely reproducible from the state...
>Also, all the undo / redo code is kept out of the widget /
>repesentation and done by the stateManager.

I like the idea of keeping serialization out of the widget, although
I don’t see how vtkAbstractWidgetStates would know what to serialize
unless either TAbstractWidget implements its own Serialize/Unserialize
to/from the history stream or there are child classed of
vtkAbstractWidgetStates specific to each widget.

Dean


On Wed, Nov 25, 2009 at 5:24 PM, Dean Inglis <dean.inglis at camris.ca> wrote:
> Hi Andrew,
>
> I was thinking unlimited, at least as far as memory would allow,
> but it could be capped and probably should be at some
> reasonable level depending on the widget representation complexity.
> maybe the API could be
>
>> int CanUndo(){return 0;} // by default for all classes that decide not
>> int CanRedo(){return 0;} // to reimplement these methods return false
>> void UpdateHistory(){}    // or some other name  and by default do
nothing
>  void SetMaximumHistorySize()
>> void Undo(){}
>> void Redo(){}
>
> Dean
>
>>I must have missed the start of this thread.
>>What levels of undo/redo do you envisage having? Or will it be limited
>>to a single undo/redo?
>
>>Regards
>>   Andrew
>
>
> On Thu, Nov 26, 2009 at 6:54 AM, Dean Inglis <dean.inglis at camris.ca>
wrote:
>> Will,
>>
>> absolutely, just ran out of steam momentarily... ;)
>>
>> My impression is that vtkWidgetRepresentation could have
>> the optional methods:
>>
>> int CanUndo(){return 0;} // by default for all classes that decide not
>> int CanRedo(){return 0;} // to reimplement these methods return false
>> void TakeSnapShot(){}    // or some other name  and by default do nothing
>> void Undo(){}
>> void Redo(){}
>>
>> Implementation would then be representation dependent.
>>
>> Dean
>>
>> -----Original Message-----
>> From: Will Schroeder [mailto:will.schroeder at kitware.com]
>> Sent: November-25-09 2:37 PM
>> To: dean.inglis at camris.ca
>> Cc: VTK Developers
>> Subject: Re: undo / redo for widgets
>>
>> Dean-
>>
>> Well I can imagine any widget benefiting, for example slider widget,
>> you may want to undo a value change; affine or box widget; reset a
>> transformation, etc.
>>
>> Am I answering your question? Doe this make sense?
>>
>> Will
>>
>> On Wed, Nov 25, 2009 at 2:32 PM, Dean Inglis <dean.inglis at camris.ca>
> wrote:
>>> Hi Will,
>>>
>>> I'm breaking this off into a separate thread.  What other (VTK) widgets
>>> and/or instances would it be desirable to have undo redo?
>>>
>>> Dean
>>>
>>>
>>>>I'm rethinking my answer on this one, I retract my previous statement
>>>>:-) I know there is some support for this in the paintbrush widgets; I
>>>>guess my premature reaction is more of a question: can we step back
>>>>and think about redo/undo at a higher level across all widgets?
>>>
>>>>Will
>>>
>>> On Wed, Nov 25, 2009 at 1:46 PM, Will Schroeder
>>> <will.schroeder at kitware.com> wrote:
>>>> IMHO Undo/redo is an application level feature. I do not think it
>>>> belongs in individual classes.
>>>>
>>>> If you want to raise a discussion about general approaches for
>>>> undo/redo that is a different matter.
>>>>
>>>> Will
>>>>
>>>> On Wed, Nov 25, 2009 at 1:33 PM, Dean Inglis <dean.inglis at sympatico.ca>
>>> wrote:
>>>>> Hi all,
>>>>>
>>>>> I would like to add undo redo capability for vtkContourWidget.  The
>>>>> implementation would be to have vtkContourRepresentation's internals
>>>>> modified as follows:
>>>>> 1) add Copy methods to the vtkContourRepresentationNode:
>>>>>
>>>>>  void Copy( vtkContourRepresentationNode* node )
>>>>>  {
>>>>>    vtkstd::vector< vtkContourRepresentationPoint* > points =
>>> node->Points;
>>>>>    vtkstd::vector< vtkContourRepresentationPoint* >::iterator it1,
it2;
>>>>>
>>>>>    memcpy( this->WorldPosition, node->WorldPosition, 3 * sizeof(
double
>> )
>>>>> );
>>>>>    memcpy( this->WorldOrientation, node->WorldOrientation, 9 * sizeof(
>>>>> double ) );
>>>>>    memcpy( this->NormalizedDisplayPosition,
>>>>> node->NormalizedDisplayPosition, 2 * sizeof( double ) );
>>>>>    this->Selected = node->Seleced;
>>>>>
>>>>>    this->Points.resize( points.size() );
>>>>>    for( it1 = points.begin(), it2 = this->Points.begin();
>>>>>         it1 != points.end() && it2 != this->Points.end();
>>>>>         it1++, it2++ )
>>>>>    {
>>>>>      ( *it2 ) = new vtkContourRepresentationPoint;
>>>>>      memcpy( ( *it2 )->WorldPosition, ( *it1 )->WorldPosition,
>>>>>        3 * sizeof( double ) );
>>>>>      memcpy( ( *it2 )->NormalizedDisplayPosition, ( *it1
>>>>> )->NormalizedDisplayPosition,
>>>>>        2 * sizeof( double ) );
>>>>>    }
>>>>>  }
>>>>>
>>>>> and the vtkContourRepresentationInternals:
>>>>>
>>>>>  void Copy( vtkContourRepresentationInternals* internal )
>>>>>  {
>>>>>    vtkstd::vector< vtkContourRepresentationNode* > nodes =
>>> internal->Nodes;
>>>>>    vtkstd::vector< vtkContourRepresentationNode* >::iterator it1, it2;
>>>>>
>>>>>    this->Nodes.resize( nodes.size() );
>>>>>    for( it1 = nodes.begin(), it2 = this->Nodes.begin();
>>>>>         it1 != nodes.end() && it2 != this->Nodes.end();
>>>>>         it1++, it2++ )
>>>>>    {
>>>>>      ( *it2 ) = new vtkContourRepresentationNode;
>>>>>      ( *it2 )->Copy( *it1 );
>>>>>    }
>>>>>  }
>>>>>
>>>>> and implement the following:
>>>>>
>>>>>  // Description:
>>>>>  // Records the current layout of nodes adding them to the node
history
>>>>> list
>>>>>  // so that they can be undone/redone.
>>>>>  virtual void TakeSnapshot();
>>>>>
>>>>>  // Description:
>>>>>  // A history of changes to the layout of nodes is kept internally and
>>>>>  // externally by calling TakeSnapshot().
>>>>>  // These two methods are used to go back to earlier changes to the
>>> contour
>>>>>  // or return to more recent ones.
>>>>>  virtual void Undo();
>>>>>  virtual void Redo();
>>>>>
>>>>>  // Description:
>>>>>  // Methods to determine whether there is any history left to undo or
>>> redo.
>>>>>  virtual int CanUndo();
>>>>>  virtual int CanRedo();
>>>>>
>>>>> by maintaining protected members:
>>>>>
>>>>> //BTX
>>>>>  vtkstd::vector< vtkContourRepresentationInternals* >
>>>>> InternalHistory;
>>>>>  vtkstd::vector< vtkContourRepresentationInternals* >::iterator
>>>>> InternalHistoryIterator;
>>>>> //ETX
>>>>>
>>>>> Also, can the SelectedNodesCursorShape be exposed through the public
> API
>>>>> of vtkOrientedGlyphContourRepresentation as is done for SetCursorShape
>>> and
>>>>> SetActiveCursorShape ?
>>>>>
>>>>> Dean
>>>>>
>>>>> _______________________________________________
>>>>> Powered by www.kitware.com
>>>>>
>>>>> Visit other Kitware open-source projects at
>>> http://www.kitware.com/opensource/opensource.html
>>>>>
>>>>> Follow this link to subscribe/unsubscribe:
>>>>> http://www.vtk.org/mailman/listinfo/vtk-developers
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> William J. Schroeder, PhD
>>>> Kitware, Inc.
>>>> 28 Corporate Drive
>>>> Clifton Park, NY 12065
>>>> will.schroeder at kitware.com
>>>> http://www.kitware.com
>>>> (518) 881-4902
>>>>
>>>
>>>
>>>
>>> --
>>> William J. Schroeder, PhD
>>> Kitware, Inc.
>>> 28 Corporate Drive
>>> Clifton Park, NY 12065
>>> will.schroeder at kitware.com
>>> http://www.kitware.com
>>> (518) 881-4902
>>> _______________________________________________
>>> Powered by www.kitware.com
>>>
>>> Visit other Kitware open-source projects at
>>> http://www.kitware.com/opensource/opensource.html
>>>
>>> Follow this link to subscribe/unsubscribe:
>>> http://www.vtk.org/mailman/listinfo/vtk-developers
>>>
>>>
>>
>>
>>
>> --
>> William J. Schroeder, PhD
>> Kitware, Inc.
>> 28 Corporate Drive
>> Clifton Park, NY 12065
>> will.schroeder at kitware.com
>> http://www.kitware.com
>> (518) 881-4902
>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.vtk.org/mailman/listinfo/vtk-developers
>>
>>
>
>
>
> --
> ___________________________________________
> Andrew J. P. Maclean
> Centre for Autonomous Systems
> The Rose Street Building J04
> The University of Sydney  2006  NSW
> AUSTRALIA
> Ph: +61 2 9351 3283
> Fax: +61 2 9351 7474
> URL: http://www.acfr.usyd.edu.au/
> ___________________________________________
>
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
>
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtk-developers
>

_________________________________
Karthik Krishnan
R&D Engineer,
Kitware Inc.
Ph: +1 5188814919, +91 9538477060




More information about the vtk-developers mailing list