# UndoManager



## tb303 (7. Mai 2007)

Hallo,
ich habe ein contentpane in dem bilder gezeichnet werden und Text.
Kann ich für die Aktionen dort einen UndoManager aufsetzen, so dass undo, redo, etc. funktionieren?

Habe es nicht hinbekommen   

Hier das Beispiel aus Java ist auch eine Insel: http://www.galileocomputing.de/openbook/javainsel6/javainsel_14_023.htm#Xxx1001958

Danach hab ich mich gehalten - ging aber nicht.


```
//    final UndoManager undomanager = new MyUndoManager(); 
    final UndoManager undomanager = new UndoManager(); 
    textarea.getDocument().addUndoableEditListener( undomanager ); 
    undomanager.setLimit( 1000 )
```

mein contentpane heißt c - ich kann doch nicht c.getDocument()... machen - welche Methode brauche ich da?
Sorry - bin ein bloody noob  :shock: 

Danke...


----------



## EOB (7. Mai 2007)

hi, probier mal so...


```
JTextComponent textcomp = new JTextArea();
    final UndoManager undo = new UndoManager();
    Document doc = textcomp.getDocument();
    
    // Listen for undo and redo events
    doc.addUndoableEditListener(new UndoableEditListener() {
        public void undoableEditHappened(UndoableEditEvent evt) {
            undo.addEdit(evt.getEdit());
        }
    });
    
    // Create an undo action and add it to the text component
    textcomp.getActionMap().put("Undo",
        new AbstractAction("Undo") {
            public void actionPerformed(ActionEvent evt) {
                try {
                    if (undo.canUndo()) {
                        undo.undo();
                    }
                } catch (CannotUndoException e) {
                }
            }
       });
    
    // Bind the undo action to ctl-Z
    textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");
    
    // Create a redo action and add it to the text component
    textcomp.getActionMap().put("Redo",
        new AbstractAction("Redo") {
            public void actionPerformed(ActionEvent evt) {
                try {
                    if (undo.canRedo()) {
                        undo.redo();
                    }
                } catch (CannotRedoException e) {
                }
            }
        });
    
    // Bind the redo action to ctl-Y
    textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
```

grüße


----------



## tb303 (7. Mai 2007)

Hallo,

Danke für die schnelle Antwort.
Aber ich habe noch eine rage: Wieso nimmst du dort eine JTextarea - ich hab ein contentpane was bilder enthält (bilder werden gezeichnet) - Text einfügen geht (noch) nicht...

Ich dachte der Undomanager muss auf das contentpane "aufpassen"?

mfg


----------



## EOB (7. Mai 2007)

häng den code einfach da dran...du musst keine neue textarea anlegen.

grüße


----------



## tb303 (7. Mai 2007)

```
public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0,0,breite, hoehe);
        if(image != null)
        g2d.drawImage(image, startx,starty,image.getWidth(), image.getHeight(), this);
        g.drawImage(zielimage, 0,0, this);
        }
```

das ist Methode für das "Bild malen" - in das contentpane.
Soll der UndoManager da jetzt auf das "g" gucken? Was dort passiert?

Sorry wenn ich mich so dumm anstell...


----------



## André Uhres (10. Mai 2007)

Man könnte über einen UndoableEdit alle Änderungen aufzeichnen, die im Contentpane vorkommen.
Dazu müsste man aber eine Möglichkeit haben, die jeweilige Änderung
rückgängig zu machen(undo), bzw. neu zu machen(redo).
Eine Möglichkeit wäre, die Bilder in einer Liste abzuspeichern und in "paintComponent" 
einfach alles zu malen, was in der Liste drin ist.
Dazu braucht man natürlich noch einen UndoManager, der den Ablauf des Geschehens festhält
und einen UndoableEditSupport, der die Events verarbeitet.


----------



## tb303 (10. Mai 2007)

Ohne jetzt unverschämt zu sein wollen - aber könntest du das nochmal in Quellcode - zumindest auszugseise - zeigen...

So viel Ahnung hab ich davon nicht - leider... ich habe es schon probiert aber so wie ich es hatte kamen nur fehler und war nicht kompilierbar...

Danke


----------



## André Uhres (10. Mai 2007)

```
package undoredo;
/*
* UndoDemo.java
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.undo.*;
public class UndoDemo extends JFrame {
    private JMenu mEdit;
    private JMenuBar menubar;
    private JMenuItem miRedo;
    private JMenuItem miResize;
    private JMenuItem miUndo;
    private BildPanel bildPanel;
    private Image bild;
    private int x, y, w, h;
    /**
     * undo system elements:
     */
    private UndoManager undoManager;         // history list
    private UndoableEditSupport undoSupport; // event support
    public UndoDemo() {
        initComponents();
        bildPanel = new BildPanel();
        add(bildPanel);
        // initialize the undo-redo system:
        undoManager= new UndoManager();
        undoSupport = new UndoableEditSupport();
        undoSupport.addUndoableEditListener(new UndoAdapter());
        refreshUndoRedo();
    }
    private void initComponents() {
        menubar = new JMenuBar();
        mEdit = new JMenu("Edit");
        miUndo = new JMenuItem();
        miRedo = new JMenuItem();
        miResize = new JMenuItem("Bildgroesse");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        miUndo.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent evt) {
                miUndoActionPerformed(evt);
            }
        });
        mEdit.add(miUndo);
        miRedo.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent evt) {
                miRedoActionPerformed(evt);
            }
        });
        mEdit.add(miRedo);
        miResize.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent evt) {
                miResizeActionPerformed(evt);
            }
        });
        mEdit.add(miResize);
        menubar.add(mEdit);
        setJMenuBar(menubar);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
    }
    private void miResizeActionPerformed(final ActionEvent evt) {
        int w = Integer.parseInt(JOptionPane.showInputDialog("Breite"));
        int h = Integer.parseInt(JOptionPane.showInputDialog("Höhe"));
        if(w != this.w && h != this.h) {
            // record the effect:
            UndoableEdit edit = new SizeEdit(w, h, this.w, this.h);
            // notify the listeners:
            undoSupport.postEdit( edit );
        }
        this.w = w;
        this.h = h;
        bildPanel.repaint();
    }
    private void miRedoActionPerformed(final ActionEvent evt) {
        undoManager.redo();
        refreshUndoRedo();
    }
    private void miUndoActionPerformed(final ActionEvent evt) {
        undoManager.undo();
        refreshUndoRedo();
    }
    /**
     * An UndoableEditListener. The listener is notified when
     * an undoable edit occurs(e.g. add to the list)
     * The listener extracts the edit from the event, add it
     * to the UndoManager, and refresh the GUI
     */
    private class UndoAdapter implements UndoableEditListener {
        public void undoableEditHappened(final UndoableEditEvent evt) {
            UndoableEdit edit = evt.getEdit();
            undoManager.addEdit( edit );
            refreshUndoRedo();
        }
    }
    /**
     * This method is called after each undoable operation
     * in order to refresh the presentation state of the
     * undo/redo GUI
     */
    public void refreshUndoRedo() {
        // refresh undo
        miUndo.setText( undoManager.getUndoPresentationName() );
        miUndo.setEnabled( undoManager.canUndo() );
        // refresh redo
        miRedo.setText( undoManager.getRedoPresentationName() );
        miRedo.setEnabled( undoManager.canRedo() );
        if(bildPanel != null) bildPanel.repaint();
    }
    public static void main(String args[]) {new UndoDemo().setVisible(true);}
    class BildPanel extends JPanel {
        public BildPanel(){
            bild = new ImageIcon("c:\\Picture1.jpg").getImage();
            w = bild.getWidth(null);
            h = bild.getHeight(null);
        }
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(bild, x, y, w, h, null);
        }
    }
    /*
     * SizeEdit
     * UndoableEdit for the size-property
     */
    class SizeEdit extends AbstractUndoableEdit {
        private int wNew, hNew, wOld, hOld;
        public SizeEdit( final int wNew, final int hNew, final int wOld, final int hOld) {
            this.wNew = wNew;
            this.hNew = hNew;
            this.wOld = wOld;
            this.hOld = hOld;
        }
        public void undo() throws CannotUndoException {
            super.undo();
            w = wOld;
            h = hOld;
            bildPanel.repaint();
        }
        public void redo() throws CannotRedoException {
            super.redo();
            w = wNew;
            h = hNew;
            bildPanel.repaint();
        }
        public boolean canUndo() {return true;}
        public boolean canRedo() {return true;}
        public String getPresentationName() {return "Bildgrösse";}
    }
}
```


----------



## tb303 (10. Mai 2007)

wow... danke für die schnelle Hilfe. Ich probier das am Wochenende mal. Muss mich erstmal auf eine Englisch- und eine Matheklausur vobereiten...

Danke erstmal ))


----------

