Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- global UndoLayer = {};
- function UndoLayer.create()
- {
- data =
- {
- object_types = {},
- feedback_out = {},
- undo_states = [],
- current_pos = 0,
- change = null,
- };
- class( data, UndoLayer );
- data.registerFeedbackOutput( "undolayer", this._registerChange );
- return data;
- }
- // S E T U P
- function UndoLayer.registerObject( obj, fnobj, fn_add, fn_rem, fn_getstate, fn_getprop, fn_setprop )
- {
- if( @this.object_types[ obj ] )
- return WARNING( "object already registered: " $ obj );
- this.object_types[ obj ] =
- {
- fnobj = fnobj,
- add = fn_add,
- rem = fn_rem,
- getstate = fn_getstate,
- getprop = fn_getprop,
- setprop = fn_setprop
- };
- }
- function UndoLayer.registerFeedbackOutput( name, func )
- {
- this.feedback_out[ name ] = func;
- }
- function UndoLayer.unregisterFeedbackOutput( name )
- {
- unset( this.feedback_out, name );
- }
- // U N D O - using
- function UndoLayer.undo()
- {
- if( this.current_pos == 0 )
- return WARNING( "cannot undo - limit reached" );
- cp = --this.current_pos;
- state = this.undo_states[ cp ];
- if( state.type == "add" )
- this.doRemove( "undolayer", state.objtype, state.id );
- else if( state.type == "remove" )
- {
- id = this.doAdd( "undolayer", state.objtype, state.state );
- if( id != state.id )
- return WARNING( "data link error: returned object ID mismatch" );
- }
- else if( state.type == "change" )
- this.doChange( "undolayer", state.objtype, state.id, state.state_from );
- }
- function UndoLayer.redo()
- {
- if( this.current_pos == this.undo_states.size )
- return WARNING( "cannot undo - limit reached" );
- cp = ++this.current_pos;
- state = this.undo_states[ cp ];
- if( state.type == "add" )
- {
- id = this.doAdd( "undolayer", state.objtype, state.state );
- if( id != state.id )
- return WARNING( "data link error: returned object ID mismatch" );
- }
- else if( state.type == "remove" )
- this.doRemove( "undolayer", state.objtype, state.id );
- else if( state.type == "change" )
- this.doChange( "undolayer", state.objtype, state.id, state.state_to );
- }
- function UndoLayer.getCurrentPos(){ return this.current_pos; }
- function UndoLayer.getStateCount(){ return this.undo_states.size; }
- function UndoLayer.setCurrentPos( pos )
- {
- if( pos < 0 || pos > this.undo_states.size )
- return WARNING( "undo position out of bounds" );
- while( pos > this.current_pos )
- this.redo();
- while( pos < this.current_pos )
- this.undo();
- }
- // U N D O - building
- function UndoLayer.beginChange()
- {
- if( this.change !== null )
- return WARNING( "already making change" );
- this.change = [];
- }
- function UndoLayer.discardChange()
- {
- if( this.change === null )
- return WARNING( "not making change" );
- this.change = null;
- }
- function UndoLayer.revertDiscardChange()
- {
- if( this.change === null )
- return WARNING( "not making change" );
- this.commitChange( "__tmp__" );
- this.undo();
- this.pop();
- }
- function UndoLayer.commitChange( name )
- {
- if( this.change === null )
- return WARNING( "not making change" );
- undo_states.push({ name = name, changes = this.change });
- this.change = null;
- }
- function UndoLayer.isMakingChange(){ return this.change !== null; }
- // E D I T I N G
- function UndoLayer.doAdd( src, objtype, props )
- {
- OT = @this.object_types[ objtype ];
- if( !OT )
- return WARNING( "object type not registered: " $ objtype );
- fnobj = OT.fnobj;
- fn_add = OT.fn_add;
- fn_getstate = OT.fn_getstate;
- id = fnobj!fn_add( props );
- state = fnobj!fn_getstate( id );
- this._invokeFeedback( src, "add", objtype, id, state );
- return id;
- }
- function UndoLayer.doRemove( src, objtype, id )
- {
- OT = @this.object_types[ objtype ];
- if( !OT )
- return WARNING( "object type not registered: " $ objtype );
- fnobj = OT.fnobj;
- fn_rem = OT.fn_rem;
- fn_getstate = OT.fn_getstate;
- state = fnobj!fn_getstate( id );
- fnobj!fn_rem( id );
- this._invokeFeedback( src, "remove", objtype, id, state );
- }
- function UndoLayer.doChange( src, objtype, id, changes )
- {
- OT = @this.object_types[ objtype ];
- if( !OT )
- return WARNING( "object type not registered: " $ objtype );
- fnobj = OT.fnobj;
- fn_setprops = OT.fn_setprops;
- fn_getprops = OT.fn_getprops;
- state = fnobj!fn_getprops( id, changes );
- fnobj!fn_setprops( id, changes );
- this._invokeFeedback( src, "change", objtype, id, state, changes );
- }
- // L O O P B A C K
- function UndoLayer._registerChange( src, action, objtype, id, state, state_to )
- {
- if( src == "undolayer" )
- return;
- if( this.change === null )
- return WARNING( "not making change" );
- if( action == "add" )
- {
- this.change.push({ objtype = objtype, type = "add", id = id, state = state });
- }
- else if( action == "remove" )
- {
- this.change.push({ objtype = objtype, type = "remove", id = id, state = state });
- }
- else if( action == "change" )
- {
- this.change.push({ objtype = objtype, type = "change", state_from = state, state_to = state_to });
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement