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.ide/nbproject/project.xml (+8 lines)
Lines 53-58 Link Here
53
                    </run-dependency>
53
                    </run-dependency>
54
                </dependency>
54
                </dependency>
55
                <dependency>
55
                <dependency>
56
                    <code-name-base>org.openide.awt</code-name-base>
57
                    <build-prerequisite/>
58
                    <compile-dependency/>
59
                    <run-dependency>
60
                        <specification-version>7.22</specification-version>
61
                    </run-dependency>
62
                </dependency>
63
                <dependency>
56
                    <code-name-base>org.openide.explorer</code-name-base>
64
                    <code-name-base>org.openide.explorer</code-name-base>
57
                    <build-prerequisite/>
65
                    <build-prerequisite/>
58
                    <compile-dependency/>
66
                    <compile-dependency/>
(-)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.15
5
OpenIDE-Module-Specification-Version: 6.16
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.16 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.16 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
    */
(-)e97507293f86 (+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
}
(-)e97507293f86 (+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
        }
(-)e97507293f86 (+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/manifest.mf (-1 / +1 lines)
Lines 1-7 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.text
2
OpenIDE-Module: org.openide.text
3
OpenIDE-Module-Install: org/netbeans/modules/openide/text/Installer.class
3
OpenIDE-Module-Install: org/netbeans/modules/openide/text/Installer.class
4
OpenIDE-Module-Specification-Version: 6.29
4
OpenIDE-Module-Specification-Version: 6.30
5
OpenIDE-Module-Localizing-Bundle: org/openide/text/Bundle.properties
5
OpenIDE-Module-Localizing-Bundle: org/openide/text/Bundle.properties
6
AutoUpdate-Essential-Module: true
6
AutoUpdate-Essential-Module: true
7
7
(-)a/openide.text/src/org/openide/text/CloneableEditorSupport.java (-3 / +8 lines)
Lines 117-126 Link Here
117
* but does not implement
117
* but does not implement
118
* those interfaces. It is up to the subclass to decide which interfaces
118
* those interfaces. It is up to the subclass to decide which interfaces
119
* really implement and which not.
119
* really implement and which not.
120
 * <p>
121
 * Since 6.30 implements {@link UndoRedo#Provider}.
120
*
122
*
121
* @author Jaroslav Tulach
123
* @author Jaroslav Tulach
122
*/
124
*/
123
public abstract class CloneableEditorSupport extends CloneableOpenSupport {
125
public abstract class CloneableEditorSupport extends CloneableOpenSupport
126
implements UndoRedo.Provider {
124
    private static final RequestProcessor RP = new RequestProcessor("org.openide.text Document Processing");
127
    private static final RequestProcessor RP = new RequestProcessor("org.openide.text Document Processing");
125
    
128
    
126
    /** Common name for editor mode. */
129
    /** Common name for editor mode. */
Lines 340-349 Link Here
340
    }
343
    }
341
344
342
    /**
345
    /**
343
     * Gets the undo redo manager.
346
     * Gets the undo redo manager. Made public since 6.30 as the class implements
347
     * {@link UndoRedo#Provider}.
344
     * @return the manager
348
     * @return the manager
345
     */
349
     */
346
    protected final synchronized UndoRedo.Manager getUndoRedo() {
350
    @Override
351
    public final synchronized UndoRedo.Manager getUndoRedo() {
347
        CloneableEditorSupport redirect = CloneableEditorSupportRedirector.findRedirect(this);
352
        CloneableEditorSupport redirect = CloneableEditorSupportRedirector.findRedirect(this);
348
        if (redirect != null) {
353
        if (redirect != null) {
349
            return redirect.getUndoRedo();
354
            return redirect.getUndoRedo();
(-)a/openide.windows/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.windows
2
OpenIDE-Module: org.openide.windows
3
OpenIDE-Module-Specification-Version: 6.32
3
OpenIDE-Module-Specification-Version: 6.33
4
OpenIDE-Module-Localizing-Bundle: org/openide/windows/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/openide/windows/Bundle.properties
5
AutoUpdate-Essential-Module: true
5
AutoUpdate-Essential-Module: true
6
6
(-)e97507293f86 (+61 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
44
<!DOCTYPE transformations PUBLIC "-//NetBeans//DTD Module Automatic Dependencies 1.0//EN" "http://www.netbeans.org/dtds/module-auto-deps-1_0.dtd">
45
46
<transformations version="1.0">
47
    <transformationgroup>
48
        <description>#180614: TopComponent implements UndoRedo.Provider</description>
49
        <transformation>
50
            <trigger-dependency type="older">
51
                <module-dependency codenamebase="org.openide.windows" spec="6.33"/>
52
            </trigger-dependency>
53
            <implies>
54
                <result>
55
                    <module-dependency codenamebase="org.openide.awt"  spec="7.22"/>
56
                </result>
57
            </implies>
58
        </transformation>
59
    </transformationgroup>
60
61
</transformations>
(-)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 */
(-)a/parsing.api/nbproject/project.xml (+8 lines)
Lines 141-146 Link Here
141
                    </run-dependency>
141
                    </run-dependency>
142
                </dependency>
142
                </dependency>
143
                <dependency>
143
                <dependency>
144
                    <code-name-base>org.openide.awt</code-name-base>
145
                    <build-prerequisite/>
146
                    <compile-dependency/>
147
                    <run-dependency>
148
                        <specification-version>7.22</specification-version>
149
                    </run-dependency>
150
                </dependency>
151
                <dependency>
144
                    <code-name-base>org.openide.filesystems</code-name-base>
152
                    <code-name-base>org.openide.filesystems</code-name-base>
145
                    <build-prerequisite/>
153
                    <build-prerequisite/>
146
                    <compile-dependency/>
154
                    <compile-dependency/>

Return to bug 180614