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 180614
Collapse All | Expand All

(-)a/core.ui/src/org/netbeans/core/ui/resources/layer.xml (-2 / +8 lines)
Lines 84-96 Link Here
84
            </file>
84
            </file>
85
            <file name="org-openide-actions-GotoAction.instance"/>
85
            <file name="org-openide-actions-GotoAction.instance"/>
86
            <file name="org-openide-actions-PasteAction.instance"/>
86
            <file name="org-openide-actions-PasteAction.instance"/>
87
            <file name="org-openide-actions-RedoAction.instance"/>
87
            <file name="org-openide-actions-RedoAction.instance">
88
                <attr name="instanceCreate" methodvalue="org.openide.actions.UndoRedoAction.create"/>
89
                <attr name="undo" boolvalue="true"/>
90
            </file>
88
            <file name="org-openide-actions-ReplaceAction.instance">
91
            <file name="org-openide-actions-ReplaceAction.instance">
89
                <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.callback"/>
92
                <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.callback"/>
90
                <attr name="key" stringvalue="org.openide.actions.ReplaceAction"/>
93
                <attr name="key" stringvalue="org.openide.actions.ReplaceAction"/>
91
                <attr name="displayName" bundlevalue="org.openide.actions.Bundle#Replace"/>
94
                <attr name="displayName" bundlevalue="org.openide.actions.Bundle#Replace"/>
92
            </file>
95
            </file>
93
            <file name="org-openide-actions-UndoAction.instance"/>
96
            <file name="org-openide-actions-UndoAction.instance">
97
                <attr name="instanceCreate" methodvalue="org.openide.actions.UndoRedoAction.create"/>
98
                <attr name="redo" boolvalue="true"/>
99
            </file>
94
        </folder>
100
        </folder>
95
101
96
        <folder name="System">
102
        <folder name="System">
(-)a/openide.actions/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.openide.actions
2
OpenIDE-Module: org.openide.actions
3
OpenIDE-Module-Localizing-Bundle: org/openide/actions/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/actions/Bundle.properties
4
AutoUpdate-Essential-Module: true
4
AutoUpdate-Essential-Module: true
5
OpenIDE-Module-Specification-Version: 6.14
5
OpenIDE-Module-Specification-Version: 6.15
6
6
(-)a/openide.actions/src/org/openide/actions/RedoAction.java (-2 / +11 lines)
Lines 40-61 Link Here
40
 */
40
 */
41
package org.openide.actions;
41
package org.openide.actions;
42
42
43
import javax.swing.Action;
43
import org.openide.awt.UndoRedo;
44
import org.openide.awt.UndoRedo;
44
import org.openide.util.HelpCtx;
45
import org.openide.util.HelpCtx;
46
import org.openide.util.Lookup;
45
import org.openide.util.NbBundle;
47
import org.openide.util.NbBundle;
46
import org.openide.util.actions.CallableSystemAction;
48
import org.openide.util.actions.CallableSystemAction;
47
49
48
import javax.swing.UIManager;
50
import javax.swing.UIManager;
49
import javax.swing.undo.CannotRedoException;
51
import javax.swing.undo.CannotRedoException;
52
import org.openide.util.ContextAwareAction;
50
import org.openide.util.Exceptions;
53
import org.openide.util.Exceptions;
51
54
52
55
53
/** Redo an edit.
56
/** Redo an edit. Since version 6.15 this class
57
* implements {@link ContextAwareAction}.
54
*
58
*
55
* @see UndoAction
59
* @see UndoAction
56
* @author   Ian Formanek, Jaroslav Tulach
60
* @author   Ian Formanek, Jaroslav Tulach
57
*/
61
*/
58
public class RedoAction extends CallableSystemAction {
62
public class RedoAction extends CallableSystemAction implements ContextAwareAction {
59
    private static String SWING_DEFAULT_LABEL = UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
63
    private static String SWING_DEFAULT_LABEL = UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
60
64
61
    @Override
65
    @Override
Lines 109-112 Link Here
109
    protected boolean asynchronous() {
113
    protected boolean asynchronous() {
110
        return false;
114
        return false;
111
    }
115
    }
116
117
    @Override
118
    public Action createContextAwareInstance(Lookup actionContext) {
119
        return new UndoRedoAction(actionContext, false, false);
120
    }
112
}
121
}
(-)a/openide.actions/src/org/openide/actions/UndoAction.java (-2 / +12 lines)
Lines 40-47 Link Here
40
 */
40
 */
41
package org.openide.actions;
41
package org.openide.actions;
42
42
43
import javax.swing.Action;
43
import org.openide.awt.UndoRedo;
44
import org.openide.awt.UndoRedo;
44
import org.openide.util.HelpCtx;
45
import org.openide.util.HelpCtx;
46
import org.openide.util.Lookup;
45
import org.openide.util.NbBundle;
47
import org.openide.util.NbBundle;
46
import org.openide.util.actions.CallableSystemAction;
48
import org.openide.util.actions.CallableSystemAction;
47
import org.openide.windows.TopComponent;
49
import org.openide.windows.TopComponent;
Lines 56-70 Link Here
56
import javax.swing.UIManager;
58
import javax.swing.UIManager;
57
import javax.swing.event.*;
59
import javax.swing.event.*;
58
import javax.swing.undo.*;
60
import javax.swing.undo.*;
61
import org.openide.util.ContextAwareAction;
59
import org.openide.util.Exceptions;
62
import org.openide.util.Exceptions;
60
63
61
64
62
/** Undo an edit.
65
/** Undo an edit. Since version 6.15 this class
66
* implements {@link ContextAwareAction}.
63
*
67
*
64
* @see UndoRedo
68
* @see UndoRedo
65
* @author   Ian Formanek, Jaroslav Tulach
69
* @author   Ian Formanek, Jaroslav Tulach
66
*/
70
*/
67
public class UndoAction extends CallableSystemAction {
71
public class UndoAction extends CallableSystemAction
72
implements ContextAwareAction {
68
    /** initialized listener */
73
    /** initialized listener */
69
    private static Listener listener;
74
    private static Listener listener;
70
75
Lines 188-193 Link Here
188
        return false;
193
        return false;
189
    }
194
    }
190
195
196
    @Override
197
    public Action createContextAwareInstance(Lookup actionContext) {
198
        return new UndoRedoAction(actionContext, true, false);
199
    }
200
191
    /** Listener on changes of selected workspace element and
201
    /** Listener on changes of selected workspace element and
192
    * its changes.
202
    * its changes.
193
    */
203
    */
(-)1db5ce9ba37d (+255 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.openide.actions;
42
43
import java.awt.EventQueue;
44
import java.awt.event.ActionEvent;
45
import javax.swing.Action;
46
import org.openide.awt.UndoRedo;
47
import org.openide.util.HelpCtx;
48
import org.openide.util.LookupEvent;
49
import org.openide.util.NbBundle;
50
import org.openide.windows.TopComponent;
51
import org.openide.windows.TopComponent.Registry;
52
import org.openide.windows.WindowManager;
53
54
import java.beans.*;
55
import java.util.Map;
56
import java.util.logging.Logger;
57
import java.util.logging.Level;
58
import javax.swing.AbstractAction;
59
60
import javax.swing.UIManager;
61
import javax.swing.event.*;
62
import javax.swing.undo.*;
63
import org.openide.util.ContextAwareAction;
64
import org.openide.util.Exceptions;
65
import org.openide.util.ImageUtilities;
66
import org.openide.util.Lookup;
67
import org.openide.util.LookupListener;
68
import org.openide.util.Utilities;
69
import org.openide.util.WeakListeners;
70
71
72
/** Context aware undo and redo actions.
73
*
74
* @author   Jaroslav Tulach
75
*/
76
final class UndoRedoAction extends AbstractAction
77
implements ContextAwareAction, PropertyChangeListener, ChangeListener, LookupListener, Runnable, HelpCtx.Provider {
78
    private static final Logger LOG = Logger.getLogger(UndoRedoAction.class.getName());
79
    /** last edit */
80
    private UndoRedo last = UndoRedo.NONE;
81
    private final boolean doUndo;
82
    private final Lookup.Result<UndoRedo.Provider> result;
83
    private final boolean fallback;
84
    private PropertyChangeListener weakPCL;
85
    private ChangeListener weakCL;
86
    private LookupListener weakLL;
87
88
89
    UndoRedoAction(Lookup context, boolean doUndo, boolean fallback) {
90
        this.doUndo = doUndo;
91
        this.fallback = fallback;
92
        this.result = context.lookupResult(UndoRedo.Provider.class);
93
    }
94
95
    public static Action create(Map<?,?> map) {
96
        if (Boolean.TRUE.equals(map.get("redo"))) { // NOI18N
97
            return new UndoRedoAction(Utilities.actionsGlobalContext(), false, true);
98
        }
99
        if (Boolean.TRUE.equals(map.get("undo"))) { // NOI18N
100
            return new UndoRedoAction(Utilities.actionsGlobalContext(), true, true);
101
        }
102
        throw new IllegalStateException();
103
    }
104
105
106
    @Override
107
    public boolean isEnabled() {
108
        initializeUndoRedo();
109
        return super.isEnabled();
110
    }
111
112
    void initializeUndoRedo() {
113
        assert EventQueue.isDispatchThread();
114
        if (weakLL != null) {
115
            return;
116
        }
117
        String res;
118
        if (doUndo) {
119
            res = "org/openide/resources/actions/undo.gif"; // NOI18N
120
        } else {
121
            res = "org/openide/resources/actions/redo.gif"; // NOI18N
122
        }
123
        putValue("iconBase", res); // NOI18N
124
        putValue(SMALL_ICON, ImageUtilities.loadImageIcon(res, true));
125
        if (fallback) {
126
            Registry r = WindowManager.getDefault().getRegistry();
127
            weakPCL = WeakListeners.propertyChange(this, r);
128
            r.addPropertyChangeListener(weakPCL);
129
        }
130
        weakCL = WeakListeners.change(this, null);
131
        weakLL = WeakListeners.create(LookupListener.class, this, result);
132
        result.addLookupListener(weakLL);
133
        last = UndoRedo.NONE;
134
135
        run();
136
    }
137
    
138
    @Override
139
    public void run() {
140
        if (!EventQueue.isDispatchThread()) {
141
            EventQueue.invokeLater(this);
142
            return;
143
        }
144
145
        UndoRedo ur = getUndoRedo();
146
        last.removeChangeListener(weakCL);
147
148
        if (doUndo) {
149
            setEnabled(ur.canUndo());
150
        } else {
151
            setEnabled(ur.canRedo());
152
        }
153
        putValue(NAME, getName());
154
        
155
        last = ur;
156
        last.addChangeListener(weakCL);
157
    }
158
159
    private UndoRedo getUndoRedo() {
160
        assert EventQueue.isDispatchThread();
161
        for (UndoRedo.Provider provider : result.allInstances()) {
162
            UndoRedo ur = provider.getUndoRedo();
163
            if (ur != null) {
164
                return ur;
165
            }
166
        }
167
168
        if (fallback) {
169
            TopComponent el = WindowManager.getDefault().getRegistry().getActivated();
170
            if (el != null) {
171
                UndoRedo ur = el.getUndoRedo();
172
                if (ur != null) {
173
                    return ur;
174
                }
175
            }
176
        }
177
        return UndoRedo.NONE;
178
    }
179
180
    private String getName() {
181
        assert EventQueue.isDispatchThread();
182
        //#40823 related. AbstractUndoableEdit prepends "Undo/Redo" strings before the custom text,
183
        // resulting in repetitive text in UndoAction/RedoAction. attempt to remove the AbstractUndoableEdit text
184
        // keeping our text because it has mnemonics.
185
        String undo = getUndoRedo().getUndoPresentationName();
186
        LOG.log (Level.FINE, "getUndoRedo().getUndoPresentationName() returns {0}", undo);
187
188
        if ((undo != null) && (getDefaultSwingText() != null) && undo.startsWith(getDefaultSwingText())) {
189
            undo = undo.substring(getDefaultSwingText().length()).trim();
190
        }
191
        
192
        LOG.log (Level.FINE, "Name adapted by SWING_DEFAULT_LABEL is {0}", undo);
193
        String presentationName = null;
194
        if (undo == null || undo.trim ().length () == 0) {
195
            presentationName = NbBundle.getMessage(UndoRedoAction.class, doUndo ? "UndoSimple" : "RedoSimple");
196
        } else {
197
            presentationName = NbBundle.getMessage(UndoRedoAction.class, doUndo ? "UndoWithParameter" : "UndoSimple", undo);
198
        }
199
        
200
        LOG.log (Level.FINE, "Result name is {0}", presentationName);
201
202
        return presentationName;
203
    }
204
205
    @Override
206
    public HelpCtx getHelpCtx() {
207
        return new HelpCtx(UndoRedoAction.class);
208
    }
209
210
    @Override
211
    public void actionPerformed(ActionEvent ev) {
212
        UndoRedo undoRedo = getUndoRedo();
213
        if (doUndo) try {
214
            if (undoRedo.canUndo()) {
215
                undoRedo.undo();
216
            }
217
        } catch (CannotUndoException ex) {
218
            Exceptions.printStackTrace(ex);
219
        } else try {
220
            if (undoRedo.canRedo()) {
221
                undoRedo.redo();
222
            }
223
        } catch (CannotRedoException ex) {
224
            Exceptions.printStackTrace(ex);
225
        }
226
        run();
227
    }
228
229
    @Override
230
    public void propertyChange(PropertyChangeEvent ev) {
231
        if (TopComponent.Registry.PROP_ACTIVATED.equals(ev.getPropertyName())) {
232
            run();
233
        }
234
    }
235
236
    @Override
237
    public void stateChanged(ChangeEvent ev) {
238
        run();
239
    }
240
241
    @Override
242
    public void resultChanged(LookupEvent ev) {
243
        run();
244
    }
245
246
    @Override
247
    public Action createContextAwareInstance(Lookup actionContext) {
248
        return new UndoRedoAction(actionContext, doUndo, false);
249
    }
250
251
    private String getDefaultSwingText() {
252
        return doUndo ? UIManager.getString("AbstractUndoableEdit.undoText") : //NOI18N
253
            UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
254
    }
255
}
(-)1db5ce9ba37d (+224 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.openide.actions;
41
42
import java.awt.event.ActionEvent;
43
import java.beans.PropertyChangeEvent;
44
import java.beans.PropertyChangeListener;
45
import javax.swing.Action;
46
import javax.swing.event.UndoableEditEvent;
47
import javax.swing.undo.CannotRedoException;
48
import javax.swing.undo.CannotUndoException;
49
import javax.swing.undo.UndoableEdit;
50
import org.netbeans.junit.NbTestCase;
51
import org.openide.awt.UndoRedo;
52
import org.openide.util.ContextAwareAction;
53
import org.openide.util.Lookup;
54
import org.openide.util.lookup.AbstractLookup;
55
import org.openide.util.lookup.InstanceContent;
56
57
/**
58
 *
59
 * @author Jaroslav Tulach <jtulach@netbeans.org>
60
 */
61
public class UndoRedoActionTest extends NbTestCase
62
implements UndoRedo.Provider {
63
    private UndoRedo.Manager ur;
64
    private MyEdit me;
65
66
    public UndoRedoActionTest(String n) {
67
        super(n);
68
    }
69
70
    @Override
71
    protected boolean runInEQ() {
72
        return true;
73
    }
74
75
    private Action undoAction(Lookup lkp) {
76
        UndoAction u = UndoAction.get(UndoAction.class);
77
        assertTrue("instance: " + u, u instanceof ContextAwareAction);
78
        return ((ContextAwareAction) u).createContextAwareInstance(lkp);
79
    }
80
81
    private Action redoAction(Lookup lkp) {
82
        RedoAction r = RedoAction.get(RedoAction.class);
83
        assertTrue("instance: " + r, r instanceof ContextAwareAction);
84
        return ((ContextAwareAction) r).createContextAwareInstance(lkp);
85
    }
86
87
    public void testUndoDeliversChanges() {
88
        doUndoRedoTest(new UndoRedo.Manager(), true);
89
    }
90
    
91
    public void testUndoDeliversChangesWithTooManyEdits() {
92
        UndoRedo.Manager man = new UndoRedo.Manager() {
93
            @Override
94
            public boolean canUndo() {
95
                if (super.canUndo()) {
96
                    undoableEditHappened(new UndoableEditEvent(UndoRedoActionTest.this, new MyEdit(true)));
97
                }
98
                return super.canUndo();
99
            }
100
        };
101
        doUndoRedoTest(man, false);
102
    }
103
104
105
    private void doUndoRedoTest(UndoRedo.Manager man, boolean testCounts) {
106
        me = new MyEdit();
107
        man.undoableEditHappened(new UndoableEditEvent(this, me));
108
        assertTrue("Can undo", man.canUndo());
109
        this.ur = man;
110
        
111
        InstanceContent ic = new InstanceContent();
112
        AbstractLookup lkp = new AbstractLookup(ic);
113
        Action u = undoAction(lkp);
114
        Action r = redoAction(lkp);
115
116
        assertFalse("Not enabled", u.isEnabled());
117
        assertFalse("Not enabledR", r.isEnabled());
118
        MyEdit lu = new MyEdit();
119
        MyEdit lr = new MyEdit();
120
        u.addPropertyChangeListener(lu);
121
        r.addPropertyChangeListener(lr);
122
123
        ic.add(this);
124
125
        assertTrue("Action is enabled", u.isEnabled());
126
        assertEquals("One change", 1, lu.cnt);
127
        assertEquals("No redo change", 0, lr.cnt);
128
129
        u.actionPerformed(new ActionEvent(this, 0, ""));
130
        if (testCounts) {
131
            assertEquals("my edit undone", 1, me.undo);
132
133
            assertFalse("No more undo", man.canUndo());
134
            assertTrue("But redo", man.canRedo());
135
            assertEquals("Another undo change", 2, lu.cnt);
136
            assertEquals("New redo change", 1, lr.cnt);
137
            assertTrue("Redo action enabled", r.isEnabled());
138
        }
139
140
        r.actionPerformed(new ActionEvent(this, 0, ""));
141
        assertFalse("Redo action no longer enabled", r.isEnabled());
142
    }
143
144
    @Override
145
    public UndoRedo getUndoRedo() {
146
        return ur;
147
    }
148
149
    private static final class MyEdit implements UndoableEdit, PropertyChangeListener {
150
        private int undo;
151
        private int redo;
152
        private int cnt;
153
        private boolean ignore;
154
155
        public MyEdit() {
156
            this(false);
157
        }
158
159
        public MyEdit(boolean ignore) {
160
            this.ignore = ignore;
161
        }
162
163
        @Override
164
        public void propertyChange(PropertyChangeEvent evt) {
165
            if ("enabled".equals(evt.getPropertyName())) {
166
                cnt++;
167
            }
168
        }
169
170
        @Override
171
        public void undo() throws CannotUndoException {
172
            undo++;
173
        }
174
175
        @Override
176
        public boolean canUndo() {
177
            return true;
178
        }
179
180
        @Override
181
        public void redo() throws CannotRedoException {
182
            redo++;
183
        }
184
185
        @Override
186
        public boolean canRedo() {
187
            return true;
188
        }
189
190
        @Override
191
        public void die() {
192
        }
193
194
        @Override
195
        public boolean addEdit(UndoableEdit anEdit) {
196
            return false;
197
        }
198
199
        @Override
200
        public boolean replaceEdit(UndoableEdit anEdit) {
201
            return false;
202
        }
203
204
        @Override
205
        public boolean isSignificant() {
206
            return true;
207
        }
208
209
        @Override
210
        public String getPresentationName() {
211
            return "My Edit";
212
        }
213
214
        @Override
215
        public String getUndoPresentationName() {
216
            return "My Undo";
217
        }
218
219
        @Override
220
        public String getRedoPresentationName() {
221
            return "My Redo";
222
        }
223
    }
224
}
(-)a/openide.awt/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.openide.awt
2
OpenIDE-Module: org.openide.awt
3
OpenIDE-Module-Localizing-Bundle: org/openide/awt/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/awt/Bundle.properties
4
AutoUpdate-Essential-Module: true
4
AutoUpdate-Essential-Module: true
5
OpenIDE-Module-Specification-Version: 7.21
5
OpenIDE-Module-Specification-Version: 7.22
6
6
(-)a/openide.awt/src/org/openide/awt/UndoRedo.java (-45 / +56 lines)
Lines 40-51 Link Here
40
 */
40
 */
41
package org.openide.awt;
41
package org.openide.awt;
42
42
43
import org.openide.util.Task;
44
import java.util.LinkedList;
43
import java.util.LinkedList;
45
44
46
import javax.swing.event.*;
45
import javax.swing.event.*;
47
import javax.swing.undo.*;
46
import javax.swing.undo.*;
48
import org.openide.util.ChangeSupport;
47
import org.openide.util.ChangeSupport;
48
import org.openide.util.Lookup;
49
import org.openide.util.Utilities;
49
50
50
51
51
/** Undo and Redo manager for top components and workspace elements.
52
/** Undo and Redo manager for top components and workspace elements.
Lines 113-118 Link Here
113
    */
114
    */
114
    public String getRedoPresentationName();
115
    public String getRedoPresentationName();
115
116
117
    /** Components that provide {@link UndoRedo} shall announce that by
118
     * implementing this provider interface. Both Edit/Undo and Edit/Redo actions
119
     * seek this interface inside current selection (e.g. {@link Utilities#actionsGlobalContext()}).
120
     * To control these actions make sure your implementation of this interface
121
     * is exposed in instance representing {@link Lookup current context}.
122
     *
123
     * @since 7.21
124
     */
125
    public static interface Provider {
126
        public UndoRedo getUndoRedo();
127
    }
128
116
    /** An undo manager which fires a change event each time it consumes a new undoable edit.
129
    /** An undo manager which fires a change event each time it consumes a new undoable edit.
117
    */
130
    */
118
    public static class Manager extends UndoManager implements UndoRedo {
131
    public static class Manager extends UndoManager implements UndoRedo {
Lines 121-130 Link Here
121
        private final ChangeSupport cs = new ChangeSupport(this);
134
        private final ChangeSupport cs = new ChangeSupport(this);
122
135
123
        /** vector of Edits to run */
136
        /** vector of Edits to run */
124
        private LinkedList<UndoableEditEvent> runus = new LinkedList<UndoableEditEvent>(); // for fix of #8692
137
        private final LinkedList<UndoableEditEvent> runus = new LinkedList<UndoableEditEvent>(); // for fix of #8692
125
126
        /** task that clears the queue */
127
        private Task task = Task.EMPTY; // for fix of #8692
128
138
129
        /** Called from undoableEditHappened() inner class */
139
        /** Called from undoableEditHappened() inner class */
130
        private void superUndoableEditHappened(UndoableEditEvent ue) {
140
        private void superUndoableEditHappened(UndoableEditEvent ue) {
Lines 140-145 Link Here
140
        * Delegates to superclass and notifies listeners.
150
        * Delegates to superclass and notifies listeners.
141
        * @param ue the edit
151
        * @param ue the edit
142
        */
152
        */
153
        @Override
143
        public void undoableEditHappened(final UndoableEditEvent ue) {
154
        public void undoableEditHappened(final UndoableEditEvent ue) {
144
            /* Edits are posted to request processor and the deadlock
155
            /* Edits are posted to request processor and the deadlock
145
             * in #8692 between undoredo and document that fires
156
             * in #8692 between undoredo and document that fires
Lines 153-158 Link Here
153
        }
164
        }
154
165
155
        /** Discard all the existing edits from the undomanager. */
166
        /** Discard all the existing edits from the undomanager. */
167
        @Override
156
        public void discardAllEdits() {
168
        public void discardAllEdits() {
157
            synchronized (runus) {
169
            synchronized (runus) {
158
                runus.add(null);
170
                runus.add(null);
Lines 161-216 Link Here
161
            updateTask();
173
            updateTask();
162
        }
174
        }
163
175
164
        public boolean canUndo() {
176
        @Override
165
            /* First it must be checked that there are
177
        public void undo() throws CannotUndoException {
166
             * undoable edits waiting to be added to undoredo.
178
            super.undo();
167
             */
179
            updateTask();
168
            boolean empty;
180
        }
169
181
170
            synchronized (runus) {
182
        @Override
171
                empty = runus.isEmpty();
183
        public void redo() throws CannotRedoException {
172
            }
184
            super.redo();
185
            updateTask();
186
        }
173
187
174
            if (!empty) {
188
        @Override
175
                task.waitFinished();
189
        public void undoOrRedo() throws CannotRedoException, CannotUndoException {
176
            }
190
            super.undoOrRedo();
177
191
            updateTask();
178
            return super.canUndo();
179
        }
192
        }
180
193
181
        private void updateTask() {
194
        private void updateTask() {
182
            /* The following task is finished when there are no
195
            for (;;) {
183
             * undoable edits waiting to be added to undoredo.
196
                UndoableEditEvent ue;
184
             */
185
            class R implements Runnable {
186
                public void run() {
187
                    for (;;) {
188
                        UndoableEditEvent ue;
189
197
190
                        synchronized (runus) {
198
                synchronized (runus) {
191
                            if (runus.isEmpty()) {
199
                    if (runus.isEmpty()) {
192
                                break;
200
                        break;
193
                            }
201
                    }
194
202
195
                            ue = runus.removeFirst();
203
                    ue = runus.removeFirst();
196
                        }
204
                }
197
205
198
                        if (ue == null) {
206
                if (ue == null) {
199
                            superDiscardAllEdits();
207
                    superDiscardAllEdits();
200
                        } else {
208
                } else {
201
                            superUndoableEditHappened(ue);
209
                    superUndoableEditHappened(ue);
202
                        }
203
204
                        cs.fireChange();
205
                    }
206
                }
210
                }
207
            }
211
            }
208
212
            cs.fireChange();
209
            R r = new R();
210
            r.run();
211
212
            //Use internal not default RequestProcessor to solve deadlock #10826
213
            //task = internalRequestProcessor.post (r, 0, Thread.MAX_PRIORITY);
214
        }
213
        }
215
214
216
        /* Attaches change listener to the this object.
215
        /* Attaches change listener to the this object.
Lines 219-238 Link Here
219
        */
218
        */
220
219
221
        //#32313 - synchronization of this method was removed
220
        //#32313 - synchronization of this method was removed
221
        @Override
222
        public void addChangeListener(ChangeListener l) {
222
        public void addChangeListener(ChangeListener l) {
223
            cs.addChangeListener(l);
223
            cs.addChangeListener(l);
224
        }
224
        }
225
225
226
        /* Removes the listener
226
        /* Removes the listener
227
        */
227
        */
228
        @Override
228
        public void removeChangeListener(ChangeListener l) {
229
        public void removeChangeListener(ChangeListener l) {
229
            cs.removeChangeListener(l);
230
            cs.removeChangeListener(l);
230
        }
231
        }
231
232
233
        @Override
232
        public String getUndoPresentationName() {
234
        public String getUndoPresentationName() {
233
            return this.canUndo() ? super.getUndoPresentationName() : ""; // NOI18N
235
            return this.canUndo() ? super.getUndoPresentationName() : ""; // NOI18N
234
        }
236
        }
235
237
238
        @Override
236
        public String getRedoPresentationName() {
239
        public String getRedoPresentationName() {
237
            return this.canRedo() ? super.getRedoPresentationName() : ""; // NOI18N
240
            return this.canRedo() ? super.getRedoPresentationName() : ""; // NOI18N
238
        }
241
        }
Lines 245-276 Link Here
245
    */
248
    */
246
    @Deprecated
249
    @Deprecated
247
    public static final class Empty extends Object implements UndoRedo {
250
    public static final class Empty extends Object implements UndoRedo {
251
        @Override
248
        public boolean canUndo() {
252
        public boolean canUndo() {
249
            return false;
253
            return false;
250
        }
254
        }
251
255
256
        @Override
252
        public boolean canRedo() {
257
        public boolean canRedo() {
253
            return false;
258
            return false;
254
        }
259
        }
255
260
261
        @Override
256
        public void undo() throws CannotUndoException {
262
        public void undo() throws CannotUndoException {
257
            throw new CannotUndoException();
263
            throw new CannotUndoException();
258
        }
264
        }
259
265
266
        @Override
260
        public void redo() throws CannotRedoException {
267
        public void redo() throws CannotRedoException {
261
            throw new CannotRedoException();
268
            throw new CannotRedoException();
262
        }
269
        }
263
270
271
        @Override
264
        public void addChangeListener(ChangeListener l) {
272
        public void addChangeListener(ChangeListener l) {
265
        }
273
        }
266
274
275
        @Override
267
        public void removeChangeListener(ChangeListener l) {
276
        public void removeChangeListener(ChangeListener l) {
268
        }
277
        }
269
278
279
        @Override
270
        public String getUndoPresentationName() {
280
        public String getUndoPresentationName() {
271
            return ""; // NOI18N
281
            return ""; // NOI18N
272
        }
282
        }
273
283
284
        @Override
274
        public String getRedoPresentationName() {
285
        public String getRedoPresentationName() {
275
            return ""; // NOI18N
286
            return ""; // NOI18N
276
        }
287
        }
(-)1db5ce9ba37d (+183 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.openide.awt;
41
42
import javax.swing.undo.CannotRedoException;
43
import javax.swing.undo.CannotUndoException;
44
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeListener;
46
import javax.swing.undo.UndoableEdit;
47
import javax.swing.event.ChangeEvent;
48
import javax.swing.event.ChangeListener;
49
import javax.swing.event.UndoableEditEvent;
50
import org.netbeans.junit.NbTestCase;
51
import static org.junit.Assert.*;
52
53
/**
54
 *
55
 * @author Jaroslav Tulach <jtulach@netbeans.org>
56
 */
57
public class UndoRedoTest extends NbTestCase implements ChangeListener {
58
    private int cnt;
59
60
    public UndoRedoTest(String n) {
61
        super(n);
62
    }
63
64
    public void testUndoDeliversChanges() {
65
        UndoRedo.Manager ur = new UndoRedo.Manager();
66
        doUndoRedoTest(ur);
67
    }
68
69
    public void testUndoDeliversChangesWithTooManyEdits() {
70
        UndoRedo.Manager ur = new UndoRedo.Manager() {
71
            @Override
72
            public boolean canUndo() {
73
                if (super.canUndo()) {
74
                    undoableEditHappened(new UndoableEditEvent(this, new MyEdit(true)));
75
                }
76
                return super.canUndo();
77
            }
78
        };
79
        doUndoRedoTest(ur);
80
    }
81
82
    private void doUndoRedoTest(UndoRedo.Manager ur) {
83
        assertFalse("Nothing to undo", ur.canUndo());
84
        ur.addChangeListener(this);
85
        MyEdit me = new MyEdit();
86
        ur.undoableEditHappened(new UndoableEditEvent(this, me));
87
        assertEquals("One change", 1, cnt);
88
        assertTrue("Can undo now", ur.canUndo());
89
        ur.undo();
90
        assertFalse("Cannot undo", ur.canUndo());
91
        assertEquals("Snd change", 2, cnt);
92
93
        assertTrue("But redo", ur.canRedo());
94
        ur.redo();
95
        assertEquals("Third change", 3, cnt);
96
        assertEquals("One undo", 1, me.undo);
97
        assertEquals("One redo", 1, me.redo);
98
    }
99
100
    @Override
101
    public void stateChanged(ChangeEvent e) {
102
        cnt++;
103
    }
104
    private static final class MyEdit implements UndoableEdit, PropertyChangeListener {
105
        private int undo;
106
        private int redo;
107
        private int cnt;
108
        private boolean ignore;
109
110
        public MyEdit() {
111
            this(false);
112
        }
113
114
        public MyEdit(boolean ignore) {
115
            this.ignore = ignore;
116
        }
117
118
        @Override
119
        public void propertyChange(PropertyChangeEvent evt) {
120
            if ("enabled".equals(evt.getPropertyName())) {
121
                cnt++;
122
            }
123
        }
124
125
        @Override
126
        public void undo() throws CannotUndoException {
127
            undo++;
128
        }
129
130
        @Override
131
        public boolean canUndo() {
132
            return true;
133
        }
134
135
        @Override
136
        public void redo() throws CannotRedoException {
137
            redo++;
138
        }
139
140
        @Override
141
        public boolean canRedo() {
142
            return true;
143
        }
144
145
        @Override
146
        public void die() {
147
        }
148
149
        @Override
150
        public boolean addEdit(UndoableEdit anEdit) {
151
            if (anEdit instanceof MyEdit && ((MyEdit)anEdit).ignore) {
152
                return true;
153
            }
154
            return false;
155
        }
156
157
        @Override
158
        public boolean replaceEdit(UndoableEdit anEdit) {
159
            return false;
160
        }
161
162
        @Override
163
        public boolean isSignificant() {
164
            return true;
165
        }
166
167
        @Override
168
        public String getPresentationName() {
169
            return "My Edit";
170
        }
171
172
        @Override
173
        public String getUndoPresentationName() {
174
            return "My Undo";
175
        }
176
177
        @Override
178
        public String getRedoPresentationName() {
179
            return "My Redo";
180
        }
181
    }
182
183
}
(-)a/openide.text/src/org/openide/text/CloneableEditorSupport.java (-1 / +2 lines)
Lines 120-126 Link Here
120
*
120
*
121
* @author Jaroslav Tulach
121
* @author Jaroslav Tulach
122
*/
122
*/
123
public abstract class CloneableEditorSupport extends CloneableOpenSupport {
123
public abstract class CloneableEditorSupport extends CloneableOpenSupport
124
implements UndoRedo.Provider {
124
    private static final RequestProcessor RP = new RequestProcessor("org.openide.text Document Processing");
125
    private static final RequestProcessor RP = new RequestProcessor("org.openide.text Document Processing");
125
    
126
    
126
    /** Common name for editor mode. */
127
    /** Common name for editor mode. */
(-)a/openide.windows/src/org/openide/windows/TopComponent.java (-1 / +1 lines)
Lines 112-118 Link Here
112
 *
112
 *
113
 * @author Jaroslav Tulach, Petr Hamernik, Jan Jancura
113
 * @author Jaroslav Tulach, Petr Hamernik, Jan Jancura
114
 */
114
 */
115
public class TopComponent extends JComponent implements Externalizable, Accessible, HelpCtx.Provider, Lookup.Provider {
115
public class TopComponent extends JComponent implements Externalizable, Accessible, HelpCtx.Provider, Lookup.Provider, UndoRedo.Provider {
116
    /** UI logger to notify about invocation of an action */
116
    /** UI logger to notify about invocation of an action */
117
    private static Logger UILOG = Logger.getLogger("org.netbeans.ui.actions"); // NOI18N
117
    private static Logger UILOG = Logger.getLogger("org.netbeans.ui.actions"); // NOI18N
118
    /** generated Serialized Version UID */
118
    /** generated Serialized Version UID */

Return to bug 180614