Index: openide/src/org/openide/util/actions/CallbackSystemAction.java =================================================================== RCS file: /cvs/openide/src/org/openide/util/actions/CallbackSystemAction.java,v retrieving revision 1.38 diff -u -r1.38 CallbackSystemAction.java --- openide/src/org/openide/util/actions/CallbackSystemAction.java 12 Mar 2004 19:31:37 -0000 1.38 +++ openide/src/org/openide/util/actions/CallbackSystemAction.java 17 Mar 2005 14:04:55 -0000 @@ -73,7 +73,6 @@ setSurviveFocusChange(false); } - /** Get the current action performer. * @return the current action performer, or null if there is currently no performer */ @@ -121,13 +120,13 @@ /** Updates the enabled state by checking performer and ActionMap */ private void updateEnabled () { - javax.swing.Action action = findGlobalContextAction (); + javax.swing.Action action = GlobalManager.getDefault ().findGlobalAction (getActionMapKey (), getSurviveFocusChange ()); if(action != null) { setEnabled (action.isEnabled()); synchronized (LISTENER) { ActionDelegateListener l = (ActionDelegateListener)getProperty(LISTENER); - if (l == null) { + if (l == null || l.get () != this) { l = new ActionDelegateListener (this, action); putProperty (LISTENER, l); } else { @@ -163,7 +162,7 @@ */ public void actionPerformed(final ActionEvent ev) { // First try global context action. - final Action action = findGlobalContextAction (); + final Action action = GlobalManager.getDefault ().findGlobalAction (getActionMapKey (), getSurviveFocusChange ()); if (action != null) { if (action.isEnabled()) { action.actionPerformed(ev); @@ -186,19 +185,6 @@ Toolkit.getDefaultToolkit().beep(); } - /** Finds global context action (the one from activated component). - * @return action for key of activated component or null - */ - private javax.swing.Action findGlobalContextAction () { - ActionMap map = GlobalManager.getDefault ().getActionMap (); - if (map != null) { - Object key = getActionMapKey(); - return map.get (key); - } - - return null; - } - /** Perform the action. * This default implementation calls the assigned action performer if it * exists, otherwise does nothing. @@ -304,7 +290,8 @@ private static final class GlobalManager implements LookupListener { private static GlobalManager instance; private Lookup.Result result; - private Reference actionMap; + private Reference actionMap = new WeakReference (null); + private final ActionMap survive = new ActionMap (); public synchronized static GlobalManager getDefault () { if (instance != null) return instance; @@ -317,46 +304,96 @@ new Lookup.Template (ActionMap.class) ); result.addLookupListener(this); + resultChanged (null); } - public ActionMap getActionMap () { - ActionMap a = (ActionMap)Utilities.actionsGlobalContext ().lookup (ActionMap.class); - if (actionMap == null) { - actionMap = new WeakReference (a); + public Action findGlobalAction (Object key, boolean surviveFocusChange) { + ActionMap map = (ActionMap)actionMap.get (); + Action a = map == null ? null : map.get (key); + + if (surviveFocusChange) { + if (a == null) { + a = survive.get (key); + if (a != null) { + a = ((WeakAction)a).getDelegate (); + } + } else { + survive.put (key, new WeakAction (a)); + } } + return a; } /** Change all that do not survive ActionMap change */ public void resultChanged(org.openide.util.LookupEvent ev) { - if (actionMap == null || actionMap.get () != getActionMap ()) { - actionMap = null; - clearActionPerformers (); + ActionMap a = (ActionMap)Utilities.actionsGlobalContext ().lookup (ActionMap.class); + if (a == actionMap.get ()) { + return; } + actionMap = new WeakReference (a); + clearActionPerformers (); } } // end of LookupListener + /** An action that holds a weak reference to other action. + */ + private static final class WeakAction extends WeakReference implements Action { + public WeakAction (Action delegate) { + super (delegate); + } + + public Action getDelegate () { + return (Action)super.get (); + } + + public Object getValue (String key) { + throw new UnsupportedOperationException (); + } + + public void putValue (String key, Object value) { + throw new UnsupportedOperationException (); + } + + public void actionPerformed (ActionEvent e) { + throw new UnsupportedOperationException (); + } + + public void removePropertyChangeListener (PropertyChangeListener listener) { + throw new UnsupportedOperationException (); + } + + public void addPropertyChangeListener (PropertyChangeListener listener) { + throw new UnsupportedOperationException (); + } + + public void setEnabled (boolean b) { + throw new UnsupportedOperationException (); + } + + public boolean isEnabled () { + throw new UnsupportedOperationException (); + } + } + /** A class that listens on changes in enabled state of an action * and updates the state of the action according to it. */ - private static final class ActionDelegateListener extends Object + private static final class ActionDelegateListener extends WeakReference implements PropertyChangeListener { - private CallbackSystemAction action; - private javax.swing.Action delegate; - + private WeakReference delegate; public ActionDelegateListener (CallbackSystemAction c, javax.swing.Action delegate) { - this.action = c; - this.delegate = delegate; - - + super (c); + this.delegate = new WeakReference (delegate); delegate.addPropertyChangeListener(this); } public void clear () { javax.swing.Action a; - - a = delegate; + + WeakReference d = delegate; + a = d == null ? null : (javax.swing.Action)d.get (); if (a == null) return; delegate = null; @@ -364,26 +401,31 @@ } public void attach (javax.swing.Action action) { - if (delegate == action) { + WeakReference d = delegate; + if (d != null && d.get () == action) { return; } - + Action prev = (Action)d.get (); // reattaches to different action - if (this.delegate != null) { - this.delegate.removePropertyChangeListener(this); + if (prev != null) { + prev.removePropertyChangeListener(this); } - this.delegate = action; + this.delegate = new WeakReference (action); action.addPropertyChangeListener(this); } public void propertyChange(java.beans.PropertyChangeEvent evt) { synchronized (LISTENER) { - if (delegate == null) return; + WeakReference d = delegate; + if (d == null || d.get () == null) return; + } + + CallbackSystemAction c = (CallbackSystemAction)get (); + if (c != null) { + c.updateEnabled(); } - - action.updateEnabled(); } } Index: openide/src/org/openide/windows/TopComponent.java =================================================================== RCS file: /cvs/openide/src/org/openide/windows/TopComponent.java,v retrieving revision 1.138 diff -u -r1.138 TopComponent.java --- openide/src/org/openide/windows/TopComponent.java 8 Feb 2005 15:06:48 -0000 1.138 +++ openide/src/org/openide/windows/TopComponent.java 17 Mar 2005 14:04:57 -0000 @@ -557,6 +557,7 @@ * unless it is in active mode already. */ public void requestVisible () { WindowManager.getDefault().topComponentRequestVisible(this); + org.netbeans.modules.openide.windows.GlobalActionContextImpl.blickActionMap (getActionMap ()); } /** Index: openide/test/unit/src/org/openide/util/actions/CallbackSystemActionTest.java =================================================================== RCS file: /cvs/openide/test/unit/src/org/openide/util/actions/CallbackSystemActionTest.java,v retrieving revision 1.11 diff -u -r1.11 CallbackSystemActionTest.java --- openide/test/unit/src/org/openide/util/actions/CallbackSystemActionTest.java 16 Mar 2005 10:56:47 -0000 1.11 +++ openide/test/unit/src/org/openide/util/actions/CallbackSystemActionTest.java 17 Mar 2005 14:04:57 -0000 @@ -13,6 +13,7 @@ package org.openide.util.actions; +import java.lang.ref.WeakReference; import javax.swing.ActionMap; import org.netbeans.junit.*; import junit.textui.TestRunner; @@ -34,14 +35,74 @@ super(name); } - public static void main(String[] args) { - TestRunner.run(new NbTestSuite(CallbackSystemActionTest.class)); - // May have used AWT thread. - System.exit(0); + + protected void setUp () throws Exception { + super.setUp(); } protected boolean runInEQ () { return true; + } + + public void testSurviveFocusChangeInTheNewWay () throws Exception { + doSurviveFocusChangeInTheNewWay (false); + } + + public void testSurviveFocusChangeInTheNewWayEvenActionIsGCed () throws Exception { + doSurviveFocusChangeInTheNewWay (true); + } + + private void doSurviveFocusChangeInTheNewWay (boolean doGC) throws Exception { + class MyAction extends javax.swing.AbstractAction { + public int cntEnabled; + public int cntPerformed; + + public boolean isEnabled () { + cntEnabled++; + return true; + } + + public void actionPerformed (java.awt.event.ActionEvent ev) { + cntPerformed++; + } + } + MyAction myAction = new MyAction (); + + TopComponent other = new TopComponent (); + TopComponent tc = new TopComponent (); + SurviveFocusChgCallbackAction a = (SurviveFocusChgCallbackAction)SurviveFocusChgCallbackAction.get (SurviveFocusChgCallbackAction.class); + tc.getActionMap().put (a.getActionMapKey (), myAction); + + ActionsInfraHid.UT.setActivated(other); + try { + assertFalse ("Disabled on other component", a.isEnabled ()); + ActionsInfraHid.UT.setActivated (tc); + assertTrue ("MyAction is enabled", a.isEnabled ()); + assertEquals ("isEnabled called once", 1, myAction.cntEnabled); + + if (doGC) { + java.lang.ref.WeakReference ref = new java.lang.ref.WeakReference (a); + a = null; + assertGC ("Action can disappear", ref); + a = (SurviveFocusChgCallbackAction)SurviveFocusChgCallbackAction.get (SurviveFocusChgCallbackAction.class); + } + + ActionsInfraHid.UT.setActivated (other); + assertTrue ("Still enabled", a.isEnabled ()); + assertEquals ("isEnabled called still only once (now it is called twice)", 2, myAction.cntEnabled); + } finally { + ActionsInfraHid.UT.setActivated (null); + } + + WeakReference ref = new WeakReference (a); + WeakReference ref2 = new WeakReference (myAction); + WeakReference ref3 = new WeakReference (tc); + a = null; + myAction = null; + tc = null; + assertGC ("We are able to clear global action", ref); + assertGC ("Even our action", ref2); + assertGC ("Even our component", ref3); } /** Make sure that the performer system works and controls enablement. Index: openide/test/unit/src/org/openide/windows/GlobalContextImplTest.java =================================================================== RCS file: /cvs/openide/test/unit/src/org/openide/windows/GlobalContextImplTest.java,v retrieving revision 1.6 diff -u -r1.6 GlobalContextImplTest.java --- openide/test/unit/src/org/openide/windows/GlobalContextImplTest.java 16 Mar 2005 19:35:17 -0000 1.6 +++ openide/test/unit/src/org/openide/windows/GlobalContextImplTest.java 17 Mar 2005 14:04:57 -0000 @@ -24,6 +24,7 @@ import org.openide.nodes.FilterNode; import org.openide.nodes.Node; import org.openide.util.Lookup; +import org.openide.util.LookupEvent; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; @@ -106,6 +107,54 @@ assertEquals ("No change", 3, cnt); assertEquals ("No items in lookup", 0, result.allItems ().size ()); + assertActionMap (); + } + + public void testRequestVisibleBlinksTheActionMapForAWhile () throws Exception { + final org.openide.nodes.Node n = new org.openide.nodes.AbstractNode (org.openide.nodes.Children.LEAF); + tc.setActivatedNodes(new Node[] { n }); + + assertActionMap (); + final Lookup.Result res = lookup.lookup (new Lookup.Template (ActionMap.class)); + assertEquals ("One action map", 1, res.allItems ().size ()); + + class L implements org.openide.util.LookupListener { + ArrayList maps = new ArrayList (); + + public void resultChanged (org.openide.util.LookupEvent ev) { + assertEquals ("Still only one", 1, res.allItems ().size ()); + Lookup.Item i = (Lookup.Item)res.allItems ().iterator ().next (); + assertNotNull (i); + + maps.add (i.getInstance ()); + + assertNode (); + } + + public void assertNode () { + assertEquals ("The node is available", n, lookup.lookup (Node.class)); + } + } + L myListener = new L (); + myListener.assertNode (); + + res.addLookupListener (myListener); + + TopComponent my = new TopComponent (); + my.requestVisible (); + + if (myListener.maps.size () != 2) { + fail ("Expected two changes in the ActionMaps: " + myListener.maps); + } + + myListener.assertNode (); + + ActionMap m1 = (ActionMap)myListener.maps.get (0); + ActionMap m2 = (ActionMap)myListener.maps.get (1); + + assertNull ("Our action is not in first map", m1.get (this)); + assertEquals ("Our action is in second map", sampleAction, m2.get (this)); + assertActionMap (); } Index: openide/windows/src/org/netbeans/modules/openide/windows/GlobalActionContextImpl.java =================================================================== RCS file: /cvs/openide/windows/src/org/netbeans/modules/openide/windows/GlobalActionContextImpl.java,v retrieving revision 1.4 diff -u -r1.4 GlobalActionContextImpl.java --- openide/windows/src/org/netbeans/modules/openide/windows/GlobalActionContextImpl.java 12 Aug 2003 09:38:20 -0000 1.4 +++ openide/windows/src/org/netbeans/modules/openide/windows/GlobalActionContextImpl.java 17 Mar 2005 14:04:57 -0000 @@ -15,6 +15,8 @@ import org.openide.util.Lookup; import org.openide.util.ContextGlobalProvider; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; import org.openide.windows.TopComponent; /** An interface that can be registered in a lookup by subsystems @@ -35,6 +37,33 @@ this.registry = r; } + /** the lookup to temporarily use */ + private static volatile Lookup temporary; + /** Temporarily provides different action map in the lookup. + */ + public static void blickActionMap (javax.swing.ActionMap map) { + Object obj = Lookup.getDefault ().lookup (ContextGlobalProvider.class); + if (obj instanceof GlobalActionContextImpl) { + GlobalActionContextImpl g = (GlobalActionContextImpl)obj; + + Lookup[] arr = { + Lookups.singleton (map), + Lookups.exclude (g.getLookup (), new Class[] { javax.swing.ActionMap.class }), + }; + + Lookup prev = temporary; + try { + temporary = new ProxyLookup (arr); + Object q = org.openide.util.Utilities.actionsGlobalContext ().lookup (javax.swing.ActionMap.class); + assert q == map : "We really get map from the lookup. Map: " + map + " returned: " + q; // NOI18N + } finally { + temporary = prev; + // fire the changes about return of the values back + org.openide.util.Utilities.actionsGlobalContext ().lookup (javax.swing.ActionMap.class); + } + } + } + /** Let's create the proxy listener that delegates to currently * selected top component. */ @@ -45,6 +74,11 @@ /** The current component lookup */ public Lookup getLookup() { + Lookup l = temporary; + if (l != null) { + return l; + } + TopComponent tc = registry.getActivated(); return tc == null ? Lookup.EMPTY : tc.getLookup(); } Index: core/ide/src/org/netbeans/core/ide/resources/layer.xml =================================================================== RCS file: /cvs/core/ide/src/org/netbeans/core/ide/resources/layer.xml,v retrieving revision 1.15 diff -u -r1.15 layer.xml --- core/ide/src/org/netbeans/core/ide/resources/layer.xml 19 May 2004 14:09:52 -0000 1.15 +++ core/ide/src/org/netbeans/core/ide/resources/layer.xml 17 Mar 2005 14:04:58 -0000 @@ -40,6 +40,24 @@ + + + + + + + + + + + + + + + + + + Index: core/output2/src/org/netbeans/core/output2/Bundle.properties =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/Bundle.properties,v retrieving revision 1.9 diff -u -r1.9 Bundle.properties --- core/output2/src/org/netbeans/core/output2/Bundle.properties 11 Nov 2004 07:40:30 -0000 1.9 +++ core/output2/src/org/netbeans/core/output2/Bundle.properties 17 Mar 2005 14:04:58 -0000 @@ -15,8 +15,6 @@ OpenIDE-Module-Long-Description=Output window based on a java.swing.text.Document over a \ ByteBuffer/CharBuffer -Actions/Build=Build - #Title for the output window LBL_OUTPUT=Output #Format for the output window title if it includes the name of the current tab @@ -30,11 +28,6 @@ LBL_SAVE=Save As... TITLE_SAVE_DLG=Save Output As -#NextOutJumpAction -NextOutJump=Ne&xt Error - -#PreviousOutJumpAction -PreviousOutJump=&Previous Error #OutputWindowAction OutputWindow=&Output Index: core/output2/src/org/netbeans/core/output2/Controller.java =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/Controller.java,v retrieving revision 1.31 diff -u -r1.31 Controller.java --- core/output2/src/org/netbeans/core/output2/Controller.java 21 Feb 2005 08:33:34 -0000 1.31 +++ core/output2/src/org/netbeans/core/output2/Controller.java 17 Mar 2005 14:04:58 -0000 @@ -16,6 +16,7 @@ import java.io.CharConversionException; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; +import javax.swing.text.DefaultEditorKit; import org.netbeans.core.output2.ui.AbstractOutputTab; import org.openide.ErrorManager; import org.openide.actions.CopyAction; @@ -82,7 +83,7 @@ //Package private for unit tests Action copyAction = new ControllerAction (ACTION_COPY, - "ACTION_COPY", CopyAction.class); //NOI18N + "ACTION_COPY"); //NOI18N Action wrapAction = new ControllerAction (ACTION_WRAP, "ACTION_WRAP"); //NOI18N Action saveAsAction = new ControllerAction (ACTION_SAVEAS, @@ -90,13 +91,13 @@ Action closeAction = new ControllerAction (ACTION_CLOSE, "ACTION_CLOSE"); //NOI18N Action nextErrorAction = new ControllerAction (ACTION_NEXTERROR, - "ACTION_NEXT_ERROR", NextOutJumpAction.class); //NOI18N + "ACTION_NEXT_ERROR" ); //NOI18N Action prevErrorAction = new ControllerAction (ACTION_PREVERROR, - "ACTION_PREV_ERROR", PreviousOutJumpAction.class); //NOI18N + "ACTION_PREV_ERROR" ); //NOI18N Action selectAllAction = new ControllerAction (ACTION_SELECTALL, "ACTION_SELECT_ALL"); //NOI18N Action findAction = new ControllerAction (ACTION_FIND, - "ACTION_FIND", FindAction.class); //NOI18N + "ACTION_FIND"); //NOI18N Action findNextAction = new ControllerAction (ACTION_FINDNEXT, "ACTION_FIND_NEXT"); //NOI18N Action findPreviousAction = new ControllerAction (ACTION_FINDPREVIOUS, @@ -171,6 +172,14 @@ } else { win.requestActiveForNewTab(); } + + if (result != null) { + // install handlers to prev/next actions + result.getActionMap ().put ("JumpPrevAction", this.prevErrorAction); // NOI18N + result.getActionMap ().put ("JumpNextAction", this.nextErrorAction); // NOI18N + result.getActionMap ().put (FindAction.class.getName (), this.findAction); + result.getActionMap ().put (javax.swing.text.DefaultEditorKit.copyAction, this.copyAction); + } return result; } @@ -718,18 +727,6 @@ } } - /** - * Messaged when the container is deactivated in the netbeans window system - */ - public void notifyDeactivated() { - for (int i=0; i < popupItems.length; i++) { - if (popupItems[i] instanceof Action && popupItems[i] != nextErrorAction && popupItems[i] != prevErrorAction) { - ((ControllerAction) popupItems[i]).detachPerformer(); - } - } - } - - private boolean firstF12 = true; /** * Sends the caret in a tab to the nearest error line to its current position, selecting @@ -1020,7 +1017,6 @@ } break; case IOEvent.CMD_SELECT : - if (tab == null) { tab = createOutputTab(win, io, io.isFocusTaken(), value); } @@ -1034,7 +1030,6 @@ win.add(tab); } win.setSelectedTab(tab); - win.requestVisible(); updateName(win,tab); } break; @@ -1155,7 +1150,6 @@ */ private static class ControllerAction extends AbstractAction implements ActionPerformer { private int id; - private Class callbackActionClass = null; /** * Create a ControllerAction with the specified action ID (constants defined in Controller), * using the specified bundle key. Expects the following contents in the bundle: @@ -1213,19 +1207,6 @@ return Utilities.stringToKey(NbBundle.getMessage(Controller.class, key)); } - /** - * Create a controller which will also act as the action performer for a - * CallbackSystemAction. - * - * @param id The action ID - * @param name The bundle key for the action - * @param callbackActionClass - */ - ControllerAction (int id, String name, Class callbackActionClass) { - this (id, name); - this.callbackActionClass = callbackActionClass; - } - public int getID() { return id; } @@ -1271,25 +1252,6 @@ */ public void setEnabled (boolean val) { super.setEnabled(val); - if (callbackActionClass != null) { - updateActionPerformer(); - } - } - - /** - * Update the state of the CallbackAction which is proxying this action. - */ - private void updateActionPerformer() { - CallbackSystemAction action = (CallbackSystemAction) SystemAction.get(callbackActionClass); - boolean val = isEnabled(); - if (!val && action.getActionPerformer() == this) { - if (log) - log ("Clearing action performer for " + getValue(NAME)); - action.setActionPerformer(null); - } else if( val ) { - if (log) log ("Setting action performer for " + getValue(NAME)); - action.setActionPerformer(this); - } } /** @@ -1304,18 +1266,6 @@ actionPerformed(ae); } - /** - * Resign this action from being the performer for its associated CallbackSystemAction. - */ - public void detachPerformer() { - if (callbackActionClass != null) { - CallbackSystemAction action = (CallbackSystemAction) SystemAction.get(callbackActionClass); - if (action.getActionPerformer() == this) { - if (log) log ("Detaching action performer for " + getValue(NAME)); - action.setActionPerformer(null); - } - } - } } /** Index: core/output2/src/org/netbeans/core/output2/IOEvent.java =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/IOEvent.java,v retrieving revision 1.4 diff -u -r1.4 IOEvent.java --- core/output2/src/org/netbeans/core/output2/IOEvent.java 24 Aug 2004 13:29:08 -0000 1.4 +++ core/output2/src/org/netbeans/core/output2/IOEvent.java 17 Mar 2005 14:04:58 -0000 @@ -100,7 +100,7 @@ * XXX may not be supported - dispose of the default output window instance */ static final int CMD_DETACH = 11; - + /** * Array of IDs for checking legal values and generating a string representing the event. */ @@ -116,7 +116,7 @@ CMD_STREAM_CLOSED, CMD_RESET, CMD_SET_TOOLBAR_ACTIONS, - CMD_DETACH + CMD_DETACH, }; /** Index: core/output2/src/org/netbeans/core/output2/OutputWindow.java =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/OutputWindow.java,v retrieving revision 1.13 diff -u -r1.13 OutputWindow.java --- core/output2/src/org/netbeans/core/output2/OutputWindow.java 14 Mar 2005 13:56:08 -0000 1.13 +++ core/output2/src/org/netbeans/core/output2/OutputWindow.java 17 Mar 2005 14:04:58 -0000 @@ -194,7 +194,6 @@ if (Controller.log) Controller.log("ComponentDeactivated"); super.componentDeactivated(); activated = false; - controller.notifyDeactivated (); } protected void removed(AbstractOutputTab view) { Index: core/output2/src/org/netbeans/core/output2/layer.xml =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/layer.xml,v retrieving revision 1.12 diff -u -r1.12 layer.xml --- core/output2/src/org/netbeans/core/output2/layer.xml 14 Feb 2005 12:47:38 -0000 1.12 +++ core/output2/src/org/netbeans/core/output2/layer.xml 17 Mar 2005 14:04:58 -0000 @@ -25,12 +25,6 @@ - - - - - - @@ -39,12 +33,6 @@ - - - - - - Index: core/output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java =================================================================== RCS file: /cvs/core/output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java,v retrieving revision 1.9 diff -u -r1.9 AbstractOutputWindow.java --- core/output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java 16 Feb 2005 12:39:26 -0000 1.9 +++ core/output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java 17 Mar 2005 14:04:58 -0000 @@ -192,6 +192,8 @@ if (pane.getParent() == this && op != pane.getSelectedComponent()) { pane.setSelectedComponent(op); } + + getActionMap().setParent (op.getActionMap ()); } public void setTabTitle (AbstractOutputTab tab, String name) { Index: core/src/org/netbeans/core/actions/Bundle.properties =================================================================== RCS file: /cvs/core/src/org/netbeans/core/actions/Bundle.properties,v retrieving revision 1.140 diff -u -r1.140 Bundle.properties --- core/src/org/netbeans/core/actions/Bundle.properties 16 Feb 2005 12:44:20 -0000 1.140 +++ core/src/org/netbeans/core/actions/Bundle.properties 17 Mar 2005 14:04:58 -0000 @@ -65,3 +65,7 @@ Actions/Window/SelectDocumentNode=Select Document in LBL_NextViewCallbackAction=Next Inner View LBL_PreviousViewCallbackAction=Previous Inner View + +# jump next/prev actions +JumpNextAction=Ne&xt Error +JumpPrevAction=&Previous Error Index: core/src/org/netbeans/core/actions/JumpNextAction.java =================================================================== RCS file: core/src/org/netbeans/core/actions/JumpNextAction.java diff -N core/src/org/netbeans/core/actions/JumpNextAction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ core/src/org/netbeans/core/actions/JumpNextAction.java 17 Mar 2005 14:04:58 -0000 @@ -0,0 +1,58 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.core.actions; + +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallbackSystemAction; + +/** The action which invoke next "jump" getLine in output window (like next error) +* +* @author Petr Hamernik +*/ +public class JumpNextAction extends CallbackSystemAction { + + protected void initialize() { + super.initialize(); + setSurviveFocusChange(true); + putProperty ("noIconInMenu", Boolean.TRUE); // NOI18N + } + + public void setEnabled (boolean b) { + super.setEnabled (b); + } + + protected String iconResource () { + return "org/netbeans/core/resources/actions/nextOutJump.gif"; // NOI18N + } + + public HelpCtx getHelpCtx() { + return new HelpCtx (JumpNextAction.class); + } + + public String getName() { + return NbBundle.getBundle(JumpNextAction.class).getString("JumpNextAction"); + } + + protected boolean asynchronous() { + return false; + } + + public void setActionPerformer (org.openide.util.actions.ActionPerformer performer) { + throw new java.lang.UnsupportedOperationException (); + } + public Object getActionMapKey () { + return "JumpNextAction"; // NOI18N + } +} Index: core/src/org/netbeans/core/actions/JumpPrevAction.java =================================================================== RCS file: core/src/org/netbeans/core/actions/JumpPrevAction.java diff -N core/src/org/netbeans/core/actions/JumpPrevAction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ core/src/org/netbeans/core/actions/JumpPrevAction.java 17 Mar 2005 14:04:58 -0000 @@ -0,0 +1,57 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.core.actions; + +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallbackSystemAction; + +/** The action which invoke previous "jump" line in output window +* (previous error) +* +* @author Petr Hamernik +*/ +public class JumpPrevAction extends CallbackSystemAction { + + protected void initialize() { + super.initialize(); + setSurviveFocusChange(true); + putProperty ("noIconInMenu", Boolean.TRUE); // NOI18N + } + + protected String iconResource () { + return "org/netbeans/core/resources/actions/previousOutJump.gif"; // NOI18N + } + + public HelpCtx getHelpCtx() { + return new HelpCtx (JumpPrevAction.class); + } + + public String getName() { + return NbBundle.getBundle(JumpPrevAction.class).getString("JumpPrevAction"); + } + + protected boolean asynchronous() { + return false; + } + + public void setActionPerformer (org.openide.util.actions.ActionPerformer performer) { + throw new java.lang.UnsupportedOperationException (); + } + + public Object getActionMapKey () { + return "JumpPrevAction"; // NOI18N + } + +} Index: core/ui/src/org/netbeans/core/ui/resources/layer.xml =================================================================== RCS file: /cvs/core/ui/src/org/netbeans/core/ui/resources/layer.xml,v retrieving revision 1.87 diff -u -r1.87 layer.xml --- core/ui/src/org/netbeans/core/ui/resources/layer.xml 16 Feb 2005 12:39:26 -0000 1.87 +++ core/ui/src/org/netbeans/core/ui/resources/layer.xml 17 Mar 2005 14:04:58 -0000 @@ -67,6 +67,11 @@ + + + + + @@ -153,6 +158,18 @@ + + + + + + + + + + + + @@ -334,6 +351,12 @@ + + + + + + Index: tasklist/core/src/org/netbeans/modules/tasklist/core/TaskListView.java =================================================================== RCS file: /cvs/tasklist/core/src/org/netbeans/modules/tasklist/core/TaskListView.java,v retrieving revision 1.117 diff -u -r1.117 TaskListView.java --- tasklist/core/src/org/netbeans/modules/tasklist/core/TaskListView.java 13 Jan 2005 18:18:08 -0000 1.117 +++ tasklist/core/src/org/netbeans/modules/tasklist/core/TaskListView.java 17 Mar 2005 14:04:59 -0000 @@ -207,6 +207,9 @@ ExplorerUtils.actionPaste(manager)); map.put("delete", ExplorerUtils.actionDelete(manager, true)); // NOI18N + map.put("JumpNextAction", new PrevNextAction (false)); // NOI18N + map.put("JumpPrevAction", new PrevNextAction (true)); // NOI18N + // following line tells the top component which lookup should be associated with it associateLookup(ExplorerUtils.createLookup(manager, map)); } @@ -593,7 +596,6 @@ assert initialized : "#37438 dangling componentActivated event, no componentOpened()" + " called at " + this; - installJumpActions(true); ExplorerUtils.activateActions(manager, true); RemoveFilterAction removeFilter = (RemoveFilterAction) SystemAction.get(RemoveFilterAction.class); @@ -1360,75 +1362,6 @@ return nodes; } - private Class nextActionClz = null; - private Class prevActionClz = null; - - /** - * Assign the Next/Previous build actions to point to the - * task window - * - * @param install true = install, false = deinstall - */ - private void installJumpActions(boolean install) { - // TODO - only install if the list is non empty (and call - // this method from SMI when the list becomes non-empty) - // In other words, the next action button shouldn't light - // up when there are no tasks to move to. - - // RFE #40185 - // Make F12 jump to next task - if (nextActionClz == null) { - if (lookupAttempted) { - return; - } - lookupAttempted = true; - ClassLoader systemClassLoader = (ClassLoader) Lookup.getDefault(). - lookup(ClassLoader.class); - try { - nextActionClz = systemClassLoader. - loadClass("org.netbeans.core.output2.NextOutJumpAction"); // NOI18N - prevActionClz = systemClassLoader. - loadClass("org.netbeans.core.output2.PreviousOutJumpAction"); // NOI18N - } catch (Exception e) { - // Check if the old core/output is installed instead. - try { - nextActionClz = systemClassLoader. - loadClass("org.netbeans.core.output.NextOutJumpAction"); // NOI18N - prevActionClz = systemClassLoader. - loadClass("org.netbeans.core.output.PreviousOutJumpAction"); // NOI18N - } catch (Exception e2) { - // Notify original error. - ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); - return; - } - } - } - - CallbackSystemAction nextAction = - (CallbackSystemAction) SystemAction.get(nextActionClz); - CallbackSystemAction previousAction = - (CallbackSystemAction) SystemAction.get(prevActionClz); - - if (install) { - nextAction.setActionPerformer(new ActionPerformer() { - public void performAction(SystemAction action) { - nextTask(); - } - }); - previousAction.setActionPerformer(new ActionPerformer() { - public void performAction(SystemAction action) { - prevTask(); - } - }); - - nextCandidate = null; - prevCandidate = null; - } else { - nextAction.setActionPerformer(null); - previousAction.setActionPerformer(null); - } - } - private boolean lookupAttempted = false; private static void invokeLater(Runnable runnable) { @@ -1695,16 +1628,6 @@ protected void componentHidden() { hideTaskInEditor(); - - // Remove jump actions - // Cannot do this, because componentHidden can be called - // after another TaskListView is shown (for example when you - // switch from one tasklist view to another) so this would - // cripple the newly showing tasklist view. - // - // According to issue #37367 hidden and activated events works - // together smmothly to get desired result - installJumpActions(false); } /** Return true iff the given node is expanded */ @@ -1782,5 +1705,25 @@ } } return (ColumnProperty[]) ret.toArray(new ColumnProperty[ret.size()]); + } + + /** Action to just to previous or next task. + */ + private final class PrevNextAction extends javax.swing.AbstractAction { + private boolean prev; + + public PrevNextAction (boolean prev) { + this.prev = prev; + } + + public void actionPerformed (java.awt.event.ActionEvent actionEvent) { + if (prev) { + prevTask (); + } else { + nextTask (); + } + } + + } }