diff -r 1db5ce9ba37d core.ui/src/org/netbeans/core/ui/resources/layer.xml
--- a/core.ui/src/org/netbeans/core/ui/resources/layer.xml Thu Feb 18 12:56:39 2010 +0100
+++ b/core.ui/src/org/netbeans/core/ui/resources/layer.xml Thu Feb 18 19:22:19 2010 +0100
@@ -84,13 +84,19 @@
-
+
+
+
+
-
+
+
+
+
diff -r 1db5ce9ba37d openide.actions/manifest.mf
--- a/openide.actions/manifest.mf Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.actions/manifest.mf Thu Feb 18 19:22:19 2010 +0100
@@ -2,5 +2,5 @@
OpenIDE-Module: org.openide.actions
OpenIDE-Module-Localizing-Bundle: org/openide/actions/Bundle.properties
AutoUpdate-Essential-Module: true
-OpenIDE-Module-Specification-Version: 6.14
+OpenIDE-Module-Specification-Version: 6.15
diff -r 1db5ce9ba37d openide.actions/src/org/openide/actions/RedoAction.java
--- a/openide.actions/src/org/openide/actions/RedoAction.java Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.actions/src/org/openide/actions/RedoAction.java Thu Feb 18 19:22:19 2010 +0100
@@ -40,22 +40,26 @@
*/
package org.openide.actions;
+import javax.swing.Action;
import org.openide.awt.UndoRedo;
import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import javax.swing.UIManager;
import javax.swing.undo.CannotRedoException;
+import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
-/** Redo an edit.
+/** Redo an edit. Since version 6.15 this class
+* implements {@link ContextAwareAction}.
*
* @see UndoAction
* @author Ian Formanek, Jaroslav Tulach
*/
-public class RedoAction extends CallableSystemAction {
+public class RedoAction extends CallableSystemAction implements ContextAwareAction {
private static String SWING_DEFAULT_LABEL = UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
@Override
@@ -109,4 +113,9 @@
protected boolean asynchronous() {
return false;
}
+
+ @Override
+ public Action createContextAwareInstance(Lookup actionContext) {
+ return new UndoRedoAction(actionContext, false, false);
+ }
}
diff -r 1db5ce9ba37d openide.actions/src/org/openide/actions/UndoAction.java
--- a/openide.actions/src/org/openide/actions/UndoAction.java Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.actions/src/org/openide/actions/UndoAction.java Thu Feb 18 19:22:19 2010 +0100
@@ -40,8 +40,10 @@
*/
package org.openide.actions;
+import javax.swing.Action;
import org.openide.awt.UndoRedo;
import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.TopComponent;
@@ -56,15 +58,18 @@
import javax.swing.UIManager;
import javax.swing.event.*;
import javax.swing.undo.*;
+import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
-/** Undo an edit.
+/** Undo an edit. Since version 6.15 this class
+* implements {@link ContextAwareAction}.
*
* @see UndoRedo
* @author Ian Formanek, Jaroslav Tulach
*/
-public class UndoAction extends CallableSystemAction {
+public class UndoAction extends CallableSystemAction
+implements ContextAwareAction {
/** initialized listener */
private static Listener listener;
@@ -188,6 +193,11 @@
return false;
}
+ @Override
+ public Action createContextAwareInstance(Lookup actionContext) {
+ return new UndoRedoAction(actionContext, true, false);
+ }
+
/** Listener on changes of selected workspace element and
* its changes.
*/
diff -r 1db5ce9ba37d openide.actions/src/org/openide/actions/UndoRedoAction.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openide.actions/src/org/openide/actions/UndoRedoAction.java Thu Feb 18 19:22:19 2010 +0100
@@ -0,0 +1,255 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.openide.actions;
+
+import java.awt.EventQueue;
+import java.awt.event.ActionEvent;
+import javax.swing.Action;
+import org.openide.awt.UndoRedo;
+import org.openide.util.HelpCtx;
+import org.openide.util.LookupEvent;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+import org.openide.windows.TopComponent.Registry;
+import org.openide.windows.WindowManager;
+
+import java.beans.*;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import javax.swing.AbstractAction;
+
+import javax.swing.UIManager;
+import javax.swing.event.*;
+import javax.swing.undo.*;
+import org.openide.util.ContextAwareAction;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.LookupListener;
+import org.openide.util.Utilities;
+import org.openide.util.WeakListeners;
+
+
+/** Context aware undo and redo actions.
+*
+* @author Jaroslav Tulach
+*/
+final class UndoRedoAction extends AbstractAction
+implements ContextAwareAction, PropertyChangeListener, ChangeListener, LookupListener, Runnable, HelpCtx.Provider {
+ private static final Logger LOG = Logger.getLogger(UndoRedoAction.class.getName());
+ /** last edit */
+ private UndoRedo last = UndoRedo.NONE;
+ private final boolean doUndo;
+ private final Lookup.Result result;
+ private final boolean fallback;
+ private PropertyChangeListener weakPCL;
+ private ChangeListener weakCL;
+ private LookupListener weakLL;
+
+
+ UndoRedoAction(Lookup context, boolean doUndo, boolean fallback) {
+ this.doUndo = doUndo;
+ this.fallback = fallback;
+ this.result = context.lookupResult(UndoRedo.Provider.class);
+ }
+
+ public static Action create(Map,?> map) {
+ if (Boolean.TRUE.equals(map.get("redo"))) { // NOI18N
+ return new UndoRedoAction(Utilities.actionsGlobalContext(), false, true);
+ }
+ if (Boolean.TRUE.equals(map.get("undo"))) { // NOI18N
+ return new UndoRedoAction(Utilities.actionsGlobalContext(), true, true);
+ }
+ throw new IllegalStateException();
+ }
+
+
+ @Override
+ public boolean isEnabled() {
+ initializeUndoRedo();
+ return super.isEnabled();
+ }
+
+ void initializeUndoRedo() {
+ assert EventQueue.isDispatchThread();
+ if (weakLL != null) {
+ return;
+ }
+ String res;
+ if (doUndo) {
+ res = "org/openide/resources/actions/undo.gif"; // NOI18N
+ } else {
+ res = "org/openide/resources/actions/redo.gif"; // NOI18N
+ }
+ putValue("iconBase", res); // NOI18N
+ putValue(SMALL_ICON, ImageUtilities.loadImageIcon(res, true));
+ if (fallback) {
+ Registry r = WindowManager.getDefault().getRegistry();
+ weakPCL = WeakListeners.propertyChange(this, r);
+ r.addPropertyChangeListener(weakPCL);
+ }
+ weakCL = WeakListeners.change(this, null);
+ weakLL = WeakListeners.create(LookupListener.class, this, result);
+ result.addLookupListener(weakLL);
+ last = UndoRedo.NONE;
+
+ run();
+ }
+
+ @Override
+ public void run() {
+ if (!EventQueue.isDispatchThread()) {
+ EventQueue.invokeLater(this);
+ return;
+ }
+
+ UndoRedo ur = getUndoRedo();
+ last.removeChangeListener(weakCL);
+
+ if (doUndo) {
+ setEnabled(ur.canUndo());
+ } else {
+ setEnabled(ur.canRedo());
+ }
+ putValue(NAME, getName());
+
+ last = ur;
+ last.addChangeListener(weakCL);
+ }
+
+ private UndoRedo getUndoRedo() {
+ assert EventQueue.isDispatchThread();
+ for (UndoRedo.Provider provider : result.allInstances()) {
+ UndoRedo ur = provider.getUndoRedo();
+ if (ur != null) {
+ return ur;
+ }
+ }
+
+ if (fallback) {
+ TopComponent el = WindowManager.getDefault().getRegistry().getActivated();
+ if (el != null) {
+ UndoRedo ur = el.getUndoRedo();
+ if (ur != null) {
+ return ur;
+ }
+ }
+ }
+ return UndoRedo.NONE;
+ }
+
+ private String getName() {
+ assert EventQueue.isDispatchThread();
+ //#40823 related. AbstractUndoableEdit prepends "Undo/Redo" strings before the custom text,
+ // resulting in repetitive text in UndoAction/RedoAction. attempt to remove the AbstractUndoableEdit text
+ // keeping our text because it has mnemonics.
+ String undo = getUndoRedo().getUndoPresentationName();
+ LOG.log (Level.FINE, "getUndoRedo().getUndoPresentationName() returns {0}", undo);
+
+ if ((undo != null) && (getDefaultSwingText() != null) && undo.startsWith(getDefaultSwingText())) {
+ undo = undo.substring(getDefaultSwingText().length()).trim();
+ }
+
+ LOG.log (Level.FINE, "Name adapted by SWING_DEFAULT_LABEL is {0}", undo);
+ String presentationName = null;
+ if (undo == null || undo.trim ().length () == 0) {
+ presentationName = NbBundle.getMessage(UndoRedoAction.class, doUndo ? "UndoSimple" : "RedoSimple");
+ } else {
+ presentationName = NbBundle.getMessage(UndoRedoAction.class, doUndo ? "UndoWithParameter" : "UndoSimple", undo);
+ }
+
+ LOG.log (Level.FINE, "Result name is {0}", presentationName);
+
+ return presentationName;
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return new HelpCtx(UndoRedoAction.class);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent ev) {
+ UndoRedo undoRedo = getUndoRedo();
+ if (doUndo) try {
+ if (undoRedo.canUndo()) {
+ undoRedo.undo();
+ }
+ } catch (CannotUndoException ex) {
+ Exceptions.printStackTrace(ex);
+ } else try {
+ if (undoRedo.canRedo()) {
+ undoRedo.redo();
+ }
+ } catch (CannotRedoException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ run();
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent ev) {
+ if (TopComponent.Registry.PROP_ACTIVATED.equals(ev.getPropertyName())) {
+ run();
+ }
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent ev) {
+ run();
+ }
+
+ @Override
+ public void resultChanged(LookupEvent ev) {
+ run();
+ }
+
+ @Override
+ public Action createContextAwareInstance(Lookup actionContext) {
+ return new UndoRedoAction(actionContext, doUndo, false);
+ }
+
+ private String getDefaultSwingText() {
+ return doUndo ? UIManager.getString("AbstractUndoableEdit.undoText") : //NOI18N
+ UIManager.getString("AbstractUndoableEdit.redoText"); //NOI18N
+ }
+}
diff -r 1db5ce9ba37d openide.actions/test/unit/src/org/openide/actions/UndoRedoActionTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openide.actions/test/unit/src/org/openide/actions/UndoRedoActionTest.java Thu Feb 18 19:22:19 2010 +0100
@@ -0,0 +1,224 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010 Sun Microsystems, Inc.
+ */
+
+package org.openide.actions;
+
+import java.awt.event.ActionEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.Action;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoableEdit;
+import org.netbeans.junit.NbTestCase;
+import org.openide.awt.UndoRedo;
+import org.openide.util.ContextAwareAction;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class UndoRedoActionTest extends NbTestCase
+implements UndoRedo.Provider {
+ private UndoRedo.Manager ur;
+ private MyEdit me;
+
+ public UndoRedoActionTest(String n) {
+ super(n);
+ }
+
+ @Override
+ protected boolean runInEQ() {
+ return true;
+ }
+
+ private Action undoAction(Lookup lkp) {
+ UndoAction u = UndoAction.get(UndoAction.class);
+ assertTrue("instance: " + u, u instanceof ContextAwareAction);
+ return ((ContextAwareAction) u).createContextAwareInstance(lkp);
+ }
+
+ private Action redoAction(Lookup lkp) {
+ RedoAction r = RedoAction.get(RedoAction.class);
+ assertTrue("instance: " + r, r instanceof ContextAwareAction);
+ return ((ContextAwareAction) r).createContextAwareInstance(lkp);
+ }
+
+ public void testUndoDeliversChanges() {
+ doUndoRedoTest(new UndoRedo.Manager(), true);
+ }
+
+ public void testUndoDeliversChangesWithTooManyEdits() {
+ UndoRedo.Manager man = new UndoRedo.Manager() {
+ @Override
+ public boolean canUndo() {
+ if (super.canUndo()) {
+ undoableEditHappened(new UndoableEditEvent(UndoRedoActionTest.this, new MyEdit(true)));
+ }
+ return super.canUndo();
+ }
+ };
+ doUndoRedoTest(man, false);
+ }
+
+
+ private void doUndoRedoTest(UndoRedo.Manager man, boolean testCounts) {
+ me = new MyEdit();
+ man.undoableEditHappened(new UndoableEditEvent(this, me));
+ assertTrue("Can undo", man.canUndo());
+ this.ur = man;
+
+ InstanceContent ic = new InstanceContent();
+ AbstractLookup lkp = new AbstractLookup(ic);
+ Action u = undoAction(lkp);
+ Action r = redoAction(lkp);
+
+ assertFalse("Not enabled", u.isEnabled());
+ assertFalse("Not enabledR", r.isEnabled());
+ MyEdit lu = new MyEdit();
+ MyEdit lr = new MyEdit();
+ u.addPropertyChangeListener(lu);
+ r.addPropertyChangeListener(lr);
+
+ ic.add(this);
+
+ assertTrue("Action is enabled", u.isEnabled());
+ assertEquals("One change", 1, lu.cnt);
+ assertEquals("No redo change", 0, lr.cnt);
+
+ u.actionPerformed(new ActionEvent(this, 0, ""));
+ if (testCounts) {
+ assertEquals("my edit undone", 1, me.undo);
+
+ assertFalse("No more undo", man.canUndo());
+ assertTrue("But redo", man.canRedo());
+ assertEquals("Another undo change", 2, lu.cnt);
+ assertEquals("New redo change", 1, lr.cnt);
+ assertTrue("Redo action enabled", r.isEnabled());
+ }
+
+ r.actionPerformed(new ActionEvent(this, 0, ""));
+ assertFalse("Redo action no longer enabled", r.isEnabled());
+ }
+
+ @Override
+ public UndoRedo getUndoRedo() {
+ return ur;
+ }
+
+ private static final class MyEdit implements UndoableEdit, PropertyChangeListener {
+ private int undo;
+ private int redo;
+ private int cnt;
+ private boolean ignore;
+
+ public MyEdit() {
+ this(false);
+ }
+
+ public MyEdit(boolean ignore) {
+ this.ignore = ignore;
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("enabled".equals(evt.getPropertyName())) {
+ cnt++;
+ }
+ }
+
+ @Override
+ public void undo() throws CannotUndoException {
+ undo++;
+ }
+
+ @Override
+ public boolean canUndo() {
+ return true;
+ }
+
+ @Override
+ public void redo() throws CannotRedoException {
+ redo++;
+ }
+
+ @Override
+ public boolean canRedo() {
+ return true;
+ }
+
+ @Override
+ public void die() {
+ }
+
+ @Override
+ public boolean addEdit(UndoableEdit anEdit) {
+ return false;
+ }
+
+ @Override
+ public boolean replaceEdit(UndoableEdit anEdit) {
+ return false;
+ }
+
+ @Override
+ public boolean isSignificant() {
+ return true;
+ }
+
+ @Override
+ public String getPresentationName() {
+ return "My Edit";
+ }
+
+ @Override
+ public String getUndoPresentationName() {
+ return "My Undo";
+ }
+
+ @Override
+ public String getRedoPresentationName() {
+ return "My Redo";
+ }
+ }
+}
\ No newline at end of file
diff -r 1db5ce9ba37d openide.awt/manifest.mf
--- a/openide.awt/manifest.mf Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.awt/manifest.mf Thu Feb 18 19:22:19 2010 +0100
@@ -2,5 +2,5 @@
OpenIDE-Module: org.openide.awt
OpenIDE-Module-Localizing-Bundle: org/openide/awt/Bundle.properties
AutoUpdate-Essential-Module: true
-OpenIDE-Module-Specification-Version: 7.21
+OpenIDE-Module-Specification-Version: 7.22
diff -r 1db5ce9ba37d openide.awt/src/org/openide/awt/UndoRedo.java
--- a/openide.awt/src/org/openide/awt/UndoRedo.java Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.awt/src/org/openide/awt/UndoRedo.java Thu Feb 18 19:22:19 2010 +0100
@@ -40,12 +40,13 @@
*/
package org.openide.awt;
-import org.openide.util.Task;
import java.util.LinkedList;
import javax.swing.event.*;
import javax.swing.undo.*;
import org.openide.util.ChangeSupport;
+import org.openide.util.Lookup;
+import org.openide.util.Utilities;
/** Undo and Redo manager for top components and workspace elements.
@@ -113,6 +114,18 @@
*/
public String getRedoPresentationName();
+ /** Components that provide {@link UndoRedo} shall announce that by
+ * implementing this provider interface. Both Edit/Undo and Edit/Redo actions
+ * seek this interface inside current selection (e.g. {@link Utilities#actionsGlobalContext()}).
+ * To control these actions make sure your implementation of this interface
+ * is exposed in instance representing {@link Lookup current context}.
+ *
+ * @since 7.21
+ */
+ public static interface Provider {
+ public UndoRedo getUndoRedo();
+ }
+
/** An undo manager which fires a change event each time it consumes a new undoable edit.
*/
public static class Manager extends UndoManager implements UndoRedo {
@@ -121,10 +134,7 @@
private final ChangeSupport cs = new ChangeSupport(this);
/** vector of Edits to run */
- private LinkedList runus = new LinkedList(); // for fix of #8692
-
- /** task that clears the queue */
- private Task task = Task.EMPTY; // for fix of #8692
+ private final LinkedList runus = new LinkedList(); // for fix of #8692
/** Called from undoableEditHappened() inner class */
private void superUndoableEditHappened(UndoableEditEvent ue) {
@@ -140,6 +150,7 @@
* Delegates to superclass and notifies listeners.
* @param ue the edit
*/
+ @Override
public void undoableEditHappened(final UndoableEditEvent ue) {
/* Edits are posted to request processor and the deadlock
* in #8692 between undoredo and document that fires
@@ -153,6 +164,7 @@
}
/** Discard all the existing edits from the undomanager. */
+ @Override
public void discardAllEdits() {
synchronized (runus) {
runus.add(null);
@@ -161,56 +173,43 @@
updateTask();
}
- public boolean canUndo() {
- /* First it must be checked that there are
- * undoable edits waiting to be added to undoredo.
- */
- boolean empty;
+ @Override
+ public void undo() throws CannotUndoException {
+ super.undo();
+ updateTask();
+ }
- synchronized (runus) {
- empty = runus.isEmpty();
- }
+ @Override
+ public void redo() throws CannotRedoException {
+ super.redo();
+ updateTask();
+ }
- if (!empty) {
- task.waitFinished();
- }
-
- return super.canUndo();
+ @Override
+ public void undoOrRedo() throws CannotRedoException, CannotUndoException {
+ super.undoOrRedo();
+ updateTask();
}
private void updateTask() {
- /* The following task is finished when there are no
- * undoable edits waiting to be added to undoredo.
- */
- class R implements Runnable {
- public void run() {
- for (;;) {
- UndoableEditEvent ue;
+ for (;;) {
+ UndoableEditEvent ue;
- synchronized (runus) {
- if (runus.isEmpty()) {
- break;
- }
+ synchronized (runus) {
+ if (runus.isEmpty()) {
+ break;
+ }
- ue = runus.removeFirst();
- }
+ ue = runus.removeFirst();
+ }
- if (ue == null) {
- superDiscardAllEdits();
- } else {
- superUndoableEditHappened(ue);
- }
-
- cs.fireChange();
- }
+ if (ue == null) {
+ superDiscardAllEdits();
+ } else {
+ superUndoableEditHappened(ue);
}
}
-
- R r = new R();
- r.run();
-
- //Use internal not default RequestProcessor to solve deadlock #10826
- //task = internalRequestProcessor.post (r, 0, Thread.MAX_PRIORITY);
+ cs.fireChange();
}
/* Attaches change listener to the this object.
@@ -219,20 +218,24 @@
*/
//#32313 - synchronization of this method was removed
+ @Override
public void addChangeListener(ChangeListener l) {
cs.addChangeListener(l);
}
/* Removes the listener
*/
+ @Override
public void removeChangeListener(ChangeListener l) {
cs.removeChangeListener(l);
}
+ @Override
public String getUndoPresentationName() {
return this.canUndo() ? super.getUndoPresentationName() : ""; // NOI18N
}
+ @Override
public String getRedoPresentationName() {
return this.canRedo() ? super.getRedoPresentationName() : ""; // NOI18N
}
@@ -245,32 +248,40 @@
*/
@Deprecated
public static final class Empty extends Object implements UndoRedo {
+ @Override
public boolean canUndo() {
return false;
}
+ @Override
public boolean canRedo() {
return false;
}
+ @Override
public void undo() throws CannotUndoException {
throw new CannotUndoException();
}
+ @Override
public void redo() throws CannotRedoException {
throw new CannotRedoException();
}
+ @Override
public void addChangeListener(ChangeListener l) {
}
+ @Override
public void removeChangeListener(ChangeListener l) {
}
+ @Override
public String getUndoPresentationName() {
return ""; // NOI18N
}
+ @Override
public String getRedoPresentationName() {
return ""; // NOI18N
}
diff -r 1db5ce9ba37d openide.awt/test/unit/src/org/openide/awt/UndoRedoTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openide.awt/test/unit/src/org/openide/awt/UndoRedoTest.java Thu Feb 18 19:22:19 2010 +0100
@@ -0,0 +1,183 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010 Sun Microsystems, Inc.
+ */
+
+package org.openide.awt;
+
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.undo.UndoableEdit;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.UndoableEditEvent;
+import org.netbeans.junit.NbTestCase;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class UndoRedoTest extends NbTestCase implements ChangeListener {
+ private int cnt;
+
+ public UndoRedoTest(String n) {
+ super(n);
+ }
+
+ public void testUndoDeliversChanges() {
+ UndoRedo.Manager ur = new UndoRedo.Manager();
+ doUndoRedoTest(ur);
+ }
+
+ public void testUndoDeliversChangesWithTooManyEdits() {
+ UndoRedo.Manager ur = new UndoRedo.Manager() {
+ @Override
+ public boolean canUndo() {
+ if (super.canUndo()) {
+ undoableEditHappened(new UndoableEditEvent(this, new MyEdit(true)));
+ }
+ return super.canUndo();
+ }
+ };
+ doUndoRedoTest(ur);
+ }
+
+ private void doUndoRedoTest(UndoRedo.Manager ur) {
+ assertFalse("Nothing to undo", ur.canUndo());
+ ur.addChangeListener(this);
+ MyEdit me = new MyEdit();
+ ur.undoableEditHappened(new UndoableEditEvent(this, me));
+ assertEquals("One change", 1, cnt);
+ assertTrue("Can undo now", ur.canUndo());
+ ur.undo();
+ assertFalse("Cannot undo", ur.canUndo());
+ assertEquals("Snd change", 2, cnt);
+
+ assertTrue("But redo", ur.canRedo());
+ ur.redo();
+ assertEquals("Third change", 3, cnt);
+ assertEquals("One undo", 1, me.undo);
+ assertEquals("One redo", 1, me.redo);
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ cnt++;
+ }
+ private static final class MyEdit implements UndoableEdit, PropertyChangeListener {
+ private int undo;
+ private int redo;
+ private int cnt;
+ private boolean ignore;
+
+ public MyEdit() {
+ this(false);
+ }
+
+ public MyEdit(boolean ignore) {
+ this.ignore = ignore;
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("enabled".equals(evt.getPropertyName())) {
+ cnt++;
+ }
+ }
+
+ @Override
+ public void undo() throws CannotUndoException {
+ undo++;
+ }
+
+ @Override
+ public boolean canUndo() {
+ return true;
+ }
+
+ @Override
+ public void redo() throws CannotRedoException {
+ redo++;
+ }
+
+ @Override
+ public boolean canRedo() {
+ return true;
+ }
+
+ @Override
+ public void die() {
+ }
+
+ @Override
+ public boolean addEdit(UndoableEdit anEdit) {
+ if (anEdit instanceof MyEdit && ((MyEdit)anEdit).ignore) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean replaceEdit(UndoableEdit anEdit) {
+ return false;
+ }
+
+ @Override
+ public boolean isSignificant() {
+ return true;
+ }
+
+ @Override
+ public String getPresentationName() {
+ return "My Edit";
+ }
+
+ @Override
+ public String getUndoPresentationName() {
+ return "My Undo";
+ }
+
+ @Override
+ public String getRedoPresentationName() {
+ return "My Redo";
+ }
+ }
+
+}
\ No newline at end of file
diff -r 1db5ce9ba37d openide.text/src/org/openide/text/CloneableEditorSupport.java
--- a/openide.text/src/org/openide/text/CloneableEditorSupport.java Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.text/src/org/openide/text/CloneableEditorSupport.java Thu Feb 18 19:22:19 2010 +0100
@@ -120,7 +120,8 @@
*
* @author Jaroslav Tulach
*/
-public abstract class CloneableEditorSupport extends CloneableOpenSupport {
+public abstract class CloneableEditorSupport extends CloneableOpenSupport
+implements UndoRedo.Provider {
private static final RequestProcessor RP = new RequestProcessor("org.openide.text Document Processing");
/** Common name for editor mode. */
diff -r 1db5ce9ba37d openide.windows/src/org/openide/windows/TopComponent.java
--- a/openide.windows/src/org/openide/windows/TopComponent.java Thu Feb 18 12:56:39 2010 +0100
+++ b/openide.windows/src/org/openide/windows/TopComponent.java Thu Feb 18 19:22:19 2010 +0100
@@ -112,7 +112,7 @@
*
* @author Jaroslav Tulach, Petr Hamernik, Jan Jancura
*/
-public class TopComponent extends JComponent implements Externalizable, Accessible, HelpCtx.Provider, Lookup.Provider {
+public class TopComponent extends JComponent implements Externalizable, Accessible, HelpCtx.Provider, Lookup.Provider, UndoRedo.Provider {
/** UI logger to notify about invocation of an action */
private static Logger UILOG = Logger.getLogger("org.netbeans.ui.actions"); // NOI18N
/** generated Serialized Version UID */