This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 51872
Collapse All | Expand All

(-)arch/arch-openide-editor.xml (+15 lines)
Lines 375-380 Link Here
375
This property can be used by the modules and is part of the Editor API.
375
This property can be used by the modules and is part of the Editor API.
376
</api>
376
</api>
377
377
378
<api type="export" group="property" name="javax.swing.text.Document.beforeModificationListener" category="friend" >
379
In order to fix <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=51872">issue 51872</a> the 
380
openide needs a way how to be notified about change of a document outside of its Document lock. 
381
<code>DocumentListener</code>s are always notified under the lock, so a special contract has
382
been established (since version 5.3) by registering an instance of <code>VetoableListener</code>
383
by calling <code>putProperty ("beforeModificationListener", listener)</code>. The
384
NetBeans aware document are adviced to honor this property and call the listener
385
outside of the document lock when a modification is made. The actual contract
386
of the call can be seen in 
387
<a href="http://www.netbeans.org/source/browse/openide/test/unit/src/org/openide/text/NbLikeEditorKit.java">NbLikeEditorKit.java</a> 
388
in methods 
389
<code>insertString</code> and <code>remove</code>.
390
391
</api>
392
378
</answer>
393
</answer>
379
394
380
395
(-)src/org/openide/text/CloneableEditorSupport.java (-48 / +53 lines)
Lines 556-563 Link Here
556
             public void run() {
556
             public void run() {
557
                 try {
557
                 try {
558
                     doc.removeDocumentListener(getListener());
558
                     doc.removeDocumentListener(getListener());
559
                     doc.putProperty ("beforeModificationListener", null); // NOI18N
559
                     doc.remove(0, doc.getLength()); // remove all text
560
                     doc.remove(0, doc.getLength()); // remove all text
560
                     doc.addDocumentListener(getListener());
561
                     doc.addDocumentListener(getListener());
562
                     doc.putProperty ("beforeModificationListener", getListener ()); // NOI18N
561
                 } catch(BadLocationException ble) {
563
                 } catch(BadLocationException ble) {
562
                     ErrorManager.getDefault().notify(
564
                     ErrorManager.getDefault().notify(
563
                         ErrorManager.INFORMATIONAL, ble);
565
                         ErrorManager.INFORMATIONAL, ble);
Lines 704-715 Link Here
704
        }
706
        }
705
        
707
        
706
        final StyledDocument myDoc = getDocument();
708
        final StyledDocument myDoc = getDocument();
707
        final IOException[] holder = new IOException[1];
708
	
709
	
709
	// save the document as a reader
710
        // save the document as a reader
710
        myDoc.render(new Runnable() {
711
        class SaveAsReader implements Runnable {
712
            private boolean doMarkAsUnmodified;
713
            private IOException ex;
714
                   
711
            public void run() {
715
            public void run() {
712
		try {
716
                try {
713
                    OutputStream os = null;
717
                    OutputStream os = null;
714
718
715
                    // write the document
719
                    // write the document
Lines 725-731 Link Here
725
                        // remember time of last save
729
                        // remember time of last save
726
                        lastSaveTime = System.currentTimeMillis();
730
                        lastSaveTime = System.currentTimeMillis();
727
731
728
                        notifyUnmodified ();
732
                        doMarkAsUnmodified = true;
729
733
730
                    } catch (BadLocationException ex) {
734
                    } catch (BadLocationException ex) {
731
                        ErrorManager.getDefault().notify(ex);
735
                        ErrorManager.getDefault().notify(ex);
Lines 744-757 Link Here
744
                    // update cached info about lines
748
                    // update cached info about lines
745
                    updateLineSet (true);
749
                    updateLineSet (true);
746
                    updateTitles ();
750
                    updateTitles ();
747
		} catch (IOException e) {
751
                } catch (IOException e) {
748
		    holder[0] = e;
752
                    this.ex = e;
749
		}
753
                }
750
            }
754
            }
751
        });
755
                
752
	
756
            public void after () throws IOException {
753
	// refire the exception
757
                if (doMarkAsUnmodified) {
754
	if (holder[0] != null) throw holder[0];
758
                    notifyUnmodified ();
759
                }
760
                
761
                if (ex != null) {
762
                    throw ex;
763
                }
764
            }
765
        }
766
        
767
        SaveAsReader saveAsReader = new SaveAsReader ();
768
        myDoc.render (saveAsReader);
769
        saveAsReader.after ();
755
    }
770
    }
756
771
757
    /**
772
    /**
Lines 1323-1337 Link Here
1323
    }
1338
    }
1324
    
1339
    
1325
    /** Conditionally calls notifyModified 
1340
    /** Conditionally calls notifyModified 
1341
     * @return true if the modification was allowed, false if it should be prohibited
1326
     */
1342
     */
1327
    private final void callNotifyModified () {
1343
    private final boolean callNotifyModified () {
1328
        if (!alreadyModified) {
1344
        if (!alreadyModified) {
1329
            alreadyModified = true;
1345
            alreadyModified = true;
1330
            if (!notifyModified ()) {
1346
            if (!notifyModified ()) {
1331
                revertUpcomingUndo ();
1347
                revertUpcomingUndo ();
1332
                alreadyModified = false;
1348
                alreadyModified = false;
1349
                return false;
1333
            }
1350
            }
1334
        }
1351
        }
1352
        return true;
1335
    }
1353
    }
1336
    
1354
    
1337
    /** Called when the document is being modified.
1355
    /** Called when the document is being modified.
Lines 1425-1430 Link Here
1425
                }
1443
                }
1426
                UndoRedo ur = getUndoRedo();
1444
                UndoRedo ur = getUndoRedo();
1427
                sd.removeDocumentListener(getListener());
1445
                sd.removeDocumentListener(getListener());
1446
                sd.putProperty ("beforeModificationListener", null); // NOI18N
1428
                try {
1447
                try {
1429
                    if(ur.canUndo()) {
1448
                    if(ur.canUndo()) {
1430
                        Toolkit.getDefaultToolkit().beep();
1449
                        Toolkit.getDefaultToolkit().beep();
Lines 1435-1440 Link Here
1435
                        ErrorManager.INFORMATIONAL, cne);
1454
                        ErrorManager.INFORMATIONAL, cne);
1436
                } finally {
1455
                } finally {
1437
                    sd.addDocumentListener(getListener());
1456
                    sd.addDocumentListener(getListener());
1457
                    sd.putProperty ("beforeModificationListener", getListener ()); // NOI18N
1438
                }
1458
                }
1439
            }
1459
            }
1440
        };
1460
        };
Lines 1494-1531 Link Here
1494
    }
1514
    }
1495
1515
1496
1516
1497
    // other public methods ................................................................
1498
1499
1500
    /* JST: Commented out
1501
    * Set actions for toolbar.
1502
    * @param actions list of actions
1503
    *
1504
    public void setActions (SystemAction[] actions) {
1505
        this.actions = actions;
1506
    }
1507
1508
    /** Utility method which enables or disables listening to modifications
1509
    * on asociated document.
1510
    * <P>
1511
    * Could be useful if we have to modify document, but do not want the
1512
    * Save and Save All actions to be enabled/disabled automatically.
1513
    * Initially modifications are listened to.
1514
    * @param listenToModifs whether to listen to modifications
1515
    *
1516
    public void setModificationListening (final boolean listenToModifs) {
1517
        if (this.listenToModifs == listenToModifs) return;
1518
        this.listenToModifs = listenToModifs;
1519
        if (doc == null) return;
1520
        if (listenToModifs)
1521
            doc.addi(getModifL());
1522
        else
1523
            doc.removeDocumentListener(getModifL());
1524
    }
1525
    */
1526
1527
1528
1529
    /** Loads the document for this object.
1517
    /** Loads the document for this object.
1530
    * @param kit kit to use
1518
    * @param kit kit to use
1531
    * @param d original document to load data into
1519
    * @param d original document to load data into
Lines 1617-1622 Link Here
1617
        if (doc != null) {
1605
        if (doc != null) {
1618
            doc.removeUndoableEditListener (getUndoRedo ());
1606
            doc.removeUndoableEditListener (getUndoRedo ());
1619
            doc.removeDocumentListener(getListener());
1607
            doc.removeDocumentListener(getListener());
1608
            doc.putProperty ("beforeModificationListener", null);
1620
        }
1609
        }
1621
1610
1622
        if (positionManager != null) {
1611
        if (positionManager != null) {
Lines 1949-1957 Link Here
1949
     * document, environment and also temporarilly on undoredo.
1938
     * document, environment and also temporarilly on undoredo.
1950
     */
1939
     */
1951
    private final class Listener extends Object
1940
    private final class Listener extends Object
1952
    implements ChangeListener, DocumentListener, PropertyChangeListener, Runnable {
1941
    implements ChangeListener, DocumentListener, PropertyChangeListener, 
1942
    Runnable, java.beans.VetoableChangeListener {
1953
1943
1954
	Listener() {}
1944
        Listener() {}
1955
1945
1956
        /** Stores exception from loadDocument, can be set in run method */
1946
        /** Stores exception from loadDocument, can be set in run method */
1957
        private IOException loadExc;
1947
        private IOException loadExc;
Lines 1993-1998 Link Here
1993
            //modified(); (bugfix #1492)
1983
            //modified(); (bugfix #1492)
1994
        }
1984
        }
1995
1985
1986
        public void vetoableChange (PropertyChangeEvent evt) throws java.beans.PropertyVetoException {
1987
            if ("modified".equals (evt.getPropertyName ())) { // NOI18N
1988
                if (Boolean.TRUE.equals (evt.getNewValue ())) {
1989
                    if (!callNotifyModified ()) {
1990
                        throw new java.beans.PropertyVetoException ("Not allowed", evt); // NOI18N
1991
                    }
1992
                } else {
1993
                    notifyUnmodified ();
1994
                }
1995
            }
1996
        }
1997
1996
        /** Gives notification that there was an insert into the document.
1998
        /** Gives notification that there was an insert into the document.
1997
        * @param ev event describing the action
1999
        * @param ev event describing the action
1998
        */
2000
        */
Lines 2054-2059 Link Here
2054
                 * which can prevent dedloks that sometimes occured during file reload.
2056
                 * which can prevent dedloks that sometimes occured during file reload.
2055
                 */
2057
                 */
2056
                 doc.removeDocumentListener(getListener());
2058
                 doc.removeDocumentListener(getListener());
2059
                 doc.putProperty ("beforeModificationListener", null); // NOI18N
2057
                 try {
2060
                 try {
2058
                    loadExc = null; 
2061
                    loadExc = null; 
2059
                    LOCAL_LOAD_TASK.set(Boolean.TRUE);
2062
                    LOCAL_LOAD_TASK.set(Boolean.TRUE);
Lines 2079-2085 Link Here
2079
                 
2082
                 
2080
                 // Start listening on changes in document
2083
                 // Start listening on changes in document
2081
                 doc.addDocumentListener(getListener());
2084
                 doc.addDocumentListener(getListener());
2085
                 doc.putProperty ("beforeModificationListener", getListener ()); // NOI18N // NOI18N
2082
            }   
2086
            }   
2087
2083
//        }
2088
//        }
2084
    }
2089
    }
2085
2090
Lines 2286-2292 Link Here
2286
        public void undo() {
2291
        public void undo() {
2287
            super.undo();
2292
            super.undo();
2288
2293
2289
            if (saveTime == lastSaveTime) {
2294
            if (saveTime == lastSaveTime && alreadyModified) {
2290
                notifyUnmodified();
2295
                notifyUnmodified();
2291
            }
2296
            }
2292
        }
2297
        }
(-)test/unit/src/org/openide/text/NbLikeEditorKit.java (-8 / +69 lines)
Lines 14-19 Link Here
14
14
15
package org.openide.text;
15
package org.openide.text;
16
16
17
import java.beans.VetoableChangeListener;
17
import javax.swing.text.*;
18
import javax.swing.text.*;
18
19
19
/**
20
/**
Lines 37-54 Link Here
37
        }
38
        }
38
39
39
        public void runAtomic (Runnable r) {
40
        public void runAtomic (Runnable r) {
40
            runAtomicAsUser (r);
41
        }
42
43
        public void runAtomicAsUser (Runnable r) {// throws BadLocationException;
44
            writeLock ();
45
            try {
41
            try {
46
                r.run ();
42
                runAtomicAsUser (r);
47
            } finally {
43
            } catch (BadLocationException ex) {
48
                writeUnlock ();
44
                throw (IllegalStateException)new IllegalStateException (ex.getMessage ()).initCause (ex);
49
            }
45
            }
50
        }
46
        }
51
47
48
        public void runAtomicAsUser (Runnable r) throws BadLocationException {
49
             insOrRemoveOrRunnable (-1, null, null, -1, false, r);
50
        }
51
52
        public javax.swing.text.Style getLogicalStyle(int p) {
52
        public javax.swing.text.Style getLogicalStyle(int p) {
53
            return null;
53
            return null;
54
        }
54
        }
Lines 88-92 Link Here
88
        public java.awt.Color getForeground(javax.swing.text.AttributeSet attr) {
88
        public java.awt.Color getForeground(javax.swing.text.AttributeSet attr) {
89
            return null;
89
            return null;
90
        }
90
        }
91
92
        private int changes;
93
        public void insertString (int offs, String str, AttributeSet a) throws BadLocationException {
94
            insOrRemoveOrRunnable (offs, str, a, 0, true, null);
95
        }
96
97
        public void remove (int offs, int len) throws BadLocationException {
98
            insOrRemoveOrRunnable (offs, null, null, len, false, null);
99
        }
100
        
101
        
102
        private void insOrRemoveOrRunnable (int offset, String str, AttributeSet set, int len, boolean insert, Runnable run) 
103
        throws BadLocationException {
104
            Object o = getProperty ("beforeModificationListener");
105
            if (o instanceof VetoableChangeListener) {
106
                VetoableChangeListener l = (VetoableChangeListener)o;
107
                try {
108
                    l.vetoableChange (new java.beans.PropertyChangeEvent (this, "modified", null, Boolean.TRUE));
109
                } catch (java.beans.PropertyVetoException ex) {
110
                    return;
111
                }
112
            }
113
            
114
            boolean unmodify = false;
115
            try {
116
                if (run != null) {
117
                    writeLock ();
118
                    int prevChanges = changes;
119
                    try {
120
                        run.run ();
121
                    } finally {
122
                        writeUnlock ();
123
                    }
124
                    if (changes == prevChanges) {
125
                        notifyUnmodified (o);
126
                    }
127
                } else {
128
                    changes++;
129
                    if (insert) {
130
                        super.insertString (offset, str, set);
131
                    } else {
132
                        super.remove(offset, len);
133
                    }
134
                }
135
            } catch (BadLocationException ex) {
136
                notifyUnmodified (o);
137
                throw ex;
138
            }
139
        }
140
        
141
        private void notifyUnmodified (Object o) {
142
            if (o instanceof VetoableChangeListener) {
143
                VetoableChangeListener l = (VetoableChangeListener)o;
144
                try {
145
                    l.vetoableChange (new java.beans.PropertyChangeEvent (this, "modified", null, Boolean.FALSE));
146
                } catch (java.beans.PropertyVetoException ignore) {
147
                    // ignore this
148
                }
149
            }
150
        }
151
91
    } // end of Doc
152
    } // end of Doc
92
}
153
}
(-)test/unit/src/org/openide/text/NotifyModifiedOnNbEditorLikeKitTest.java (+83 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 * 
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 * 
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.openide.text;
15
16
import java.io.ByteArrayOutputStream;
17
import java.io.IOException;
18
import java.io.InputStream;
19
import java.util.Arrays;
20
import junit.framework.*;
21
22
import org.netbeans.junit.*;
23
24
import org.openide.util.Lookup;
25
import org.openide.util.lookup.*;
26
27
28
/** Testing different features of NotifyModifieTest with NbEditorKit
29
 *
30
 * @author Jaroslav Tulach
31
 */
32
public class NotifyModifiedOnNbEditorLikeKitTest extends NotifyModifiedTest {
33
    private NbLikeEditorKit k;
34
    
35
    public NotifyModifiedOnNbEditorLikeKitTest (String s) {
36
        super (s);
37
    }
38
    
39
    //
40
    // overwrite editor kit
41
    //
42
    
43
    protected javax.swing.text.EditorKit createEditorKit () {
44
        NbLikeEditorKit k = new NbLikeEditorKit ();
45
        return k;
46
    }
47
    
48
    protected void checkThatDocumentLockIsNotHeld () {
49
        class X implements Runnable {
50
            private boolean second;
51
            private boolean ok;
52
53
            public void run () {
54
                if (second) {
55
                    ok = true;
56
                    return;
57
                } else {
58
                    second = true;
59
                    javax.swing.text.Document doc = support.getDocument ();
60
                    assertNotNull (doc);
61
                    // we have to pass thru read access
62
                    doc.render (this);
63
                    
64
                    if (ok) {
65
                        try {
66
                            // we have to be allowed to do modifications as well
67
                            doc.insertString (0, "A", null);
68
                            doc.remove (0, 1);
69
                        } catch (javax.swing.text.BadLocationException ex) {
70
                            ok = false;
71
                        }
72
                    }
73
                        
74
                    return;
75
                }
76
            }
77
        }
78
79
        X x = new X ();
80
        org.openide.util.RequestProcessor.getDefault ().post (x).waitFinished ();
81
        assertTrue ("No lock is held on document when running notifyModified", x.ok);
82
    }
83
}
(-)test/unit/src/org/openide/text/NotifyModifiedTest.java (-27 / +97 lines)
Lines 32-38 Link Here
32
public class NotifyModifiedTest extends NbTestCase 
32
public class NotifyModifiedTest extends NbTestCase 
33
implements CloneableEditorSupport.Env {
33
implements CloneableEditorSupport.Env {
34
    /** the support to work with */
34
    /** the support to work with */
35
    private CES support;
35
    protected CES support;
36
    /** the content of lookup of support */
36
    /** the content of lookup of support */
37
    private InstanceContent ic;
37
    private InstanceContent ic;
38
38
Lines 45-50 Link Here
45
    private java.util.List/*<java.beans.PropertyChangeListener>*/ propL = new java.util.ArrayList ();
45
    private java.util.List/*<java.beans.PropertyChangeListener>*/ propL = new java.util.ArrayList ();
46
    private java.beans.VetoableChangeListener vetoL;
46
    private java.beans.VetoableChangeListener vetoL;
47
    private boolean shouldVetoNotifyModified;
47
    private boolean shouldVetoNotifyModified;
48
    /** kit to create */
49
    private javax.swing.text.EditorKit editorKit;
48
50
49
    
51
    
50
    public NotifyModifiedTest(java.lang.String testName) {
52
    public NotifyModifiedTest(java.lang.String testName) {
Lines 56-61 Link Here
56
        support = new CES (this, new AbstractLookup (ic));
58
        support = new CES (this, new AbstractLookup (ic));
57
    }
59
    }
58
    
60
    
61
    
62
    //
63
    // overwrite editor kit
64
    //
65
    
66
    protected javax.swing.text.EditorKit createEditorKit () {
67
        return null;
68
    }
69
    
70
    protected void checkThatDocumentLockIsNotHeld () {
71
    }
72
73
    
74
    //
75
    // test methods
76
    //
77
78
    
59
    public void testJustOneCallToModified () throws Exception {
79
    public void testJustOneCallToModified () throws Exception {
60
        content = "Line1\nLine2\n";
80
        content = "Line1\nLine2\n";
61
        
81
        
Lines 91-101 Link Here
91
        // should be reverted in SwingUtilities.invokeLater
111
        // should be reverted in SwingUtilities.invokeLater
92
        doc.insertString (0, "Ahoj", null);
112
        doc.insertString (0, "Ahoj", null);
93
        waitEQ ();
113
        waitEQ ();
114
        
115
        assertEquals ("One modification called (but it was vetoed)", 1, support.notifyModified);
116
        assertEquals ("No unmodification called", 0, support.notifyUnmodified);
117
118
        String first = doc.getText (0, 1);
119
        assertEquals ("First letter is N", "N", first);
120
    }
121
    public void testBadLocationException () throws Exception {
122
        content = "Nic\n";
123
        
124
        // in order to set.getLines() work correctly, the document has to be loaded
125
        javax.swing.text.Document doc = support.openDocument();
126
        assertEquals ("No modification", 0, support.notifyModified);
127
        
128
        try {
129
            doc.insertString (10, "Ahoj", null);
130
            fail ("This should generate bad location exception");
131
        } catch (javax.swing.text.BadLocationException ex) {
132
            // ok
133
        }
134
        
135
        int expected = createEditorKit () instanceof NbLikeEditorKit ? 1 : 0;
136
        assertEquals (expected + " modification called (but it was vetoed)", expected, support.notifyModified);
137
        assertEquals (expected + " unmodification called", expected, support.notifyUnmodified);
94
138
95
        String first = doc.getText (0, 1);
139
        String first = doc.getText (0, 1);
96
        assertEquals ("First letter is N", "N", first);
140
        assertEquals ("First letter is N", "N", first);
97
    }
141
    }
98
    
142
    
143
    public void testDoModificationsInAtomicBlock () throws Exception {
144
        content = "Something";
145
        
146
        final javax.swing.text.StyledDocument doc = support.openDocument();
147
148
        
149
        class R implements Runnable {
150
            public void run () {
151
                try {
152
                    doc.insertString (0, "Ahoj", null);
153
                } catch (javax.swing.text.BadLocationException ex) {
154
                    AssertionFailedError e = new AssertionFailedError (ex.getMessage ());
155
                    e.initCause (ex);
156
                    throw e;
157
                }
158
            }
159
        }
160
        
161
        R r = new R ();
162
        
163
        NbDocument.runAtomic (doc, r);
164
        
165
        assertEquals ("One modification", 1, support.notifyModified);
166
        assertEquals ("no unmod", 0, support.notifyUnmodified);
167
    }
168
    
169
    public void testAtomicBlockWithoutModifications () throws Exception {
170
        content = "Something";
171
        
172
        final javax.swing.text.StyledDocument doc = support.openDocument();
173
174
        
175
        class R implements Runnable {
176
            public void run () {
177
            }
178
        }
179
        
180
        R r = new R ();
181
        
182
        NbDocument.runAtomic (doc, r);
183
184
        assertEquals ("The same number of modification and unmodifications", support.notifyModified, support.notifyUnmodified);
185
    }
99
    
186
    
100
    private void waitEQ () throws Exception {
187
    private void waitEQ () throws Exception {
101
        javax.swing.SwingUtilities.invokeAndWait (new Runnable () { public void run () { } });
188
        javax.swing.SwingUtilities.invokeAndWait (new Runnable () { public void run () { } });
Lines 165-197 Link Here
165
        checkThatDocumentLockIsNotHeld ();
252
        checkThatDocumentLockIsNotHeld ();
166
    }
253
    }
167
    
254
    
168
    private void checkThatDocumentLockIsNotHeld () {
169
        /*
170
        class X implements Runnable {
171
            private boolean second;
172
            private boolean ok;
173
            
174
            public void run () {
175
                if (second) {
176
                    ok = true;
177
                    return;
178
                } else {
179
                    second = true;
180
                    javax.swing.text.Document doc = support.getDocument ();
181
                    assertNotNull (doc);
182
                    doc.render (this);
183
                    return;
184
                }
185
            }
186
        }
187
        
188
        X x = new X ();
189
        org.openide.util.RequestProcessor.getDefault ().post (x).waitFinished ();
190
         */
191
    }
192
193
    /** Implementation of the CES */
255
    /** Implementation of the CES */
194
    private final class CES extends CloneableEditorSupport {
256
    protected final class CES extends CloneableEditorSupport {
195
        public int notifyUnmodified;
257
        public int notifyUnmodified;
196
        public int notifyModified;
258
        public int notifyModified;
197
        
259
        
Lines 235-240 Link Here
235
            boolean retValue;            
297
            boolean retValue;            
236
            retValue = super.notifyModified();
298
            retValue = super.notifyModified();
237
            return retValue;
299
            return retValue;
300
        }
301
        
302
        protected javax.swing.text.EditorKit createEditorKit() {
303
            javax.swing.text.EditorKit k = NotifyModifiedTest.this.createEditorKit ();
304
            if (k != null) {
305
                return k;
306
            } 
307
            return super.createEditorKit ();
238
        }
308
        }
239
        
309
        
240
    }
310
    }

Return to bug 51872