# JTextPane, StyledDocument & UndoManager



## ugh_bough_ (3. Mrz 2005)

Hi.
Ich habe ein Problem und weiss nicht weiter. Kann mir jemand helfen?

1. Ich habe ein JTextPane.
2. Dieses JTextPane kommuniziert bei Textänderungen mit einem UndoManager.
3. Alles funktioniert prima.
4. Wenn ich aber anfange Teile des Texts zu highlighten (mit Hilfe von textPane.getStyledDocument().setCharacterAttributes(...) und einem Style, den ich vorher vom JTextPane bekommen und mit StyleConstants angepasst habe), so tun sich Probleme auf. Wenn ich direkt hinter einer gehighlighteten Stelle eine Zeile umbreche und dann "Undo" betätige, so ist auf einmal aller Text nach dem Umbruch verschwunden. Nur der Text, der vor dem Umbruch stand ist noch da.
5. Komischerweise kann man den Text mit einer neuen Betätigung von "Redo" wieder ins JTextPane reinholen und zwar so wie man es denken würde --- nämlich in dem Zustand genau nach dem Umbruch.

Ich denke mal dass es ziemlich aussichtslos ist, aber wenn doch jemand ne spontane Idee hat...  :cry: 
ugh_bough


----------



## Roar (3. Mrz 2005)

1. das is gut )
2. besser )
3. schönschön )
4. whoa???
5. whoa?

also ich arbeite auch grad mit JTextPane, UndoManager und StyledDocuments und STyles zusammen  
ein problem was ich da festgestellt hab, war, dass veränderungen der styles am styleddocument auch ein undo event auslösen. vielleicht ist das, was bei dir stört. ich hab das einfach so gelöst:

```
if(!"style change".equals(evt.getEdit().getPresentationName()))
					undo.addEdit(evt.getEdit());
```

das steht in der undoableEventHappened() ... das geht noch schöner,. bin aber im moment zu faul das zu implementieren. ich glaub auch, dass das nur geht wenn Locale auf EN ist. probiers mal zum testen ob das problem daran liegt, denn ich kann mir dein prob auch nich wirklich erklären


----------



## ugh_bough_ (3. Mrz 2005)

danke für den tip. hatte vergessen zu erwähnen, dass ich das schon erledigt habe. In undoableEventHappened() werden nur die Events verarbeitet, die auch verarbeitet werden dürfen. Kommt auch ein bisschen auf die Knöpfe an, die man drückt --- da sind nicht alle erlaubt. Da ist der Haken aber auch nicht. Alles schon gecheckt. Das liegt echt an dem Sch*@!# Highlighting... naja... eigentlich ists ja ne schöne Sache, wenns funzt...


----------



## Roar (3. Mrz 2005)

hmm...

kansnt du mir das prog ma schicken oder nen bisschen source posten? ich kann das prob wie gesagt nich nachvollziehen....


----------



## ugh_bough (3. Mrz 2005)

Konstruktor des Panels, in dem sich alles abpielt:

```
private PanelAnalysis()
    {
        initComponents();
        
        // set up styles for highlighting in the JTextPane
        styleNormal = jtpEditPane.addStyle("normal", null);
        styleNeedle = jtpEditPane.addStyle("needle", null);
        styleVector = jtpEditPane.addStyle("vector", null);
        
        StyleConstants.setBold(styleNeedle, true);
        StyleConstants.setBold(styleVector, true);
        StyleConstants.setForeground(styleVector, Color.BLUE);
        
        // important, because the undoableEditListener should not react to
        // eventType == CHANGE which is for example invoked on syntax highlighting
        jtpEditPane.getDocument().addDocumentListener(new DocumentListener()
        {
            public void changedUpdate(DocumentEvent e)  { eventType = e.getType(); }
            public void removeUpdate(DocumentEvent e)   { eventType = e.getType(); }
            public void insertUpdate(DocumentEvent e)   { eventType = e.getType(); }
        });
        
        // this listener takes care of undohandling
        // also updates the gui if user chanaged the text
        jtpEditPane.getDocument().addUndoableEditListener(new UndoableEditListener()
        {
            public void undoableEditHappened(UndoableEditEvent e)
            {
                if (eventType == DocumentEvent.EventType.CHANGE)
                    return;

                if (eventConsumed)
                    return;
                
                // save
                undoManager.addEdit(e.getEdit());
            }
        });
    }
```
das Panel hat die Members "eventType" und "eventConsumed", welche beschreiben, welche Art von Event auftrat und ob ein Event gültig ist.

diese Methode highlightet drei unterschiedliche Arten von Schlüsselwörtern. vorher reinigt sie alle bisherigen highlights. die wird immer beim gültigen input in das JTextPane aufgerufen und highlightet natürlich nur das richtige. 

```
private void highlightSequence()
    {
        int index;
        String sequence = jtpEditPane.getText();
        
        // clear style
        jtpEditPane.getStyledDocument().setCharacterAttributes(0, sequence.length(), styleNormal, true);

        // add needle style
        int offset = 0;
        while ((index = sequence.indexOf(settings.needle, offset)) != -1)
        {
            jtpEditPane.getStyledDocument().setCharacterAttributes(index, settings.needle.length(), styleNeedle, true);
            offset = index + settings.needle.length();
        }
        
        // left vector
        index = sequence.indexOf(settings.vectLeft);
        if (index != -1)
            jtpEditPane.getStyledDocument().setCharacterAttributes(index, settings.vectLeft.length(), styleVector, true);
        
        // right vector
        index = sequence.indexOf(settings.vectRight);
        if (index != -1)
            jtpEditPane.getStyledDocument().setCharacterAttributes(index, settings.vectRight.length(), styleVector, true);
    }
```

und natürlich noch

```
private void jbUndoActionPerformed(java.awt.event.ActionEvent evt) {                                       
        undoManager.undo();
        
        jbUndo.setEnabled(undoManager.canUndo());
        jbRedo.setEnabled(undoManager.canRedo());
        
        highlightSequence();
        jtpEditPane.requestFocus();
        
        jbReload.setEnabled(undoManager.canUndo());
    }
```
redoActionPerformed() ist analog aufgebaut.

*kopfkratz*


----------



## ugh_bough (3. Mrz 2005)

streich zeile 25 im ersten code.
da hatte ich den fehler vermutet. hab das jetzt schon entfernt...
ist ja auch designmäßig klüger finde ich


----------

