1. #1
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    9
    Vote Rating
    0
    smitzkus is on a distinguished road

      0  

    Default Undo Redo for Grid-Editing

    Undo Redo for Grid-Editing


    Hello,

    i'm new to GXT and just evaluating GXT for one of our customers. One of the requirements is undo/redo functionality in grids. Can anybody tell me how complex it would be to develop undo/redo support for GXT grids? A short explanation or a code-sample would be very welcome.

    Thanks in advance
    Steve

  2. #2
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,731
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      1  

    Default


    (No code sample here, but brief discussion that should push you in the right direction)

    GXT looks at data models via a ValueProvider interface - this describes how values can be read and written to a given model - these can be thought of as a 'property' on a bean. The Store.Change interface allows a ValueProvider<M,V> to be paired with a value of type V, to be later applied to a model in the store of type M.

    Rather than manipulating items in the store directly, the Store exposes Record objects which wrap the models and keep track of what changes have been applied to them. In many cases, this is the most 'undo' that is needed, and so all that the library supports by default - Changes can be added to a Record, removed (reverted to the original value), and committed (make the modified value into the new 'original' value). The entire Record can also be reverted, losing all changes that have been added since the last commit().

    Knowing this, you can watch for changes, and put them on an 'undo stack' as they happen. Performing an undo action then is a matter of popping the top item off the stack, undoing it, and pushing it onto a 'redo stack'. Redo then is the opposite - from redo stack to undo, and perform the action instead of un-performing. If any non-undo/redo action happens (such as a normal edit), dump the redo stack and put this new action onto the undo stack.

  3. #3
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    9
    Vote Rating
    0
    smitzkus is on a distinguished road

      0  

    Default


    Thanks Colin for your detailed answer. I tried implementing your idea using the command pattern.
    Here is my Code of the Command:

    Code:
    public class GridCellChangeCommand<M,V> implements Command {
        
        private Store<M>.Record record;
        private ValueProvider<? super M, V> provider;
        private Change<M, ?> change;
            
        public GridCellChangeCommand (Store<M>.Record record, ValueProvider<? super M, V> provider) {
            this.record = record;
            this.provider = provider;
            for(Change<M, ?> change : record.getChanges()) {
                this.change = change;
            }
        }
    
        @Override
        public void execute() {
            
        }
    
        @Override
        public void undo() {
            record.revert(provider);
        }
    
        @Override
        public void redo() {
            record.addChange(provider, (V) change.getValue());
        }
    }
    And here is the code, that generates the command and put it to the undo stack:
    Code:
    protected <M> void register(Grid<M> grid) {
            grid.getStore().addStoreRecordChangeHandler(new StoreRecordChangeHandler<M>() {
                @Override
                public void onRecordChange(StoreRecordChangeEvent<M> event) {
                    Store<M>.Record rec = event.getRecord();
                    ValueProvider<? super M, ?> prop = event.getProperty();
                    GridCellChangeCommand<M, ?> c = new GridCellChangeCommand((Record) rec, prop);
                    undoStack.push(c);
                    eventBus.fireEvent(new UndoableEvent());
                }
            });
        }

    The first problem is, that record.getChanges() in my command class always returns one change, I would have expected, that it returns all changes that was made to the record. A closer look at the source of method Record#addChange shows that
    Code:
    changes.put(c.getChangeTag(), c);
    is responsibly for that, because c#getChangeTag() always returns the same valueProvider and so the new change always replaces the old change (same key). Can you tell me the reason for that?
    The second problem is, that my redo-method adds a change to the record what ends up in firing a new StoreUpdateEvent, so my listener generates a new undo-command.
    I'm not sure if it would be easier to set the auto-commit in store to false and implementing the changes by myself...Any ideas for solving my problems?

Thread Participants: 1

Tags for this Thread

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi