diff --git a/core.io.ui/src/org/netbeans/core/io/ui/IOWindow.java b/core.io.ui/src/org/netbeans/core/io/ui/IOWindow.java --- a/core.io.ui/src/org/netbeans/core/io/ui/IOWindow.java +++ b/core.io.ui/src/org/netbeans/core/io/ui/IOWindow.java @@ -271,7 +271,8 @@ @Override public void open() { - super.open(); + if (!isOpened()) + super.open(); } @Override @@ -285,10 +286,12 @@ @Override public void requestVisible() { - super.requestVisible(); - if (Boolean.TRUE.equals(getClientProperty("isSliding"))) { //NOI18N - requestActive(); - } + if (!isShowing()) { + super.requestVisible(); + if (Boolean.TRUE.equals(getClientProperty("isSliding"))) { //NOI18N + requestActive(); + } + } } boolean activated; @@ -360,12 +363,15 @@ } public void selectTab(JComponent comp) { - if (!isOpened()) { - open(); - } - if (!isShowing()) { - requestVisible(); - } +// Calls to open/requestVisible() lifted into Controller, case CMD_SELECT. +// Tests pushed into this.open() and this.requestVisible(). +// +// if (!isOpened()) { +// open(); +// } +// if (!isShowing()) { +// requestVisible(); +// } if (singleTab == null) { pane.setSelectedComponent(comp); } diff --git a/core.output2/src/org/netbeans/core/output2/Controller.java b/core.output2/src/org/netbeans/core/output2/Controller.java --- a/core.output2/src/org/netbeans/core/output2/Controller.java +++ b/core.output2/src/org/netbeans/core/output2/Controller.java @@ -47,6 +47,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -60,6 +61,7 @@ import org.openide.util.NbPreferences; import org.openide.windows.IOColors; import org.openide.windows.IOContainer; +import org.openide.windows.IOSelect; import org.openide.windows.OutputEvent; import org.openide.xml.XMLUtil; @@ -376,10 +378,38 @@ if (tab == null) { tab = createOutputTab(io); } - if (io.isFocusTaken()) { - ioContainer.requestActive(); + if (io.isFocusTaken()) { + ioContainer.requestActive(); + } + + // After fixing bug#185209 IOContainer.select() no longer + // performs these operations for us so we have to do them. + ioContainer.open(); + ioContainer.requestVisible(); + + ioContainer.select(tab); + break; + case IOEvent.CMD_FINE_SELECT : + if (tab == null) { + tab = createOutputTab(io); } - ioContainer.select(tab); + + // We get here via IOSelect.select(). + assert data == null || data instanceof EnumSet; + @SuppressWarnings("unchecked") // NOI18N + EnumSet extraOps = + (EnumSet) data; + + if (extraOps != null) { + // the order of these tests mimics the order of calls above. + if (io.isFocusTaken() && extraOps.contains(IOSelect.AdditionalOperation.REQUEST_ACTIVE)) + ioContainer.requestActive(); + if (extraOps.contains(IOSelect.AdditionalOperation.OPEN)) + ioContainer.open(); + if (extraOps.contains(IOSelect.AdditionalOperation.REQUEST_VISIBLE)) + ioContainer.requestVisible(); + } + ioContainer.select(tab); break; case IOEvent.CMD_SET_TOOLBAR_ACTIONS : if (tab != null) { diff --git a/core.output2/src/org/netbeans/core/output2/IOEvent.java b/core.output2/src/org/netbeans/core/output2/IOEvent.java --- a/core.output2/src/org/netbeans/core/output2/IOEvent.java +++ b/core.output2/src/org/netbeans/core/output2/IOEvent.java @@ -135,8 +135,13 @@ /** set default colors */ static final int CMD_DEF_COLORS = 14; + + /** + * Command to support IOSelect.select() (with "fine" control. + */ + static final int CMD_FINE_SELECT=15; - private static final int CMD_LAST = 15; + private static final int CMD_LAST = 16; /** * Strings representing the event. @@ -156,6 +161,8 @@ "CMD_SET_ICON", //NOI18N "CMD_SET_TOOLTIP", //NOI18N "CMD_SCROLL", //NOI18N + "CMD_DEF_COLORS", //NOI18N + "CMD_FINE_SELECT", //NOI18N }; /** diff --git a/core.output2/src/org/netbeans/core/output2/NbIO.java b/core.output2/src/org/netbeans/core/output2/NbIO.java --- a/core.output2/src/org/netbeans/core/output2/NbIO.java +++ b/core.output2/src/org/netbeans/core/output2/NbIO.java @@ -41,6 +41,7 @@ package org.netbeans.core.output2; +import java.util.EnumSet; import org.openide.windows.InputOutput; import org.openide.windows.OutputListener; import org.openide.windows.OutputWriter; @@ -57,6 +58,7 @@ import org.openide.windows.IOColors; import org.openide.windows.IOContainer; import org.openide.windows.IOPosition; +import org.openide.windows.IOSelect; import org.openide.windows.IOTab; /** Implementation of InputOutput. Implements calls as a set of @@ -272,7 +274,7 @@ if (lookup == null) { ioTab = new IOTabImpl(); ioColors = new IOColorsImpl(); - lookup = Lookups.fixed(ioTab, ioColors, new IOPositionImpl(), new IOColorLinesImpl(), new IOColorPrintImpl()); + lookup = Lookups.fixed(ioTab, ioColors, new IOPositionImpl(), new IOColorLinesImpl(), new IOColorPrintImpl(), new IOSelectImpl()); } return lookup; } @@ -502,6 +504,15 @@ } } + private class IOSelectImpl extends IOSelect { + + @Override + protected void select(EnumSet extraOps) { + if (Controller.LOG) Controller.log (this + ": IOSelect.select"); + NbIO.post (NbIO.this, IOEvent.CMD_FINE_SELECT, extraOps); + } + } + private class IOColorsImpl extends IOColors { Color[] clrs = new Color[4]; diff --git a/core.output2/src/org/netbeans/core/output2/OutputTab.java b/core.output2/src/org/netbeans/core/output2/OutputTab.java --- a/core.output2/src/org/netbeans/core/output2/OutputTab.java +++ b/core.output2/src/org/netbeans/core/output2/OutputTab.java @@ -231,6 +231,10 @@ IOContainer ioContainer = io.getIOContainer(); if (io.isFocusTaken()) { + // The following two lines pulled up from select per bug#185209 + ioContainer.open(); + // ioContainer.requestVisible(); + ioContainer.select(this); ioContainer.requestVisible(); } diff --git a/core.output2/test/unit/src/org/netbeans/core/output2/LifecycleTest.java b/core.output2/test/unit/src/org/netbeans/core/output2/LifecycleTest.java --- a/core.output2/test/unit/src/org/netbeans/core/output2/LifecycleTest.java +++ b/core.output2/test/unit/src/org/netbeans/core/output2/LifecycleTest.java @@ -47,6 +47,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.EnumSet; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; @@ -54,6 +55,7 @@ import org.netbeans.junit.RandomlyFails; import org.openide.util.Exceptions; import org.openide.windows.IOContainer; +import org.openide.windows.IOSelect; import org.openide.windows.OutputWriter; /** @@ -338,6 +340,45 @@ } + // Not really a Lifecycle feature but requires a bonafide TC container + // which this Test provides. + public void testFineSelect() { + System.out.println("testFineSelect"); + + EnumSet extraOps; + + extraOps = null; + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.noneOf(IOSelect.AdditionalOperation.class); + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.of(IOSelect.AdditionalOperation.OPEN); + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.of(IOSelect.AdditionalOperation.REQUEST_ACTIVE); + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.of(IOSelect.AdditionalOperation.REQUEST_VISIBLE); + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.of(IOSelect.AdditionalOperation.OPEN, + IOSelect.AdditionalOperation.REQUEST_VISIBLE); + IOSelect.select(io, extraOps); + sleep(); + + extraOps = EnumSet.of(IOSelect.AdditionalOperation.OPEN, + IOSelect.AdditionalOperation.REQUEST_VISIBLE, + IOSelect.AdditionalOperation.REQUEST_ACTIVE); + IOSelect.select(io, extraOps); + sleep(); + } + static JComponent getIOWindow() { IOContainer container = IOContainer.getDefault(); JComponent comp = null; diff --git a/openide.io/src/org/openide/windows/IOSelect.java b/openide.io/src/org/openide/windows/IOSelect.java new file mode 100644 --- /dev/null +++ b/openide.io/src/org/openide/windows/IOSelect.java @@ -0,0 +1,116 @@ +/* + * 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.windows; + +import java.util.EnumSet; +import org.openide.util.Lookup; + +/** + * Capability of an InputOutput of finer grained selection of a component. + *

+ * InputOutput.select() does too much. + * @author ivan + */ +public abstract class IOSelect { + + /** + * Additional operations to perform when issuing {@link IOSelect#select}. + * @author ivan + */ + public static enum AdditionalOperation { + /** + * Additionally issue open() on the TopComponent containing the InputOutput. + */ + OPEN, + + /** + * Additionally issue requestVisible() on the TopComponent containing the InputOutput. + */ + REQUEST_VISIBLE, + + /** + * Additionally issue requestActive() on the TopComponent containing the InputOutput. + */ + REQUEST_ACTIVE + } + + private static IOSelect find(InputOutput io) { + if (io instanceof Lookup.Provider) { + Lookup.Provider p = (Lookup.Provider) io; + return p.getLookup().lookup(IOSelect.class); + } + return null; + } + + /** + * With a null or empty 'extraOps' simply selects this io + * without involving it's containing TopComponent. + *

+ * If this capability is not supported then regular InputOutput.select() + * will be called. + * @param io InputOutput to operate on. + * @param extraOps Additional operations to apply to the containing + * TopComponent. + */ + public static void select(InputOutput io, EnumSet extraOps) { + IOSelect ios = find(io); + if (ios != null) + ios.select(extraOps); + else + io.select(); // fallback + } + + /** + * Checks whether this feature is supported for provided IO + * @param io IO to check on + * @return true if supported + */ + public static boolean isSupported(InputOutput io) { + return find(io) != null; + } + + /** + * With a null or empty 'extraOps' simply selects this io + * without involving it's containing TopComponent. + * @param extraOps Additional operations to apply to the containing + * TopComponent. + */ + abstract protected void select(EnumSet extraOps); +}