<s> """<STR_LIT>""" <EOL> from __future__ import absolute_import <EOL> import collections <EOL> from traits . api import ( Event , HasPrivateTraits , HasStrictTraits , HasTraits , <EOL> Instance , Int , List , Property , Str , Trait ) <EOL> NumericTypes = ( int , long , float , complex ) <EOL> SimpleTypes = ( str , unicode , int , long , float , complex ) <EOL> class AbstractUndoItem ( HasPrivateTraits ) : <EOL> """<STR_LIT>""" <EOL> def undo ( self ) : <EOL> """<STR_LIT>""" <EOL> raise NotImplementedError <EOL> def redo ( self ) : <EOL> """<STR_LIT>""" <EOL> raise NotImplementedError <EOL> def merge_undo ( self , undo_item ) : <EOL> """<STR_LIT>""" <EOL> return False <EOL> class UndoItem ( AbstractUndoItem ) : <EOL> """<STR_LIT>""" <EOL> object = Trait ( HasTraits ) <EOL> name = Str <EOL> old_value = Property <EOL> new_value = Property <EOL> def _get_old_value ( self ) : <EOL> return self . _old_value <EOL> def _set_old_value ( self , value ) : <EOL> if isinstance ( value , list ) : <EOL> value = value [ : ] <EOL> self . _old_value = value <EOL> def _get_new_value ( self ) : <EOL> return self . _new_value <EOL> def _set_new_value ( self , value ) : <EOL> if isinstance ( value , list ) : <EOL> value = value [ : ] <EOL> self . _new_value = value <EOL> def undo ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> setattr ( self . object , self . name , self . old_value ) <EOL> except : <EOL> pass <EOL> def redo ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> setattr ( self . object , self . name , self . new_value ) <EOL> except : <EOL> pass <EOL> def merge_undo ( self , undo_item ) : <EOL> """<STR_LIT>""" <EOL> if ( isinstance ( undo_item , self . __class__ ) and <EOL> ( self . object is undo_item . object ) and <EOL> ( self . name == undo_item . name ) ) : <EOL> v1 = self . new_value <EOL> v2 = undo_item . new_value <EOL> t1 = type ( v1 ) <EOL> if t1 is type ( v2 ) : <EOL> if isinstance ( t1 , basestring ) : <EOL> n1 = len ( v1 ) <EOL> n2 = len ( v2 ) <EOL> n = min ( n1 , n2 ) <EOL> i = <NUM_LIT:0> <EOL> while ( i < n ) and ( v1 [ i ] == v2 [ i ] ) : <EOL> i += <NUM_LIT:1> <EOL> if v1 [ i + ( n2 <= n1 ) : ] == v2 [ i + ( n2 >= n1 ) : ] : <EOL> self . new_value = v2 <EOL> return True <EOL> elif isinstance ( v1 , collections . Sequence ) : <EOL> v1 = self . old_value <EOL> if isinstance ( v1 , collections . Sequence ) : <EOL> try : <EOL> if len ( v1 ) == len ( v2 ) : <EOL> diffs = <NUM_LIT:0> <EOL> for i , item in enumerate ( v1 ) : <EOL> titem = type ( item ) <EOL> item2 = v2 [ i ] <EOL> if ( ( titem not in SimpleTypes ) or <EOL> ( titem is not type ( item2 ) ) or <EOL> ( item != item2 ) ) : <EOL> diffs += <NUM_LIT:1> <EOL> if diffs >= <NUM_LIT:2> : <EOL> return False <EOL> if diffs == <NUM_LIT:0> : <EOL> return False <EOL> self . new_value = v2 <EOL> return True <EOL> except : <EOL> pass <EOL> elif t1 in NumericTypes : <EOL> self . new_value = v2 <EOL> return True <EOL> return False <EOL> def __repr__ ( self ) : <EOL> """<STR_LIT>""" <EOL> n = self . name <EOL> cn = self . object . __class__ . __name__ <EOL> return '<STR_LIT>' % ( <EOL> cn , n , self . old_value , cn , n , self . new_value ) <EOL> class ListUndoItem ( AbstractUndoItem ) : <EOL> """<STR_LIT>""" <EOL> object = Trait ( HasTraits ) <EOL> name = Str <EOL> index = Int <EOL> added = List <EOL> removed = List <EOL> def undo ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> list = getattr ( self . object , self . name ) <EOL> list [ self . index : ( self . index + len ( self . added ) ) ] = self . removed <EOL> except : <EOL> pass <EOL> def redo ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> list = getattr ( self . object , self . name ) <EOL> list [ self . index : ( self . index + len ( self . removed ) ) ] = self . added <EOL> except : <EOL> pass <EOL> def merge_undo ( self , undo_item ) : <EOL> """<STR_LIT>""" <EOL> if ( isinstance ( undo_item , self . __class__ ) and <EOL> ( self . object is undo_item . object ) and <EOL> ( self . name == undo_item . name ) and <EOL> ( self . index == undo_item . index ) ) : <EOL> added = undo_item . added <EOL> removed = undo_item . removed <EOL> if ( ( len ( self . added ) == len ( added ) ) and <EOL> ( len ( self . removed ) == len ( removed ) ) ) : <EOL> for i , item in enumerate ( self . added ) : <EOL> if item is not added [ i ] : <EOL> break <EOL> else : <EOL> for i , item in enumerate ( self . removed ) : <EOL> if item is not removed [ i ] : <EOL> break <EOL> else : <EOL> return True <EOL> return False <EOL> def __repr__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( <EOL> self . object . __class__ . __name__ , self . name , self . index , <EOL> self . index + len ( self . removed ) , self . added ) <EOL> class UndoHistory ( HasStrictTraits ) : <EOL> """<STR_LIT>""" <EOL> history = List <EOL> now = Int <EOL> undoable = Event ( False ) <EOL> redoable = Event ( False ) <EOL> can_undo = Property <EOL> can_redo = Property <EOL> def add ( self , undo_item , extend = False ) : <EOL> """<STR_LIT>""" <EOL> if extend : <EOL> self . extend ( undo_item ) <EOL> return <EOL> now = self . now <EOL> if now > <NUM_LIT:0> : <EOL> previous = self . history [ now - <NUM_LIT:1> ] <EOL> if ( len ( previous ) == <NUM_LIT:1> ) and previous [ <NUM_LIT:0> ] . merge_undo ( undo_item ) : <EOL> self . history [ now : ] = [ ] <EOL> return <EOL> old_len = len ( self . history ) <EOL> self . history [ now : ] = [ [ undo_item ] ] <EOL> self . now += <NUM_LIT:1> <EOL> if self . now == <NUM_LIT:1> : <EOL> self . undoable = True <EOL> if self . now <= old_len : <EOL> self . redoable = False <EOL> def extend ( self , undo_item ) : <EOL> """<STR_LIT>""" <EOL> if self . now > <NUM_LIT:0> : <EOL> undo_list = self . history [ self . now - <NUM_LIT:1> ] <EOL> if not undo_list [ - <NUM_LIT:1> ] . merge_undo ( undo_item ) : <EOL> undo_list . append ( undo_item ) <EOL> def undo ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . can_undo : <EOL> self . now -= <NUM_LIT:1> <EOL> items = self . history [ self . now ] <EOL> for i in range ( len ( items ) - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> items [ i ] . undo ( ) <EOL> if self . now == <NUM_LIT:0> : <EOL> self . undoable = False <EOL> if self . now == ( len ( self . history ) - <NUM_LIT:1> ) : <EOL> self . redoable = True <EOL> def redo ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . can_redo : <EOL> self . now += <NUM_LIT:1> <EOL> for item in self . history [ self . now - <NUM_LIT:1> ] : <EOL> item . redo ( ) <EOL> if self . now == <NUM_LIT:1> : <EOL> self . undoable = True <EOL> if self . now == len ( self . history ) : <EOL> self . redoable = False <EOL> def revert ( self ) : <EOL> """<STR_LIT>""" <EOL> history = self . history [ : self . now ] <EOL> self . clear ( ) <EOL> for i in range ( len ( history ) - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> items = history [ i ] <EOL> for j in range ( len ( items ) - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> items [ j ] . undo ( ) <EOL> def clear ( self ) : <EOL> """<STR_LIT>""" <EOL> old_len = len ( self . history ) <EOL> old_now = self . now <EOL> self . now = <NUM_LIT:0> <EOL> del self . history [ : ] <EOL> if old_now > <NUM_LIT:0> : <EOL> self . undoable = False <EOL> if old_now < old_len : <EOL> self . redoable = False <EOL> def _get_can_undo ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . now > <NUM_LIT:0> <EOL> def _get_can_redo ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . now < len ( self . history ) <EOL> class UndoHistoryUndoItem ( AbstractUndoItem ) : <EOL> """<STR_LIT>""" <EOL> history = Instance ( UndoHistory ) <EOL> def undo ( self ) : <EOL> """<STR_LIT>""" <EOL> history = self . history <EOL> for i in range ( history . now - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> items = history . history [ i ] <EOL> for j in range ( len ( items ) - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> items [ j ] . undo ( ) <EOL> def redo ( self ) : <EOL> """<STR_LIT>""" <EOL> history = self . history <EOL> for i in range ( <NUM_LIT:0> , history . now ) : <EOL> for item in history . history [ i ] : <EOL> item . redo ( ) </s>
