+ Small module containing "Output Window" (main IO container). It provides
+ IOContainer.Provider via service registration. This provider is used
+ by I/O APIs module to create default instance of IOContainer. This default
+ IOContainer is used by IOProvider implementators to access "Output Window"
+ for operation like adding/removing tabs etc.
+
+
+
+
+
+
+
+
+ OW output is tested by functional tests.
+
+
+
+
+
+
+
+
+ XXX no answer for arch-time
+
+
+
+
+
+
+
+
+ The API is represented by service registration of IOContainer.Provider.
+
+
+
+
+
+
+
+
+ Provide "Output Window" for IOProvider implementators.
+
+ Yes, IOContainer.Provider via @ServiceProvider
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ XXX no answer for perf-mem
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ Nothing.
+
+
+
+
+
+
+
+
+ No enforcement.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ Yes. Action/Menu/Shortcut to open "Output Window".
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
+
+
+
+
+ No.
+
+
+
+
diff --git a/core.io.ui/build.xml b/core.io.ui/build.xml
new file mode 100644
--- /dev/null
+++ b/core.io.ui/build.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
diff --git a/core.io.ui/manifest.mf b/core.io.ui/manifest.mf
new file mode 100644
--- /dev/null
+++ b/core.io.ui/manifest.mf
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.core.io.ui/1
+OpenIDE-Module-Implementation-Version: 1
+OpenIDE-Module-Provides: org.openide.windows.IOContainer$Provider
+OpenIDE-Module-Layer: org/netbeans/core/io/ui/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/netbeans/core/io/ui/Bundle.properties
+
diff --git a/core.io.ui/nbproject/project.properties b/core.io.ui/nbproject/project.properties
new file mode 100644
--- /dev/null
+++ b/core.io.ui/nbproject/project.properties
@@ -0,0 +1,44 @@
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2008 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-2006 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.
+
+is.autoload=true
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
+spec.version.base=1.0
diff --git a/core.io.ui/nbproject/project.xml b/core.io.ui/nbproject/project.xml
new file mode 100644
--- /dev/null
+++ b/core.io.ui/nbproject/project.xml
@@ -0,0 +1,45 @@
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ org.netbeans.core.io.ui
+
+
+ org.openide.awt
+
+
+
+ 7.4
+
+
+
+ org.openide.io
+
+
+
+ 1.14
+
+
+
+ org.openide.util
+
+
+
+ 7.20
+
+
+
+ org.openide.windows
+
+
+
+ 6.25
+
+
+
+
+
+
+
+
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/Bundle.properties b/core.io.ui/src/org/netbeans/core/io/ui/Bundle.properties
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/Bundle.properties
@@ -0,0 +1,15 @@
+OpenIDE-Module-Name=I/O UI
+
+#IOWindowAction
+IOWindow=&Output
+
+#Title for I/O window
+LBL_IO_WINDOW=Output
+
+#Format for the I/O window title if it includes the name of the current tab
+FMT_IO_WINDOW={0} - {1}
+
+#IO window tab popup
+LBL_Close=Close Tab
+LBL_CloseAll=Close All Tabs
+LBL_CloseOthers=Close Other Tabs
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
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/IOWindow.java
@@ -0,0 +1,640 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 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]"
+ *
+ * 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 2009 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.core.io.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPopupMenu;
+import javax.swing.JTabbedPane;
+import javax.swing.JToolBar;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.openide.util.Utilities;
+import org.openide.awt.MouseUtils;
+import org.openide.awt.TabbedPaneFactory;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+import org.openide.windows.IOContainer;
+import org.openide.windows.IOContainer.CallBacks;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
+
+
+/**
+ *
+ * @author Tomas Holy
+ */
+@org.openide.util.lookup.ServiceProvider(service=org.openide.windows.IOContainer.Provider.class, position=100)
+public final class IOWindow implements IOContainer.Provider {
+ private static IOWindowImpl impl;
+
+ IOWindowImpl impl() {
+ if (impl == null) {
+ impl = IOWindowImpl.findDefault();
+ }
+ return impl;
+ }
+
+ public void add(JComponent comp, CallBacks cb, Action[] toolbarActions) {
+ impl().addTab(comp, cb, toolbarActions);
+ }
+
+ public JComponent getSelected() {
+ return impl().getSelectedTab();
+ }
+
+ public boolean isActivated() {
+ return impl().isActivated();
+ }
+
+ public void open() {
+ impl().open();
+ }
+
+ public void remove(JComponent comp) {
+ impl().removeTab(comp);
+ }
+
+ public void requestActive() {
+ impl().requestActive();
+ }
+
+ public void requestVisible() {
+ impl().requestVisible();
+ }
+
+ public void select(JComponent comp) {
+ impl().selectTab(comp);
+ }
+
+ public void setIcon(JComponent comp, Icon icon) {
+ impl().setIcon(comp, icon);
+ }
+
+ public void setTitle(JComponent comp, String name) {
+ impl().setTitle(comp, name);
+ }
+
+ public void setToolTipText(JComponent comp, String text) {
+ impl().setToolTipText(comp, text);
+ }
+
+ public boolean isCloseable(JComponent comp) {
+ return true;
+ }
+
+ static final class IOWindowImpl extends TopComponent implements ChangeListener, PropertyChangeListener {
+
+ static IOWindowImpl DEFAULT;
+
+ static synchronized IOWindowImpl findDefault() {
+ if (DEFAULT == null) {
+ TopComponent tc = WindowManager.getDefault().findTopComponent("output"); // NOI18N
+ if (tc != null) {
+ if (tc instanceof IOWindowImpl) {
+ DEFAULT = (IOWindowImpl) tc;
+ } else {
+ //This should not happen. Possible only if some other module
+ //defines different settings file with the same name but different class.
+ //Incorrect settings file?
+ IllegalStateException exc = new IllegalStateException("Incorrect settings file. Unexpected class returned." // NOI18N
+ + " Expected: " + IOWindowImpl.class.getName() // NOI18N
+ + " Returned: " + tc.getClass().getName()); // NOI18N
+ Logger.getLogger(IOWindowImpl.class.getName()).log(Level.WARNING, null, exc);
+ //Fallback to accessor reserved for window system.
+ IOWindowImpl.getDefault();
+ }
+ } else {
+ IOWindowImpl.getDefault();
+ }
+ }
+ return DEFAULT;
+ }
+
+ /* Singleton accessor reserved for window system ONLY. Used by window system to create
+ * IOWindowImpl instance from settings file when method is given. Use findDefault
+ * to get correctly deserialized instance of IOWindowImpl. */
+ public static synchronized IOWindowImpl getDefault() {
+ if (DEFAULT == null) {
+ DEFAULT = new IOWindowImpl();
+ }
+ return DEFAULT;
+ }
+
+ public Object readResolve() throws java.io.ObjectStreamException {
+ return getDefault();
+ }
+
+ private static final String ICON_PROP = "tabIcon"; //NOI18N
+ private static final String TOOLBAR_ACTIONS_PROP = "toolbarActions"; //NOI18N
+ private static final String TOOLBAR_BUTTONS_PROP = "toolbarButtons"; //NOI18N
+ private static final String ICON_RESOURCE = "org/netbeans/core/resources/frames/output.png"; // NOI18N
+ private JTabbedPane pane;
+ private JComponent singleTab;
+ private JToolBar toolbar;
+ private JPopupMenu popupMenu;
+ private Map tabToCb = new HashMap();
+
+ public IOWindowImpl() {
+ pane = TabbedPaneFactory.createCloseButtonTabbedPane();
+ pane.addChangeListener(this);
+ pane.addPropertyChangeListener(TabbedPaneFactory.PROP_CLOSE, this);
+ setFocusable(true);
+
+ toolbar = new JToolBar();
+ toolbar.setOrientation(JToolBar.VERTICAL);
+ toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.Y_AXIS));
+ toolbar.setFloatable(false);
+ Insets ins = toolbar.getMargin();
+ JButton sample = new JButton();
+ sample.setBorderPainted(false);
+ sample.setOpaque(false);
+ sample.setText(null);
+ sample.setIcon(new Icon() {
+
+ public int getIconHeight() {
+ return 16;
+ }
+
+ public int getIconWidth() {
+ return 16;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y) {
+ }
+ });
+ toolbar.add(sample);
+ Dimension buttonPref = sample.getPreferredSize();
+ Dimension minDim = new Dimension(buttonPref.width + ins.left + ins.right, buttonPref.height + ins.top + ins.bottom);
+ toolbar.setMinimumSize(minDim);
+ toolbar.setPreferredSize(minDim);
+ toolbar.remove(sample);
+ setLayout(new BorderLayout());
+ add(toolbar, BorderLayout.WEST);
+ toolbar.setBorder(new VariableRightBorder(pane));
+ toolbar.setBorderPainted(true);
+
+ popupMenu = new JPopupMenu();
+ popupMenu.add(new Close());
+ popupMenu.add(new CloseAll());
+ popupMenu.add(new CloseOthers());
+ pane.addMouseListener(new MouseUtils.PopupMouseAdapter() {
+
+ @Override
+ protected void showPopup(MouseEvent evt) {
+ popupMenu.show(IOWindowImpl.this, evt.getX(), evt.getY());
+ }
+ });
+
+ String name = NbBundle.getMessage(IOWindow.class, "LBL_IO_WINDOW");
+ setDisplayName(name); //NOI18N
+ // setting name to satisfy the accesible name requirement for window.
+ setName(name); //NOI18N
+
+ setIcon(ImageUtilities.loadImage(ICON_RESOURCE)); // NOI18N
+ // special title for sliding mode
+ // XXX - please rewrite to regular API when available - see issue #55955
+ putClientProperty("SlidingName", getDisplayName()); //NOI18N
+ }
+
+ @Override
+ public void open() {
+ super.open();
+ }
+
+ @Override
+ public void requestActive() {
+ super.requestActive();
+ }
+
+ @Override
+ public void requestVisible() {
+ super.requestVisible();
+ }
+
+ boolean activated;
+ public boolean isActivated() {
+ return activated;
+ }
+
+
+ public void addTab(JComponent comp, CallBacks cb, Action[] toolbarActions) {
+ if (toolbarActions != null && toolbarActions.length > 0) {
+ if (toolbarActions.length > 5) {
+ throw new IllegalArgumentException("No more than 5 actions allowed in the output window toolbar"); //NOI18N
+ }
+ comp.putClientProperty(TOOLBAR_ACTIONS_PROP, toolbarActions);
+ }
+ if (cb != null) {
+ tabToCb.put(comp, cb);
+ }
+ setFocusable(false);
+ if (singleTab != null) {
+ // only single tab, remove it from TopComp. and add it to tabbed pane
+ assert pane.getParent() == null;
+ assert pane.getTabCount() == 0;
+ remove(singleTab);
+ pane.add(singleTab);
+ singleTab = null;
+ pane.add(comp);
+ add(pane);
+ updateWindowName(null);
+ updateWindowToolTip(null);
+ } else if (pane.getTabCount() > 0) {
+ // already several tabs
+ assert pane.getParent() != null;
+ assert singleTab == null;
+ pane.add(comp);
+ } else {
+ // nothing yet
+ assert pane.getParent() == null;
+ assert singleTab == null;
+ singleTab = comp;
+ add(comp);
+ updateWindowName(singleTab.getName());
+ updateWindowToolTip(singleTab.getToolTipText());
+ checkTabSelChange();
+ }
+ revalidate();
+ }
+
+ public void removeTab(JComponent comp) {
+ if (singleTab != null) {
+ assert singleTab == comp;
+ remove(singleTab);
+ singleTab = null;
+ updateWindowName(null);
+ updateWindowToolTip(null);
+ checkTabSelChange();
+ setFocusable(true);
+ revalidate();
+ } else if (pane.getParent() == this) {
+ assert pane.getTabCount() > 1;
+ pane.remove(comp);
+ if (pane.getTabCount() == 1) {
+ singleTab = (JComponent) pane.getComponentAt(0);
+ pane.remove(singleTab);
+ remove(pane);
+ add(singleTab);
+ updateWindowName(singleTab.getName());
+ updateWindowToolTip(singleTab.getToolTipText());
+ }
+ revalidate();
+ }
+ CallBacks cb = tabToCb.get(comp);
+ if (cb != null) {
+ cb.closed();
+ }
+ }
+
+ public void selectTab(JComponent comp) {
+ if (!isOpened()) {
+ open();
+ }
+ if (!isShowing()) {
+ requestVisible();
+ }
+ if (singleTab == null) {
+ pane.setSelectedComponent(comp);
+ }
+ }
+
+ public JComponent getSelectedTab() {
+ return singleTab != null ? singleTab : (JComponent) pane.getSelectedComponent();
+ }
+
+ public void setTitle(JComponent comp, String name) {
+ comp.setName(name);
+ if (singleTab != null) {
+ assert singleTab == comp;
+ updateWindowName(name);
+ } else {
+ assert pane.getParent() == this;
+ int idx = pane.indexOfComponent(comp);
+ assert idx >= 0;
+ pane.setTitleAt(idx, name);
+ }
+ }
+
+ public void setToolTipText(JComponent comp, String text) {
+ comp.setToolTipText(text);
+ if (singleTab != null) {
+ assert singleTab == comp;
+ updateWindowToolTip(text);
+ } else {
+ assert pane.getParent() == this;
+ int idx = pane.indexOfComponent(comp);
+ assert idx >= 0;
+ pane.setToolTipTextAt(idx, text);
+ }
+ }
+
+ public void setIcon(JComponent comp, Icon icon) {
+ if (comp == singleTab) {
+ comp.putClientProperty(ICON_PROP, icon);
+ return;
+ }
+ int idx = pane.indexOfComponent(comp);
+ if (idx < 0) {
+ return;
+ }
+ comp.putClientProperty(ICON_PROP, icon);
+ pane.setIconAt(idx, icon);
+ pane.setDisabledIconAt(idx, icon);
+ }
+
+ @Override
+ public int getPersistenceType() {
+ return PERSISTENCE_ALWAYS;
+ }
+
+ @Override
+ public String preferredID() {
+ return "output"; //NOI18N
+ }
+
+ @Override
+ public String getToolTipText() {
+ return getDisplayName();
+ }
+
+ @Override
+ public void processFocusEvent(FocusEvent fe) {
+ super.processFocusEvent(fe);
+ if (Boolean.TRUE.equals(getClientProperty("isSliding"))) { //NOI18N
+ repaint(200);
+ }
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ if (hasFocus()) {
+ Insets ins = getInsets();
+ Color col = UIManager.getColor("controlShadow"); //NOI18N
+ //Draw *some* focus indication
+ if (col == null) {
+ col = java.awt.Color.GRAY;
+ }
+ g.setColor(col);
+ g.drawRect(
+ ins.left + 2,
+ ins.top + 2,
+ getWidth() - (ins.left + ins.right + 4),
+ getHeight() - (ins.top + ins.bottom + 4));
+ }
+ }
+
+ void updateWindowName(String name) {
+ String winName = NbBundle.getMessage(IOWindowImpl.class, "LBL_IO_WINDOW"); //NOI18N
+ if (name != null) {
+ String newName = NbBundle.getMessage(IOWindowImpl.class, "FMT_IO_WINDOW", new Object[]{winName, name}); //NOI18N
+ if (newName.indexOf("") != -1) {
+ newName = Utilities.replaceString(newName, "", ""); //NOI18N
+ setHtmlDisplayName("" + newName); //NOI18N
+ } else {
+ setDisplayName(newName);
+ setHtmlDisplayName(null);
+ }
+ } else {
+ setDisplayName(winName);
+ setHtmlDisplayName(null);
+ }
+
+ }
+
+ void updateWindowToolTip(String toolTipText) {
+ setToolTipText(toolTipText == null ? NbBundle.getMessage(IOWindowImpl.class, "LBL_IO_WINDOW") : toolTipText);
+ }
+
+ private void updateToolbar(JComponent comp) {
+ toolbar.removeAll();
+ if (comp != null) {
+ JButton[] buttons = getTabButtons(comp);
+ for (int i = 0; i < buttons.length; i++) {
+ toolbar.add(buttons[i]);
+ }
+ }
+ toolbar.revalidate();
+ toolbar.repaint();
+ }
+
+ JButton[] getTabButtons(JComponent comp) {
+ JButton[] buttons = (JButton[]) comp.getClientProperty(TOOLBAR_BUTTONS_PROP);
+ if (buttons != null) {
+ return buttons;
+ }
+ Action[] actions = (Action[]) comp.getClientProperty(TOOLBAR_ACTIONS_PROP);
+ if (actions == null) {
+ return new JButton[0];
+ }
+
+ buttons = new JButton[actions.length];
+ for (int i=0; i < buttons.length; i++) {
+ buttons[i] = new JButton(actions[i]);
+ buttons[i].setBorderPainted(false);
+ buttons[i].setOpaque(false);
+ buttons[i].setText(null);
+ buttons[i].putClientProperty("hideActionText", Boolean.TRUE); //NOI18N
+ if (actions[i].getValue (Action.SMALL_ICON) == null) {
+ throw new IllegalStateException ("No icon provided for " + actions[i]); //NOI18N
+ }
+ }
+ return buttons;
+ }
+
+
+
+ @Override
+ protected void componentActivated() {
+ super.componentActivated();
+ activated = true;
+ JComponent comp = getSelectedTab();
+ CallBacks cb = tabToCb.get(comp);
+ if (cb != null) {
+ cb.activated();
+ }
+ }
+
+ @Override
+ protected void componentDeactivated() {
+ super.componentDeactivated();
+ activated = false;
+ JComponent comp = getSelectedTab();
+ CallBacks cb = tabToCb.get(comp);
+ if (cb != null) {
+ cb.deactivated();
+ }
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ checkTabSelChange();
+ }
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (TabbedPaneFactory.PROP_CLOSE.equals(evt.getPropertyName())) {
+ JComponent comp = (JComponent) evt.getNewValue();
+ removeTab(comp);
+ }
+ }
+
+ JComponent lastSelTab;
+ void checkTabSelChange() {
+ JComponent sel = getSelectedTab();
+ if (sel != lastSelTab) {
+ lastSelTab = sel;
+ updateToolbar(sel);
+ }
+ }
+
+ private void closeOtherTabs() {
+ assert pane.getParent() == this;
+ JComponent sel = getSelectedTab();
+ for (int i = 0; i < pane.getTabCount(); i++) {
+ JComponent comp = (JComponent) pane.getComponentAt(0);
+ if (comp != sel) {
+ removeTab(comp);
+ }
+ }
+ }
+
+ private void closeAllTabs() {
+ for (int i = 0; i < pane.getTabCount(); i++) {
+ JComponent comp = (JComponent) pane.getComponentAt(0);
+ removeTab(comp);
+ }
+ }
+
+ private class Close extends AbstractAction {
+
+ public Close() {
+ super(NbBundle.getMessage(IOWindowImpl.class, "LBL_Close"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ removeTab(getSelectedTab());
+ }
+ }
+
+ private class CloseAll extends AbstractAction {
+
+ public CloseAll() {
+ super(NbBundle.getMessage(IOWindowImpl.class, "LBL_CloseAll"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ closeAllTabs();
+ }
+ }
+
+ private class CloseOthers extends AbstractAction {
+
+ public CloseOthers() {
+ super(NbBundle.getMessage(IOWindowImpl.class, "LBL_CloseOthers"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ closeOtherTabs();
+ }
+ }
+
+ private class VariableRightBorder implements Border {
+
+ private JTabbedPane pane;
+
+ public VariableRightBorder(JTabbedPane pane) {
+ this.pane = pane;
+ }
+
+ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+ if (pane.getParent() != IOWindowImpl.this) {
+ Color old = g.getColor();
+ g.setColor(getColor());
+ g.drawLine(x + width - 1, y, x + width - 1, y + height);
+ g.setColor(old);
+ }
+ }
+
+ public Color getColor() {
+ if (Utilities.isMac()) {
+ Color c1 = UIManager.getColor("controlShadow");
+ Color c2 = UIManager.getColor("control");
+ return new Color((c1.getRed() + c2.getRed()) / 2,
+ (c1.getGreen() + c2.getGreen()) / 2,
+ (c1.getBlue() + c2.getBlue()) / 2);
+ } else {
+ return UIManager.getColor("controlShadow");
+ }
+ }
+
+ public Insets getBorderInsets(Component c) {
+ if (pane.getParent() == IOWindowImpl.this) {
+ return new Insets(0, 0, 0, 0);
+ }
+ return new Insets(0, 0, 0, 2);
+ }
+
+ public boolean isBorderOpaque() {
+ return true;
+ }
+ }
+ }
+}
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/IOWindowAction.java b/core.io.ui/src/org/netbeans/core/io/ui/IOWindowAction.java
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/IOWindowAction.java
@@ -0,0 +1,76 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 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]"
+ *
+ * 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 2009 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.core.io.ui;
+
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CallableSystemAction;
+import org.openide.windows.IOContainer;
+
+/** The action which shows standard IO component.
+*
+* @author Tomas Holy
+*/
+public final class IOWindowAction extends CallableSystemAction {
+
+ public void performAction() {
+ IOContainer container = IOContainer.getDefault();
+ container.open();
+ container.requestActive();
+ }
+
+ @Override
+ protected boolean asynchronous() {
+ return false;
+ }
+
+ public String getName() {
+ return NbBundle.getBundle(IOWindowAction.class).getString("IOWindow");
+ }
+
+ public HelpCtx getHelpCtx() {
+ return new HelpCtx(IOWindowAction.class);
+ }
+
+ @Override
+ protected String iconResource() {
+ return "org/netbeans/core/resources/frames/output.png"; // NOI18N
+ }
+}
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/layer.xml b/core.io.ui/src/org/netbeans/core/io/ui/layer.xml
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/layer.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/resources/output.settings b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.settings
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wsmode b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wsmode
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wsmode
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcgrp b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcgrp
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcgrp
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcref b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcref
new file mode 100644
--- /dev/null
+++ b/core.io.ui/src/org/netbeans/core/io/ui/resources/output.wstcref
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/core.output2/manifest.mf b/core.output2/manifest.mf
--- a/core.output2/manifest.mf
+++ b/core.output2/manifest.mf
@@ -3,6 +3,5 @@
OpenIDE-Module-Localizing-Bundle: org/netbeans/core/output2/Bundle.properties
OpenIDE-Module-Implementation-Version: 1
OpenIDE-Module-Provides: org.openide.windows.IOProvider
-OpenIDE-Module-Layer: org/netbeans/core/output2/layer.xml
AutoUpdate-Essential-Module: true
diff --git a/core.output2/nbproject/project.xml b/core.output2/nbproject/project.xml
--- a/core.output2/nbproject/project.xml
+++ b/core.output2/nbproject/project.xml
@@ -99,6 +99,10 @@
unit
+ org.netbeans.core.io.ui
+
+
+ org.netbeans.core.output2
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
@@ -41,50 +41,19 @@
package org.netbeans.core.output2;
-import java.awt.Component;
-import java.awt.Container;
-import java.awt.FileDialog;
-import java.awt.Frame;
-import java.awt.KeyboardFocusManager;
-import java.awt.Point;
-import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.beans.PropertyChangeListener;
import java.io.CharConversionException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import javax.swing.AbstractAction;
+import java.util.HashMap;
+import java.util.Map;
import javax.swing.Action;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JComponent;
-import javax.swing.JFileChooser;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPopupMenu;
-import javax.swing.JSeparator;
-import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.event.PopupMenuEvent;
-import javax.swing.event.PopupMenuListener;
-import javax.swing.text.BadLocationException;
-import org.netbeans.core.output2.ui.AbstractOutputTab;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.actions.FindAction;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
+import org.openide.windows.IOContainer;
import org.openide.windows.OutputEvent;
-import org.openide.windows.OutputListener;
-import org.openide.windows.WindowManager;
import org.openide.xml.XMLUtil;
/**
@@ -95,176 +64,71 @@
* controller. The controller is fully stateless, and stores information of interest in
* the components as appropriate.
*/
-public class Controller { //XXX public only for debug access to logging code
+public class Controller {
public static void ensureViewInDefault (final NbIO io, final boolean reuse) {
Mutex.EVENT.readAccess(new Runnable() {
public void run() {
- OutputWindow.findDefault();
IOEvent evt = new IOEvent (io, IOEvent.CMD_CREATE, reuse);
NbIO.post(evt);
}
});
}
- private static final int ACTION_COPY = 0;
- private static final int ACTION_WRAP = 1;
- private static final int ACTION_SAVEAS = 2;
- private static final int ACTION_CLOSE = 3;
- private static final int ACTION_NEXTERROR = 4;
- private static final int ACTION_PREVERROR = 5;
- private static final int ACTION_SELECTALL = 6;
- private static final int ACTION_FIND = 7;
- private static final int ACTION_FINDNEXT = 8;
- private static final int ACTION_NAVTOLINE = 9;
- private static final int ACTION_POSTMENU = 10;
- private static final int ACTION_FINDPREVIOUS = 11;
- private static final int ACTION_CLEAR = 12;
- private static final int ACTION_NEXTTAB = 13;
- private static final int ACTION_PREVTAB = 14;
-// issue 59447
-// private static final int ACTION_TO_EDITOR = 15;
-
+ static Controller controller;
- //Package private for unit tests
- Action copyAction = new ControllerAction (ACTION_COPY,
- "ACTION_COPY"); //NOI18N
- Action wrapAction = new ControllerAction (ACTION_WRAP,
- "ACTION_WRAP"); //NOI18N
- Action saveAsAction = new ControllerAction (ACTION_SAVEAS,
- "ACTION_SAVEAS"); //NOI18N
- Action closeAction = new ControllerAction (ACTION_CLOSE,
- "ACTION_CLOSE"); //NOI18N
- Action nextErrorAction = new ControllerAction (ACTION_NEXTERROR,
- "ACTION_NEXT_ERROR" ); //NOI18N
- Action prevErrorAction = new ControllerAction (ACTION_PREVERROR,
- "ACTION_PREV_ERROR" ); //NOI18N
- Action selectAllAction = new ControllerAction (ACTION_SELECTALL,
- "ACTION_SELECT_ALL"); //NOI18N
- Action findAction = new ControllerAction (ACTION_FIND,
- "ACTION_FIND"); //NOI18N
- Action findNextAction = new ControllerAction (ACTION_FINDNEXT,
- "ACTION_FIND_NEXT"); //NOI18N
- Action findPreviousAction = new ControllerAction (ACTION_FINDPREVIOUS,
- "ACTION_FIND_PREVIOUS"); //NOI18N
- Action navToLineAction = new ControllerAction (ACTION_NAVTOLINE, "navToLine", //NOI18N
- KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
- Action postMenuAction = new ControllerAction (ACTION_POSTMENU, "postMenu", //NOI18N
- KeyStroke.getKeyStroke(KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK));
- Action clearAction = new ControllerAction (ACTION_CLEAR, "ACTION_CLEAR");
-
- Action nextTabAction = new ControllerAction (ACTION_NEXTTAB, "NextViewAction", //NOI18N
- (KeyStroke)null);
- Action prevTabAction = new ControllerAction (ACTION_PREVTAB, "PreviousViewAction", //NOI18N
- (KeyStroke)null);
-// issue 59447
-// Action toEditorAction = new ControllerAction (ACTION_TO_EDITOR, "ToEditorAction",
-// // if you ever change or remove the shortcut, check the popup hiding hack. in postPopuMenu()
-// KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
+ static Controller getDefault() {
+ if (controller == null) {
+ controller = new Controller();
+ }
+ return controller;
+ }
- private Object[] popupItems = new Object[] {
- copyAction, new JSeparator(), findAction, findNextAction,
- new JSeparator(),
- wrapAction, new JSeparator(), saveAsAction, clearAction, closeAction,
- };
-
- private Action[] kbdActions = new Action[] {
- copyAction, selectAllAction, findAction, findNextAction,
- findPreviousAction, wrapAction, saveAsAction, closeAction,
- navToLineAction, postMenuAction, clearAction, //toEditorAction,
- };
+ private Map ioToTab = new HashMap();
Controller() {}
- private OutputTab createOutputTab (OutputWindow win, NbIO io, boolean activateContainer, boolean reuse) {
- AbstractOutputTab[] ov = win.getTabs();
- OutputTab result = null;
- if (LOG) log ("Find or create component for nbio " + io);
-
- for (int i=0; i < ov.length; i++) {
- OutputTab oc = (OutputTab) ov[i];
- if (oc.getIO() == io) {
- if (LOG) log ("Found an existing tab");
- result = oc;
- break;
- }
- }
- if (result == null) {
- if (LOG) log ("Didn't find an existing open tab, checking hidden tabs");
- OutputTab[] hidden = win.getHiddenTabs();
- for (int i=0; i < hidden.length; i++) {
- OutputTab oc = hidden[i];
- if (hidden[i].getIO() == io) {
- if (LOG) log ("Found a hidden tab with the same IO. Unhiding it for reuse");
- result = oc;
- unhideHiddenView (win, result);
- break;
- }
- }
- }
-
- if (LOG) log ("FindOrCreate: " + io.getName() + " found=" + (result !=
- null) + " for io " + io);
-
- if (result == null) {
- if (LOG) log ("Find or create creating " + io.getName());
- result = createAndInstallView (win, io);
- }
- if (result != null) {
- // install handlers to prev/next actions
- result.getActionMap ().put ("jumpPrev", this.prevErrorAction); // NOI18N
- result.getActionMap ().put ("jumpNext", this.nextErrorAction); // NOI18N
- result.getActionMap ().put (FindAction.class.getName (), this.findAction);
- result.getActionMap ().put (javax.swing.text.DefaultEditorKit.copyAction, this.copyAction);
- }
-
- return result;
+ void eventDispatched(IOEvent ioe) {
+ if (Controller.LOG) Controller.log ("Event received: " + ioe);
+ NbIO io = ioe.getIO();
+ int command = ioe.getCommand();
+ boolean value = ioe.getValue();
+ Object data = ioe.getData();
+ OutputTab comp = ioToTab.get(io);
+ if (Controller.LOG) Controller.log ("Passing command to controller " + ioe);
+ performCommand(io.getIOContainer(), comp, io, command, value, data);
+ ioe.consume();
}
- /**
- * Creates and installs an output view
- *
- * @param win The owning container
- * @param io The IO whose output is to be displayed
- * @return A new OutputTab attached to the passed IO
- */
- private OutputTab createAndInstallView (OutputWindow win, NbIO io) {
- if (LOG) log ("Create and install a new tab for : " + io.getName());
+ private OutputTab createOutputTab(IOContainer ioContainer, NbIO io) {
+ if (LOG) log ("Create component for nbio " + io);
OutputTab result = new OutputTab (io);
result.setName (io.getName() + " ");
Action[] a = io.getToolbarActions();
if (a != null) {
result.setToolbarActions(a);
}
- for (int i=0; i < kbdActions.length; i++) {
- result.installKeyboardAction(kbdActions[i]);
- }
-
- if (LOG) log ("Adding and selecting new tab " + result);
- win.add (result);
+
+ if (LOG) log ("Adding new tab " + result);
+ ioToTab.put(io, result);
+ ioContainer.add(result, result, a);
//Make sure names are boldfaced for all open streams - if the tabbed
- //pane was just added in, it will just have used the name of the
+ //pane was just added in, it will just have used the name of the
//component, which won't contain html
- AbstractOutputTab[] aot = win.getTabs();
- for (int i=0; i < aot.length; i++) {
- updateName(win, (OutputTab) aot[i]);
+ for (OutputTab tab : ioToTab.values()) {
+ updateName(ioContainer, tab);
}
return result;
}
- /**
- * Output views can be hidden by the user invoking close before the output stream for
- * the output has been closed. In this case, they are stored in the OutputWindow,
- * and can be reopened if new output arrives. This method will remove a component
- * from the set of hidden components and re-add it to the component hierarchy.
- *
- * @param win The owning container
- * @param hidden The output component which is hidden but was not closed when it was hidden
- */
- private void unhideHiddenView (OutputWindow win, OutputTab hidden) {
- if (LOG) log ("Unhiding hidden tab for " + hidden.getIO());
- win.add (hidden);
- win.removeHiddenView(hidden);
+ void removeTab(NbIO io) {
+ ioToTab.remove(io);
+ }
+
+ void removeFromUpdater(OutputTab tab) {
+ if (nameUpdater != null) {
+ nameUpdater.remove(tab);
+ }
}
/**
@@ -274,15 +138,16 @@
* technique and the CoalescedNameUpdater to coalesce all name changes - otherwise
* the name change may be delayed.
*
+ * @param ioContainer IOContainer managing tab
* @param tab The component whose name may need adjusting
*/
- private void updateName (OutputWindow win, OutputTab tab) {
+ void updateName(IOContainer ioContainer, OutputTab tab) {
if (nameUpdater == null) {
if (LOG) log ("Update name for " + tab.getIO() + " dispatching a name updater");
- nameUpdater = new CoalescedNameUpdater(win);
+ nameUpdater = new CoalescedNameUpdater();
SwingUtilities.invokeLater(nameUpdater);
}
- nameUpdater.add (tab);
+ nameUpdater.add(ioContainer, tab);
}
private CoalescedNameUpdater nameUpdater = null;
@@ -300,18 +165,12 @@
* queue.
*/
private class CoalescedNameUpdater implements Runnable {
- private Set components = new HashSet();
- private OutputWindow win;
- CoalescedNameUpdater (OutputWindow win) {
- this.win = win;
+ private Map components = new HashMap();
+ CoalescedNameUpdater() {
}
- /**
- * Add a tab whose name should be changed.
- * @param tab The tab
- */
- public void add (OutputTab tab) {
- components.add (tab);
+ public void add(IOContainer ioContainer, OutputTab tab) {
+ components.put(tab, ioContainer);
}
public void remove(OutputTab tab) {
@@ -319,748 +178,43 @@
}
public void run() {
- for (OutputTab t: components) {
+ for (OutputTab t: components.keySet()) {
NbIO io = t.getIO();
+ if (!ioToTab.containsKey(io)) {
+ continue;
+ }
if (LOG) {
log ("Update name for " + io.getName() + " stream " +
"closed is " + io.isStreamClosed());
}
- if (win.isAncestorOf(t)) {
- String escaped;
- try {
- escaped = XMLUtil.toAttributeValue(io.getName());
- } catch (CharConversionException e) {
- escaped = io.getName();
- }
- boolean wasReset = io.checkReset();
- // XXX useHtml name appears to be backwards? -jglick
- boolean useHtml = io.isStreamClosed() && !wasReset;
-
- String name = useHtml ? io.getName() + " " :
- "" + escaped
- + " "; //NOI18N
-
- if (LOG) log (" set name to " + name);
- //#88204 apostophes are escaped in xm but not html
- win.setTabTitle (t, name.replace("'", "'"));
+ String escaped;
+ try {
+ escaped = XMLUtil.toAttributeValue(io.getName());
+ } catch (CharConversionException e) {
+ escaped = io.getName();
}
+ boolean wasReset = io.checkReset();
+ // XXX useHtml name appears to be backwards? -jglick
+ boolean useHtml = io.isStreamClosed() && !wasReset;
+
+ String name = useHtml ? io.getName() + " " : "" + escaped + " "; //NOI18N
+
+ if (LOG) {
+ log(" set name to " + name);
+ }
+ //#88204 apostophes are escaped in xm but not html
+ io.getIOContainer().setTitle(t, name.replace("'", "'"));
}
nameUpdater = null;
}
}
-
- private void forceName(OutputWindow win, OutputTab tab) {
- if (LOG) log ("ForceName ensuring non-html tab name");
- if (nameUpdater != null) {
- if (LOG) log (" an update was queued, aborting it");
- nameUpdater.remove(tab);
- }
- if (win.isAncestorOf(tab)) {
- String escaped;
- try {
- escaped = XMLUtil.toAttributeValue(tab.getIO().getName() + " ");
- } catch (CharConversionException e) {
- escaped = tab.getIO().getName() + " ";
- }
- if (LOG) log (" setting non-html name " + escaped);
- //#88204 apostophes are escaped in xm but not html
- win.setTabTitle (tab, escaped.replace("'", "'"));
- }
- }
-
- /**
- * Called when a ControllerAction is invoked, either by the keyboard or
- * from the popup menu.
- *
- * @param win The output window where it was invoked
- * @param tab The tab it was invoked on
- * @param id The ID of the action
- */
- public void actionPerformed(OutputWindow win, OutputTab tab, int id) {
- switch (id) {
- case ACTION_COPY:
- tab.getOutputPane().copy();
- break;
- case ACTION_WRAP:
- boolean wrapped = tab.getOutputPane().isWrapped();
- tab.getOutputPane().setWrapped(!wrapped);
- break;
- case ACTION_SAVEAS:
- saveAs (tab);
- break;
- case ACTION_CLOSE:
- close (win, tab, false);
- break;
- case ACTION_NEXTERROR:
- sendCaretToError(win, tab, false);
- break;
- case ACTION_PREVERROR:
- sendCaretToError(win, tab, true);
- break;
- case ACTION_SELECTALL:
- tab.getOutputPane().selectAll();
- break;
- case ACTION_FIND:
- int start = tab.getOutputPane().getSelectionStart();
- int end = tab.getOutputPane().getSelectionEnd();
- String str = null;
- if (start > 0 && end > start) {
- try {
- str = tab.getOutputPane().getDocument().getText(start, end - start);
- } catch (BadLocationException ex) {
- ex.printStackTrace();
- }
- }
- FindDialogPanel.showFindDialog(tab.getFindActionListener(findNextAction, findPreviousAction, copyAction), str);
- break;
- case ACTION_FINDNEXT:
- findNext (tab);
- break;
- case ACTION_FINDPREVIOUS :
- findPrevious (tab);
- break;
- case ACTION_NAVTOLINE :
- if (LOG) log ("Action NAVTOLINE received");
- openLineIfError (tab);
- break;
- case ACTION_POSTMENU :
- if (LOG) log ("Action POSTMENU received");
- postPopupMenu(win, tab, new Point(0,0), tab);
- break;
- case ACTION_CLEAR :
- if (LOG) log ("Action CLEAR receieved");
- NbIO io = tab.getIO();
-
- if (io != null) {
- NbWriter writer = io.writer();
- if (writer != null) {
- try {
- if (LOG) log ("Resetting the writer for Clear");
- writer.reset();
- forceName(win, tab);
- } catch (IOException ioe) {
- Exceptions.printStackTrace(ioe);
- }
- } else if (LOG) {
- log ("IO's NbWriter is null");
- }
- } else if (LOG) {
- log ("Clear on a tab with no IO");
- }
- break;
- case ACTION_NEXTTAB :
- if (LOG) log ("Action NEXTTAB received");
- win.selectNextTab(tab);
- break;
- case ACTION_PREVTAB :
- if (LOG) log ("Action PREVTAB received");
- win.selectPreviousTab(tab);
- break;
-// #issue 59447
-// case ACTION_TO_EDITOR :
-// if (log) log ("Action TO_EDITOR received"); //NOI18N
-// Mode m = WindowManager.getDefault().findMode ("editor"); //NOI18N
-// if (m != null) {
-// TopComponent tc = m.getSelectedTopComponent();
-// if (tc != null) {
-// tc.requestActive();
-// }
-// }
-// break;
-
- default :
- assert false;
- }
- }
-
- /**
- * Called when a line is clicked - if an output listener is listening on that
- * line, it will be sent outputLineAction.
- * @param tab
- */
- private void openLineIfError(OutputTab tab) {
- OutWriter out = tab.getIO().out();
- if (out != null) {
- int line = tab.getOutputPane().getCaretLine();
- OutputListener lis = out.getLines().getListenerForLine(line);
- if (lis != null) {
- if (LOG) log (" Sending action for getLine " + line);
- ignoreCaretChanges = true;
- tab.getOutputPane().sendCaretToLine(line, true);
- ignoreCaretChanges = false;
- ControllerOutputEvent coe = new ControllerOutputEvent (tab.getIO(), line);
- lis.outputLineAction(coe);
- }
- }
- }
-
-
-
- /**
- * Find the next match for the previous search contents, starting at
- * the current caret position.
- *
- * @param tab The tab
- */
- private void findNext (OutputTab tab) {
- OutWriter out = tab.getIO().out();
- if (out != null) {
- String lastPattern = FindDialogPanel.getPanel().getPattern();
- if (lastPattern != null) {
- out.getLines().find(lastPattern);
- }
- Matcher matcher = out.getLines().getForwardMatcher();
- int pos = tab.getOutputPane().getCaretPos();
- if (pos >= tab.getOutputPane().getLength() || pos < 0) {
- pos = 0;
- }
-
- if (matcher != null && matcher.find (pos)) {
- tab.getOutputPane().setSelection(matcher.start(), matcher.end());
- copyAction.setEnabled(true);
- } else {
- Toolkit.getDefaultToolkit().beep();
- }
- }
- }
-
- /**
- * Find the match before the current caret position, using the previously
- * searched for value.
- *
- * @param tab The tab
- */
- private void findPrevious (OutputTab tab) {
- OutWriter out = tab.getIO().out();
- if (out != null) {
- String lastPattern = FindDialogPanel.getPanel().getPattern();
- if (lastPattern != null) {
- out.getLines().find(lastPattern);
- }
- Matcher matcher = out.getLines().getReverseMatcher();
-
- int length = tab.getOutputPane().getLength();
- int pos = length - tab.getOutputPane().getSelectionStart();
-
- if (pos >= tab.getOutputPane().getLength()-1 || pos < 0) {
- pos = 0;
- }
- if (LOG) log ("Reverse search from " + pos);
- if (matcher != null && matcher.find (pos)) {
- int start = length - matcher.end();
- int end = length - matcher.start();
- tab.getOutputPane().setSelection(start, end);
- copyAction.setEnabled(true);
- } else {
- Toolkit.getDefaultToolkit().beep();
- }
- }
- }
-
- /**
- * Update the enabled state of the actions based on the state of the passed
- * tab. If the tab is not currently selected, does nothing.
- *
- * @param win The output window
- * @param tab The tab, presumably the selected one
- */
- private void updateActions (OutputWindow win, OutputTab tab) {
- if (tab == win.getSelectedTab()) {
- OutputPane pane = (OutputPane) tab.getOutputPane();
- int len = pane.getLength();
- boolean enable = len > 0;
- findAction.setEnabled (enable);
- OutWriter out = tab.getIO().out();
-// findNextAction.setEnabled (out != null && out.getLines().getForwardMatcher() != null);
-// findPreviousAction.setEnabled (out != null && out.getLines().getForwardMatcher() != null);
- saveAsAction.setEnabled (enable);
- selectAllAction.setEnabled(enable);
- copyAction.setEnabled(pane.hasSelection());
- boolean hasErrors = out == null ? false : out.getLines().firstListenerLine() != -1;
- nextErrorAction.setEnabled(hasErrors);
- prevErrorAction.setEnabled(hasErrors);
- }
- }
-
- /**
- * Close the tab. If programmatic is false and it is the last
- * tab, the output window will be closed as well.
- *
- * @param win The owning output window
- * @param tab The tab
- * @param programmatic False if the user requested the tab to be closed
- */
- public void close(OutputWindow win, OutputTab tab, boolean programmatic) {
- //NotifyRemoved callback will take care of putting it into the hidden view list if
- //its output is still open.
- Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
- boolean hadFocus = focusOwner != null && (focusOwner == win || win.isAncestorOf(focusOwner));
-
- win.remove(tab); //Triggers a call to notifyRemoved()
- boolean winClosed = false;
- if (!programmatic && win.getTabs().length == 0) {
- if (LOG) log ("Last tab closed by user, closing output window.");
- win.close();
- winClosed = true;
- }
- if (hadFocus) {
- if (!winClosed && win.getSelectedTab() != null) {
- if (LOG) log ("Trying to send focus to the newly selected tab");
- win.getSelectedTab().requestFocus();
- }
- }
- if (LOG) log ("Close received, removing " + tab + " from component");
- }
-
- /**
- * Holds the last written to directory for the save as file chooser.
- */
- private static String lastDir = null;
-
- /**
- * Invokes a file dialog and if a file is chosen, saves the output to
- * that file.
- *
- * @param tab The tab
- */
- private void saveAs(OutputTab tab) {
- OutWriter out = tab.getIO().out();
- if (out == null) {
- return;
- }
- File f = showFileChooser (tab);
- if (f != null) {
- try {
- synchronized (out) {
- out.getLines().saveAs(f.getPath());
- }
- } catch (IOException ioe) {
- NotifyDescriptor notifyDesc = new NotifyDescriptor(
- NbBundle.getMessage(Controller.class, "MSG_SaveAsFailed", f.getPath()),
- NbBundle.getMessage(Controller.class, "LBL_SaveAsFailedTitle"),
- NotifyDescriptor.DEFAULT_OPTION,
- NotifyDescriptor.ERROR_MESSAGE,
- new Object[] {NotifyDescriptor.OK_OPTION},
- NotifyDescriptor.OK_OPTION);
-
- DialogDisplayer.getDefault().notify(notifyDesc);
- }
- }
- }
-
- /**
- * Shows a file dialog and an overwrite dialog if the file exists, returning
- * null if the user chooses not to overwrite. Will use an AWT FileDialog for
- * Aqua, per Apple UI guidelines.
- *
- * @param owner A parent component for the dialog - the top level ancestor will
- * actually be used so positioning is correct
- * @return A file to write to
- */
- private static File showFileChooser (JComponent owner) {
- File f = null;
- String dlgTtl = NbBundle.getMessage (Controller.class, "TITLE_SAVE_DLG"); //NOI18N
-
- boolean isAqua = "Aqua".equals(UIManager.getLookAndFeel().getID()); //NOI18N
-
- if (isAqua) {
- //Apple UI guidelines recommend against ever using JFileChooser
- FileDialog fd = new FileDialog((Frame) owner.getTopLevelAncestor(), dlgTtl, FileDialog.SAVE);
- if (lastDir != null && new File (lastDir).exists()) {
- fd.setDirectory(lastDir);
- }
- fd.setModal(true);
- fd.setVisible(true);
- String s = fd.getDirectory() + fd.getFile();
- f = new File(s);
- if (f.exists() && f.isDirectory()) {
- f = null;
- }
- } else {
- JFileChooser jfc = new JFileChooser();
- if (lastDir != null && new File(lastDir).exists()) {
- File dir = new File (lastDir);
- if (dir.exists()) {
- jfc.setCurrentDirectory(dir);
- }
- }
- jfc.setName(dlgTtl);
- jfc.setDialogTitle(dlgTtl);
-
- if (jfc.showSaveDialog(owner.getTopLevelAncestor()) == JFileChooser.APPROVE_OPTION) {
- f = jfc.getSelectedFile();
- }
- }
-
- if (f != null && f.exists() && !isAqua) { //Aqua's file dialog takes care of this
- String msg = NbBundle.getMessage(Controller.class,
- "FMT_FILE_EXISTS", new Object[] { f.getName() }); //NOI18N
- String title = NbBundle.getMessage(Controller.class,
- "TITLE_FILE_EXISTS"); //NOI18N
- if (JOptionPane.showConfirmDialog(owner.getTopLevelAncestor(), msg, title,
- JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) {
- f = null;
- }
- }
- if (f != null) {
- lastDir = f.getParent();
- }
- return f;
- }
-
- /**
- * Called when the selected component is changed in an output container.
- *
- * @param win The owning container
- * @param former The previously selected output view, or null
- * @param current The newly selected output view, or null
- */
- public void selectionChanged(OutputWindow win, OutputTab former,
- OutputTab current) {
- if (former != null) {
- former.updateTimestamp();
- }
- if (current != null) {
- current.updateTimestamp();
- updateActions (win, current);
- }
- }
-
- /**
- * Messaged when the container becomes activated in the netbeans window system
- * @param win The container
- */
- public void notifyActivated(OutputWindow win) {
- OutputTab tab = (OutputTab) win.getSelectedTab();
- if (tab != null) {
- updateActions (win, tab);
- }
- }
-
- /**
- * Sends the caret in a tab to the nearest error line to its current position, selecting
- * that line.
- *
- * @param win The output window
- * @param tab the tab
- * @param backward If the search should be done in reverse
- */
- private void sendCaretToError(OutputWindow win, OutputTab tab, boolean backward) {
- if (tab == null) {
- //We're being invoked from SystemAction via main menu - no associated component
- tab = (OutputTab) win.getSelectedTab();
- if (tab == null) {
- return;
- }
- }
- OutWriter out = tab.getIO().out();
- if (out != null) {
- int line = tab.getOutputPane().getCaretLine();
- if (!tab.getOutputPane().isLineSelected(line)) {
- line += backward ? 1 : -1;
- }
-
- if (line >= tab.getOutputPane().getLineCount()-1) {
- line = 0;
- }
- //FirstF12: #48485 - caret is already on the first listener line,
- //so F12 jumps to the second error. So search from 0 the first time after a reset
- int newline = out.getLines().nearestListenerLine(line, backward);
- if (LOG) {
- log ("sendCaretToError - caret line: " + line +
- " nearest listener line " + newline);
- }
- if (newline == line) {
- if (!backward && line != tab.getOutputPane().getLineCount()) {
- newline = out.getLines().nearestListenerLine(line+1, backward);
- } else if (backward && line > 0) {
- newline = out.getLines().nearestListenerLine(line-1, backward);
- } else {
- return;
- }
- }
- if (newline != -1) {
- if (LOG)
- log("Sending caret to error line " + newline);
- tab.getOutputPane().sendCaretToLine(newline, true);
- if (!win.isActivated()) {
- OutputListener l = out.getLines().getListenerForLine(newline);
-
- ControllerOutputEvent ce = new ControllerOutputEvent (tab.getIO(), newline);
- l.outputLineAction(ce);
- }
- }
- }
- }
-
- /**
- * Called when an output tab has been removed from the component hierarchy.
- * If its io is not closed, holds a reference to it in a list of closed
- * tabs, re-showing it on request, or finally disposing its IO and
- * releasing it if it has not been shown again.
- */
- public void notifyRemoved(OutputTab tab) {
- assert SwingUtilities.isEventDispatchThread();
- if (LOG) log ("Tab " + tab + " has been CLOSED. Disposing its IO.");
- NbIO io = tab.getIO();
- if (io != null) {
- io.setClosed(true);
- }
- NbWriter w = io.writer();
- if (w != null && w.isClosed()) {
- //Will dispose the document
- tab.setDocument(null);
- } else if (w != null) {
- //Something is still writing to the stream, but we're getting rid of the tab. Don't dispose
- //the writer, just kill the tab's document
- tab.getDocument().disposeQuietly();
- }
- }
-
- /**
- * Called when input has been sent by the user via the input component
- *
- * @param win The output window
- * @param tab The tab component
- * @param txt The input entered
- */
- public void notifyInput(OutputWindow win, OutputTab tab, String txt) {
- if (Controller.LOG) Controller.log ("Notify input on " + tab + " - " + txt);
- NbIO io = tab.getIO();
- if (io != null) {
- NbIO.IOReader in = io.in();
- if (in != null) {
- if (Controller.LOG) Controller.log ("Sending input to " + in);
-
- in.pushText (txt + "\n");
- //#56070 - copy input to output, TODO - make it more different color..
- io.getOut().println(txt);
- }
- }
- }
-
- /**
- * Fetch the output listener for a given line in a given tab
- *
- * @param tab The output tab
- * @param line The line to find a listener on
- * @return An output listener or null
- */
- private OutputListener listenerForLine (OutputTab tab, int line) {
- OutWriter out = tab.getIO().out();
- if (out != null) {
- return out.getLines().getListenerForLine(line);
- }
- return null;
- }
-
- /**
- * Called when the user has clicked a line in the text view
- * @param win The output window
- * @param tab The tab
- * @param line The line which was clicked
- */
- public void lineClicked(OutputWindow win, OutputTab tab, int line) {
- OutputListener l = listenerForLine (tab, line);
- if (l != null) {
- ControllerOutputEvent oe = new ControllerOutputEvent (tab.getIO(), line);
- l.outputLineAction(oe);
- //Select the text on click
- tab.getOutputPane().sendCaretToLine(line, true);
- }
- }
-
- /**
- * Post the output window's popup menu
- *
- * @param win The output window
- * @param tab The tab
- * @param p The point clicked
- * @param src The source of the click event
- */
- public void postPopupMenu(OutputWindow win, OutputTab tab, Point p, Component src) {
- if (LOG) {
- log ("post popup menu for " + tab.getName());
- }
- JPopupMenu popup = new JPopupMenu();
- popup.putClientProperty ("container", win); //NOI18N
- popup.putClientProperty ("component", tab); //NOI18N
- Action[] a = tab.getToolbarActions();
- if (a.length > 0) {
- boolean added = false;
- for (int i=0; i < a.length; i++) {
- if (a[i].getValue(Action.NAME) != null) {
- // add the proxy that doesn't show icons #67451
- popup.add (new ProxyAction(a[i]));
- added = true;
- }
- }
- if (added) {
- popup.add (new JSeparator());
- }
- }
- for (int i=0; i < popupItems.length; i++) {
- if (popupItems[i] instanceof JSeparator) {
- popup.add ((JSeparator) popupItems[i]);
- } else {
- if (popupItems[i] != wrapAction) {
- JMenuItem item = popup.add((Action) popupItems[i]);
- if (popupItems[i] == findAction) {
- item.setMnemonic(KeyEvent.VK_F);
- }
- } else {
- JCheckBoxMenuItem item =
- new JCheckBoxMenuItem((Action) popupItems[i]);
-
- item.setSelected(tab.getOutputPane().isWrapped());
- popup.add (item);
- }
- }
- }
- // hack to remove the esc keybinding when doing popup..
- KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
- JComponent c = tab.getOutputPane().getTextView();
- Object escHandle = c.getInputMap().get(esc);
- c.getInputMap().remove(esc);
- tab.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(esc);
-
- popup.addPopupMenuListener(new PMListener(popupItems, escHandle));
- popup.show(src, p.x, p.y);
-
- }
-
- private static class ProxyAction implements Action {
- private Action orig;
- ProxyAction(Action original) {
- orig = original;
- }
-
- public Object getValue(String key) {
- if (Action.SMALL_ICON.equals(key)) {
- return null;
- }
- return orig.getValue(key);
- }
-
- public void putValue(String key, Object value) {
- orig.putValue(key, value);
- }
-
- public void setEnabled(boolean b) {
- orig.setEnabled(b);
- }
-
- public boolean isEnabled() {
- return orig.isEnabled();
- }
-
- public void addPropertyChangeListener(PropertyChangeListener listener) {
- orig.addPropertyChangeListener(listener);
- }
-
- public void removePropertyChangeListener(PropertyChangeListener listener) {
- orig.removePropertyChangeListener(listener);
- }
-
- public void actionPerformed(ActionEvent e) {
- orig.actionPerformed(e);
- }
- }
-
- /**
- * #47166 - a disposed tab which has had its popup menu shown remains
- * referenced through PopupItems->JSeparator->PopupMenu->Invoker->OutputPane->OutputTab
- */
- private static class PMListener implements PopupMenuListener {
- private Object[] popupItems;
- private Object handle;
- PMListener (Object[] popupItems, Object escHandle) {
- this.popupItems = popupItems;
- handle = escHandle;
- }
-
- public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
- JPopupMenu popup = (JPopupMenu) e.getSource();
- popup.removeAll();
- popup.setInvoker(null);
- // hack
- AbstractOutputTab tab = (AbstractOutputTab)popup.getClientProperty("component");
- KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
- JComponent c = tab.getOutputPane().getTextView();
- c.getInputMap().put(esc, handle);
- tab.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(esc, handle);
-
- //hack end
- popup.putClientProperty ("container", null); //NOI18N
- popup.putClientProperty ("component", null); //NOI18N
- popup.removePopupMenuListener(this);
- for (int i=0; i < popupItems.length; i++) {
- if (popupItems[i] instanceof ControllerAction) {
- ((ControllerAction) popupItems[i]).clearListeners();
- }
- }
- }
-
- public void popupMenuCanceled(PopupMenuEvent e) {
- popupMenuWillBecomeInvisible(e);
- }
-
- public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
- //do nothing
- }
- }
-
- /**
- * Called when the text caret has changed lines - will call OutputListener.outputLineSelected if
- * there is a listener for that line.
- *
- * @param tab The output tab
- * @param line The line the caret is in
- */
- public void caretEnteredLine(OutputTab tab, int line) {
- if (!ignoreCaretChanges) {
- OutputListener l = listenerForLine (tab, line);
- if (LOG) {
- log ("Caret entered line " + line + " notifying listener " + l);
- }
- if (l != null) {
- ControllerOutputEvent oe = new ControllerOutputEvent (tab.getIO(), line);
- l.outputLineSelected(oe);
- }
- } else {
- if (LOG) {
- log ("Caret entered line " + line + " which has no listener");
- }
- }
- }
-
- /**
- * Called when an event has been received from the document (indicating that new
- * output has been appended. Handles InputOutput.isFocusTaken(), and updates the
- * tab title in the case the stream has been closed, and updates the actions if
- * it is the selected tab.
- *
- * @param win
- * @param tab
- */
- public void documentChanged(OutputWindow win, OutputTab tab) {
- if (tab.getIO().isFocusTaken()) {
- //Not at all sure that isFocusTaken() is a terribly bright idea to begin with
- win.setSelectedTab(tab);
- win.requestVisible();
- }
- updateName(win, tab);
- if (tab == win.getSelectedTab() && win.isActivated()) {
- updateActions(win, tab);
- }
- }
/**
* Handles IOEvents posted into the AWT Event Queue by NbIO instances whose methods have
* been called, as received by an OutputTab which has identified the event as being
* intended for it.
*
- * @param win The output container owning the IO, or in the case of CMD_CREATE, the
+ * @param ioContainer The output container owning the IO, or in the case of CMD_CREATE, the
* one that received the event
* @param tab The output component associated with this IO, if any
* @param io The IO which originated the event
@@ -1068,61 +222,48 @@
* @param value The boolean value of the command, if pertinent
* @param data The data associated with the command, if pertinent
*/
- public void performCommand(OutputWindow win, OutputTab tab, NbIO io, int command,
+ public void performCommand(IOContainer ioContainer, OutputTab tab, NbIO io, int command,
boolean value, Object data) {
if (LOG) {
log ("PERFORMING: " + IOEvent.cmdToString(command) + " value=" + value + " on " + io + " tob " + tab);
}
- OutWriter out = io.out();
-
switch (command) {
case IOEvent.CMD_CREATE :
- createOutputTab(win, io, io.isFocusTaken(), value);
+ createOutputTab(ioContainer, io);
break;
case IOEvent.CMD_INPUT_VISIBLE :
if (value && tab == null) {
- tab = createOutputTab(win, io, io.isFocusTaken(), value);
+ tab = createOutputTab(ioContainer, io);
}
if (tab != null) {
tab.setInputVisible(value);
- win.setSelectedTab(tab);
+ ioContainer.select(tab);
}
break;
case IOEvent.CMD_SELECT :
if (tab == null) {
- tab = createOutputTab(win, io, io.isFocusTaken(), value);
+ tab = createOutputTab(ioContainer, io);
}
- if (!win.isOpened()) {
- win.open();
+ ioContainer.open();
+ if (io.isFocusTaken()) {
+ ioContainer.requestActive();
+ } else {
+ ioContainer.requestVisible();
}
- if (io.isFocusTaken()) {
- win.requestActive();
- } else {
- win.requestVisible();
- }
- if (win.getSelectedTab() != tab) {
- if (tab.getParent() == null) {
- //It was hidden
- win.add(tab);
- }
- win.setSelectedTab(tab);
- updateName(win,tab);
- }
+ ioContainer.select(tab);
break;
case IOEvent.CMD_SET_TOOLBAR_ACTIONS :
if (tab == null && data != null) {
- tab = createOutputTab(win, io, io.isFocusTaken(), value);
+ tab = createOutputTab(ioContainer, io);
}
Action[] a = (Action[]) data;
tab.setToolbarActions(a);
break;
case IOEvent.CMD_CLOSE :
if (tab != null) {
- close(win, tab, true);
- win.revalidate();
- win.repaint();
+ ioContainer.remove(tab);
} else {
io.dispose();
}
@@ -1135,193 +276,32 @@
io.out().dispose();
}
} else {
- if (tab.getParent() != null) {
- updateName(win, tab);
- if (tab.getIO().out() != null && tab.getIO().out().getLines().firstListenerLine() == -1) {
- tab.getOutputPane().ensureCaretPosition();
- }
- if (tab == win.getSelectedTab()) {
- updateActions (win, tab);
- }
- } else {
- //The tab had been kept around to be re-shown, but now the stream is closed, dispose it
- win.removeHiddenView(tab);
- if (io.out() != null) {
- io.out().dispose();
- }
+ updateName(ioContainer, tab);
+ if (tab.getIO().out() != null && tab.getIO().out().getLines().firstListenerLine() == -1) {
+ tab.getOutputPane().ensureCaretPosition();
+ }
+ if (tab == ioContainer.getSelected()) {
+ tab.updateActions();
}
}
} else {
if (tab != null && tab.getParent() != null) {
- updateName(win, tab);
+ updateName(ioContainer, tab);
}
}
break;
case IOEvent.CMD_RESET :
if (tab == null) {
if (LOG) log ("Got a reset on an io with no tab. Creating a tab.");
- performCommand (win, null, io, IOEvent.CMD_CREATE, value, data);
- win.requestVisible();
+ performCommand (ioContainer, null, io, IOEvent.CMD_CREATE, value, data);
+ ioContainer.requestVisible();
return;
}
if (LOG) log ("Setting io " + io + " on tab " + tab);
-// tab.setDocument (new OutputDocument((OutWriter)io.getOut()));
- tab.setIO(io);
- win.setSelectedTab(tab);
- updateName(win, tab);
- // Undesirable in practice: win.requestVisibleForNewTab();
+ tab.reset();
+ updateName(ioContainer, tab);
if (LOG) log ("Reset on " + tab + " tab displayable " + tab.isDisplayable() + " io " + io + " io.out " + io.out());
break;
- case IOEvent.CMD_ICON :
- win.setTabIcon(tab, io.getIcon());
- break;
- }
- }
-
- /**
- * Called when the output stream has been closed, to navigate to the
- * first line which shows an error (if any).
- *
- * @param comp The output component whose IO's stream has been closed.
- */
- private void navigateToFirstErrorLine (OutputTab comp) {
- OutWriter out = comp.getIO().out();
- if (out != null) {
- int line = comp.getFirstNavigableListenerLine();
- if (Controller.LOG) Controller.log ("NAV TO FIRST LISTENER LINE: " + line);
- if (line > 0) {
- comp.getOutputPane().sendCaretToLine (line, false);
- if (isSDI(comp)) {
- comp.requestActive();
- }
- }
- }
- }
-
-
- private static boolean isSDI (OutputTab comp) {
- Container c = comp.getTopLevelAncestor();
- return (c != WindowManager.getDefault().getMainWindow());
- }
-
- /**
- * Flag used to block navigating the editor to the first error line when
- * selecting the error line in the output window after a build (or maybe
- * it should navigate the editor there? Could be somewhat rude...)
- */
- boolean ignoreCaretChanges = false;
-
- void hasSelectionChanged(OutputWindow outputWindow, OutputTab tab, boolean val) {
- if (tab == outputWindow.getSelectedTab()) {
- copyAction.setEnabled(val);
- selectAllAction.setEnabled(!tab.getOutputPane().isAllSelected());
- }
- }
-
- void hasOutputListenersChanged(OutputWindow win, OutputTab tab, boolean hasOutputListeners) {
- if (hasOutputListeners && tab.getOutputPane().isScrollLocked()) {
- navigateToFirstErrorLine(tab);
- }
- }
-
- /**
- * A stateless action which will find the owning OutputTab's controller and call
- * actionPerformed with its ID as an argument.
- */
- private static class ControllerAction extends AbstractAction {
- private int id;
- /**
- * Create a ControllerAction with the specified action ID (constants defined in Controller),
- * using the specified bundle key. Expects the following contents in the bundle:
- *
- *
A name for the action matching the passed key
- *
An accelerator for the action matching [key].accel
- *
- * @param id An action ID
- * @param bundleKey A key for the bundle associated with the Controller class
- * @see org.openide.util.Utilities#stringToKey
- */
- ControllerAction (int id, String bundleKey) {
- if (bundleKey != null) {
- String name = NbBundle.getMessage(Controller.class, bundleKey);
- KeyStroke accelerator = getAcceleratorFor(bundleKey);
- this.id = id;
- putValue (NAME, name);
- putValue (ACCELERATOR_KEY, accelerator);
- }
- }
-
- /**
- * Create a ControllerAction with the specified ID, name and keystroke. Actions created
- * using this constructor will not be added to the popup menu of the component.
- *
- * @param id The ID
- * @param name A programmatic name for the item
- * @param stroke An accelerator keystroke
- */
- ControllerAction (int id, String name, KeyStroke stroke) {
- this.id = id;
- putValue (NAME, name);
- putValue (ACCELERATOR_KEY, stroke);
- }
-
- void clearListeners() {
- PropertyChangeListener[] l = changeSupport.getPropertyChangeListeners();
- for (int i=0; i < l.length; i++) {
- removePropertyChangeListener (l[i]);
- }
- }
-
- /**
- * Get a keyboard accelerator from the resource bundle, with special handling
- * for the mac keyboard layout.
- *
- * @param name The bundle key prefix
- * @return A keystroke
- */
- private static KeyStroke getAcceleratorFor (String name) {
- String key = name + ".accel"; //NOI18N
- if (Utilities.isMac()) {
- key += ".mac"; //NOI18N
- }
- return Utilities.stringToKey(NbBundle.getMessage(Controller.class, key));
- }
-
- public int getID() {
- return id;
- }
-
- public void actionPerformed(ActionEvent e) {
- if (LOG) log ("ACTION PERFORMED: " + getValue(NAME));
- Component c = (Component) e.getSource();
-
- OutputTab outComp = c instanceof OutputTab ? (OutputTab) c :
- c instanceof OutputWindow ? null :
- (OutputTab) SwingUtilities.getAncestorOfClass(OutputTab.class, c);
-
- OutputWindow win= c instanceof OutputWindow ? (OutputWindow) c :
- (OutputWindow) SwingUtilities.getAncestorOfClass(OutputWindow.class, outComp);
-
- if (win == null) {
- win = OutputWindow.findDefault();
- }
- if (outComp == null && win != null) {
- outComp = (OutputTab) win.getSelectedTab();
- }
-
- if (win == null && outComp == null) {
- //For popup menus, we store the component they were invoked over in
- //client properties
- JPopupMenu jpm = (JPopupMenu) SwingUtilities.getAncestorOfClass (JPopupMenu.class, c);
- if (jpm != null) {
- win = (OutputWindow) jpm.getClientProperty ("win"); //NOI18N
- outComp = (OutputTab) jpm.getClientProperty ("component"); //NOI18N
- }
- }
- Controller cont = win.getController();
- if (cont != null) {
- cont.actionPerformed (win, outComp, getID());
- }
}
}
@@ -1426,14 +406,5 @@
}
return logStream;
}
-
- void inputEof(OutputTab tab) {
- if (Controller.LOG) Controller.log ("Input EOF");
- NbIO io = tab.getIO();
- NbIO.IOReader in = io.in();
- if (in != null) {
- in.eof();
- }
- }
}
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
@@ -41,7 +41,6 @@
package org.netbeans.core.output2;
import java.awt.*;
-import java.util.Arrays;
/**
* An event type which carries data about an operation performed on an
@@ -124,38 +123,11 @@
* Set the toolbar actions that should be displayed.
*/
static final int CMD_SET_TOOLBAR_ACTIONS = 10;
- /**
- * XXX may not be supported - dispose of the default output window instance
- */
- static final int CMD_DETACH = 11;
- /**
- * change the icon on the tab..
- */
- static final int CMD_ICON = 12;
-
-
- /**
- * Array of IDs for checking legal values and generating a string representing the event.
- */
- private static final int[] IDS = new int[] {
- CMD_CREATE,
- CMD_OUTPUT_VISIBLE,
- CMD_INPUT_VISIBLE,
- CMD_ERR_VISIBLE,
- CMD_ERR_SEPARATED,
- CMD_FOCUS_TAKEN,
- CMD_SELECT,
- CMD_CLOSE,
- CMD_STREAM_CLOSED,
- CMD_RESET,
- CMD_SET_TOOLBAR_ACTIONS,
- CMD_DETACH,
- CMD_ICON
- };
+ private static final int CMD_LAST = 11;
/**
- * Strings matching the values in the IDS array for generating a string representing the event.
+ * Strings representing the event.
*/
private static final String[] CMDS = new String[] {
"CREATE", //NOI18N
@@ -169,7 +141,6 @@
"STREAM_CLOSED", //NOI18N
"RESET", //NOI18N
"SET_TOOLBAR_ACTIONS", //NOI18N
- "DETACH" //NOI18N
};
/**
@@ -198,7 +169,7 @@
IOEvent(NbIO source, int command, boolean value) {
//Null source only for destroying the default instance
super(source == null ? new Object() : source, command + IO_EVENT_MASK);
- assert Arrays.binarySearch (IDS, command) >= 0 : "Unknown command: " + command; //NOI18N
+ assert command >= 0 && command < CMD_LAST : "Unknown command: " + command; //NOI18N
consumed = false;
this.value = value;
pendingCount++;
@@ -260,6 +231,7 @@
*
* @return If the event is consumed
*/
+ @Override
public boolean isConsumed() {
return consumed;
}
@@ -268,10 +240,12 @@
* Overridden to avoid a bit of work AWTEvent does that's not
* necessary for us.
*/
+ @Override
public void consume() {
consumed = true;
}
+ @Override
public String toString() {
return "IOEvent@" + System.identityHashCode(this) + "-" +
cmdToString(getCommand()) + " on " + getIO() +
@@ -279,20 +253,11 @@
}
public void dispatch() {
- //The only thing needed to make this package fully reentrant (capable of
- //supporting multiple output windows, FWIW) is to replace this line with
- //iterating a registry of OutputContainers, and calling eventDispatched on each.
-
- //Null check below so that if the module has been disabled (the only way
- //this can be null), the dead module doesn't reopen its output window
- if (OutputWindow.DEFAULT != null) {
- //Can be null after CMD_DETACH
- OutputWindow.DEFAULT.eventDispatched(this);
- }
+ Controller.getDefault().eventDispatched(this);
pendingCount--;
}
public static String cmdToString (int cmd) {
- return CMDS[Arrays.binarySearch(IDS, cmd)];
+ return CMDS[cmd];
}
}
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
@@ -49,6 +49,7 @@
import java.io.IOException;
import java.io.Reader;
import org.openide.util.Exceptions;
+import org.openide.windows.IOContainer;
/** Implementation of InputOutput. Implements calls as a set of
* "commands" which are passed up to Dispatcher to be run on the event
@@ -59,7 +60,7 @@
class NbIO implements InputOutput {
private Boolean focusTaken = null;
- private Boolean closed = null;
+ private boolean closed = false;
private final String name;
private Action[] actions;
@@ -68,13 +69,17 @@
private Icon icon;
+ private IOContainer ioContainer;
+
/** Creates a new instance of NbIO
* @param name The name of the IO
* @param toolbarActions an optional set of toolbar actions
+ * @param iowin parent container accessor (null for default)
*/
- NbIO(String name, Action[] toolbarActions) {
+ NbIO(String name, Action[] toolbarActions, IOContainer ioContainer) {
this(name);
this.actions = toolbarActions;
+ this.ioContainer = ioContainer != null ? ioContainer : IOContainer.getDefault();
}
/** Package private constructor for unit tests */
@@ -94,7 +99,11 @@
String getName() {
return name;
}
-
+
+ IOContainer getIOContainer() {
+ return ioContainer;
+ }
+
public OutputWriter getErr() {
return ((NbWriter) getOut()).getErr();
}
@@ -134,11 +143,11 @@
}
void setClosed (boolean val) {
- closed = val ? Boolean.TRUE : Boolean.FALSE;
+ closed = val;
}
public boolean isClosed() {
- return Boolean.TRUE.equals(closed);
+ return closed;
}
public boolean isErrSeparated() {
@@ -214,7 +223,7 @@
private boolean wasReset = false;
public void reset() {
if (Controller.LOG) Controller.log (this + ": reset");
- closed = null;
+ closed = false;
streamClosedSet = false;
streamClosed = false;
@@ -265,12 +274,6 @@
@SuppressWarnings("deprecation")
public Reader flushReader() {
return getIn();
- }
-
- public void setIcon(Icon icn) {
- icon = icn;
- post (this, IOEvent.CMD_ICON, icn);
-
}
public Icon getIcon() {
diff --git a/core.output2/src/org/netbeans/core/output2/NbIOProvider.java b/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
--- a/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
+++ b/core.output2/src/org/netbeans/core/output2/NbIOProvider.java
@@ -46,6 +46,7 @@
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.windows.IOProvider;
+import org.openide.windows.IOContainer;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;
@@ -59,12 +60,14 @@
private static final String STDOUT = NbBundle.getMessage(NbIOProvider.class,
"LBL_STDOUT"); //NOI18N
+
+ private static final String NAME = "output2"; // NOI18N
public OutputWriter getStdOut() {
if (Controller.LOG) {
Controller.log("NbIOProvider.getStdOut");
}
- InputOutput stdout = getIO (STDOUT, false, null);
+ InputOutput stdout = getIO (STDOUT, false);
NbWriter out = ((NbIO)stdout).writer();
Controller.ensureViewInDefault ((NbIO) stdout, true);
@@ -75,7 +78,7 @@
out = (NbWriter) stdout.getOut();
} catch (IOException e) {
Exceptions.printStackTrace(e);
- stdout = getIO (STDOUT, true, null);
+ stdout = getIO (STDOUT, true);
out = (NbWriter) stdout.getOut();
}
} else {
@@ -86,22 +89,32 @@
public InputOutput getIO(String name, boolean newIO) {
- return getIO (name, newIO, new Action[0]);
+ return getIO (name, newIO, new Action[0], null);
}
@Override
public InputOutput getIO(String name, Action[] toolbarActions) {
- return getIO (name, true, toolbarActions);
+ return getIO (name, true, toolbarActions, null);
}
-
- private InputOutput getIO(String name, boolean newIO, Action[] toolbarActions) {
+
+ @Override
+ public InputOutput getIO(String name, Action[] additionalActions, IOContainer ioContainer) {
+ return getIO(name, true, additionalActions, ioContainer);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ private InputOutput getIO(String name, boolean newIO, Action[] toolbarActions, IOContainer ioContainer) {
if (Controller.LOG) {
Controller.log("GETIO: " + name + " new:" + newIO);
}
NbIO result = namesToIos.get(name);
if (result == null || newIO) {
- result = new NbIO(name, toolbarActions);
+ result = new NbIO(name, toolbarActions, ioContainer);
namesToIos.add (name, result);
Controller.ensureViewInDefault (result, newIO);
} else {
diff --git a/core.output2/src/org/netbeans/core/output2/OutputPane.java b/core.output2/src/org/netbeans/core/output2/OutputPane.java
--- a/core.output2/src/org/netbeans/core/output2/OutputPane.java
+++ b/core.output2/src/org/netbeans/core/output2/OutputPane.java
@@ -87,6 +87,7 @@
}
}
+ @Override
public void setMouseLine (int line, Point p) {
Document doc = getDocument();
if (doc instanceof OutputDocument) {
@@ -157,6 +158,7 @@
* numbers of calls to viewToModel if the cursor is never going to be
* changed anyway.
*/
+ @Override
public void mouseMoved (MouseEvent evt) {
Document doc = getDocument();
if (doc instanceof OutputDocument) {
@@ -166,6 +168,7 @@
}
}
+ @Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
if (e.getSource() == textView && SwingUtilities.isLeftMouseButton(e)) {
@@ -189,6 +192,7 @@
return (OutputTab) SwingUtilities.getAncestorOfClass (OutputTab.class, this);
}
+ @Override
protected void setDocument (Document doc) {
if (doc == null) {
Document d = getDocument();
@@ -266,7 +270,7 @@
InputMap map = result.getInputMap();
MyInputMap myMap = new MyInputMap();
myMap.setParent(map);
- result.setInputMap(result.WHEN_FOCUSED, myMap);
+ result.setInputMap(JEditorPane.WHEN_FOCUSED, myMap);
Action act = new AbstractAction() {
public void actionPerformed(ActionEvent arg0) {
@@ -296,6 +300,7 @@
super();
}
+ @Override
public Object get(KeyStroke keyStroke) {
KeyStroke stroke = KeyStroke.getKeyStroke("control shift O");
if (keyStroke.equals(stroke)) {
@@ -325,6 +330,7 @@
}
private static final class GEP extends JEditorPane {
+ @Override
public java.awt.Color getBackground() {
return UIManager.getColor("text");
}
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
@@ -42,41 +42,79 @@
package org.netbeans.core.output2;
import java.awt.Component;
+import java.awt.Container;
+import java.awt.FileDialog;
+import java.awt.Frame;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.beans.PropertyChangeListener;
+import java.io.CharConversionException;
+import java.io.File;
+import java.io.IOException;
import java.util.regex.Matcher;
+import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
+import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
+import org.netbeans.core.output2.Controller.ControllerOutputEvent;
import org.netbeans.core.output2.ui.AbstractOutputPane;
import org.netbeans.core.output2.ui.AbstractOutputTab;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.actions.FindAction;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+import org.openide.windows.IOContainer;
+import org.openide.windows.OutputListener;
+import org.openide.windows.WindowManager;
+import org.openide.xml.XMLUtil;
/**
* A component representing one tab in the output window.
*/
-final class OutputTab extends AbstractOutputTab {
- private NbIO io;
+final class OutputTab extends AbstractOutputTab implements IOContainer.CallBacks {
+ private final NbIO io;
- OutputTab (NbIO io) {
+ OutputTab(NbIO io) {
this.io = io;
if (Controller.LOG) Controller.log ("Created an output component for " + io);
OutputDocument doc = new OutputDocument (((NbWriter) io.getOut()).out());
- setDocument (doc);
- }
+ setDocument(doc);
- @Override
- public void addNotify() {
- super.addNotify();
- if (io != null) io.setClosed(false);
- }
+ installKeyboardAction(copyAction);
+ installKeyboardAction(selectAllAction);
+ installKeyboardAction(findAction);
+ installKeyboardAction(findNextAction);
+ installKeyboardAction(findPreviousAction);
+ installKeyboardAction(wrapAction);
+ installKeyboardAction(saveAsAction);
+ installKeyboardAction(closeAction);
+ installKeyboardAction(copyAction);
+ installKeyboardAction(navToLineAction);
+ installKeyboardAction(postMenuAction);
+ installKeyboardAction(clearAction);
- @Override
- public void removeNotify() {
- if (io != null) io.setClosed(true);
- super.removeNotify();
+ getActionMap().put("jumpPrev", this.prevErrorAction); // NOI18N
+ getActionMap().put("jumpNext", this.nextErrorAction); // NOI18N
+ getActionMap().put(FindAction.class.getName(), this.findAction);
+ getActionMap().put(javax.swing.text.DefaultEditorKit.copyAction, this.copyAction);
+
}
@Override
@@ -92,16 +130,9 @@
}
}
- public void setIO (NbIO io) {
- if (Controller.LOG) Controller.log ("Replacing io on " + this + " with " + io + " out is " + (io != null ? io.getOut() : null));
- if (io != null) {
- setDocument (new OutputDocument(((NbWriter) io.getOut()).out()));
- io.setClosed(false);
- } else {
- if (this.io != null) this.io.setClosed(true);
- this.io = null;
- setDocument(null);
- }
+ public void reset() {
+ setDocument(new OutputDocument(((NbWriter) io.getOut()).out()));
+ io.setClosed(false);
}
public OutputDocument getDocument() {
@@ -119,70 +150,60 @@
protected void inputSent(String txt) {
if (Controller.LOG) Controller.log("Input sent on OutputTab: " + txt);
getOutputPane().lockScroll();
- findOutputWindow().inputSent(this, txt);
+ NbIO.IOReader in = io.in();
+ if (in != null) {
+ if (Controller.LOG) Controller.log("Sending input to " + in);
+ in.pushText(txt + "\n");
+ io.getOut().println(txt);
+ }
}
protected void inputEof() {
- if (Controller.LOG) Controller.log ("Input EOF on OutputTab: ");
- findOutputWindow().inputEof(this);
+ if (Controller.LOG) Controller.log ("Input EOF");
+ NbIO.IOReader in = io.in();
+ if (in != null) {
+ in.eof();
+ }
}
public void hasSelectionChanged(boolean val) {
- OutputWindow win = findOutputWindow();
- if (win != null) {
- win.hasSelectionChanged(this, val);
+ if (isShowing()) {
+ copyAction.setEnabled(val);
+ selectAllAction.setEnabled(!getOutputPane().isAllSelected());
}
}
public NbIO getIO() {
return io;
}
-
- private long timestamp = 0;
- void updateTimestamp() {
- timestamp = System.currentTimeMillis();
- }
-
- long getTimestamp() {
- return timestamp;
- }
-
- private OutputWindow findOutputWindow() {
- if (getParent() != null) {
- return (OutputWindow) SwingUtilities.getAncestorOfClass(OutputWindow.class, this);
- } else {
- return (OutputWindow) getClientProperty ("outputWindow"); //NOI18N
- }
- }
void requestActive() {
- findOutputWindow().requestActive();
+ io.getIOContainer().requestActive();
}
public void lineClicked(int line) {
- findOutputWindow().lineClicked (this, line);
+ OutWriter out = io.out();
+ if (out == null) {
+ return;
+ }
+ OutputListener l = out.getLines().getListenerForLine(line);
+ if (l != null) {
+ ControllerOutputEvent oe = new ControllerOutputEvent (io, line);
+ l.outputLineAction(oe);
+ //Select the text on click
+ getOutputPane().sendCaretToLine(line, true);
+ }
}
-
- boolean linePressed (int line, Point p) {
- OutWriter out = getIO().out();
+
+ boolean linePressed(int line, Point p) {
+ OutWriter out = io.out();
if (out != null) {
return out.getLines().getListenerForLine(line) != null;
} else {
return false;
}
- }
-
- public void postPopupMenu(Point p, Component src) {
- findOutputWindow().postPopupMenu(this, p, src);
}
- public void caretEnteredLine(int line) {
- OutputWindow ow = findOutputWindow();
- if (ow != null) {
- ow.caretEnteredLine(this, line);
- }
- }
-
private int firstNavigableListenerLine = -1;
/**
* Do not unlock scrollbar unless there is a bona-fide error to
@@ -209,21 +230,84 @@
}
private boolean hasOutputListeners = false;
+
public void documentChanged() {
- OutputWindow win = findOutputWindow();
- if (win != null) {
- boolean hadOutputListeners = hasOutputListeners;
- if (getFirstNavigableListenerLine() == -1) {
- return;
+ boolean hadOutputListeners = hasOutputListeners;
+ if (getFirstNavigableListenerLine() == -1) {
+ return;
+ }
+ hasOutputListeners = io.out() != null && io.out().getLines().firstListenerLine() >= 0;
+ if (hasOutputListeners != hadOutputListeners) {
+ hasOutputListenersChanged(hasOutputListeners);
+ }
+
+ IOContainer ioContainer = io.getIOContainer();
+ if (io.isFocusTaken()) {
+ ioContainer.select(this);
+ ioContainer.requestVisible();
+ }
+ Controller.getDefault().updateName(ioContainer, this);
+ if (this == ioContainer.getSelected() && ioContainer.isActivated()) {
+ updateActions();
+ }
+ }
+
+ /**
+ * Called when the output stream has been closed, to navigate to the
+ * first line which shows an error (if any).
+ */
+ private void navigateToFirstErrorLine() {
+ OutWriter out = io.out();
+ if (out != null) {
+ int line = getFirstNavigableListenerLine();
+ if (Controller.LOG) {
+ Controller.log("NAV TO FIRST LISTENER LINE: " + line);
}
- hasOutputListeners = getIO().out() != null && getIO().out().getLines().firstListenerLine() >= 0;
- if (hasOutputListeners != hadOutputListeners) {
- win.hasOutputListenersChanged(this, hasOutputListeners);
+ if (line > 0) {
+ getOutputPane().sendCaretToLine(line, false);
+ if (isSDI()) {
+ requestActive();
+ }
}
- win.documentChanged(this);
}
}
+ private boolean isSDI() {
+ Container c = getTopLevelAncestor();
+ return (c != WindowManager.getDefault().getMainWindow());
+ }
+
+ void hasOutputListenersChanged(boolean hasOutputListeners) {
+ if (hasOutputListeners && getOutputPane().isScrollLocked()) {
+ navigateToFirstErrorLine();
+ }
+ }
+
+ public void activated() {
+ updateActions();
+ }
+
+ public void closed() {
+ io.setClosed(true);
+ Controller.getDefault().removeTab(io);
+ io.setClosed(true);
+ NbWriter w = io.writer();
+ if (w != null && w.isClosed()) {
+ //Will dispose the document
+ setDocument(null);
+ } else if (w != null) {
+ //Something is still writing to the stream, but we're getting rid of the tab. Don't dispose
+ //the writer, just kill the tab's document
+ getDocument().disposeQuietly();
+ }
+ }
+
+ public void deactivated() {
+ }
+
+ public void selected() {
+ }
+
/**
* Determine if the new caret position is close enough that the scrollbar should be re-locked
* to the end of the document.
@@ -232,12 +316,10 @@
* @return if it should be locked
*/
public boolean shouldRelock(int dot) {
- if (io != null) {
- OutWriter w = io.out();
- if (w != null && !w.isClosed()) {
- int dist = Math.abs(w.getLines().getCharCount() - dot);
- return dist < 100;
- }
+ OutWriter w = io.out();
+ if (w != null && !w.isClosed()) {
+ int dist = Math.abs(w.getLines().getCharCount() - dot);
+ return dist < 100;
}
return false;
}
@@ -298,5 +380,589 @@
}
}
}
- }
+ }
+
+ /**
+ * Fetch the output listener for a given line
+ *
+ * @param line The line to find a listener on
+ * @return An output listener or null
+ */
+ private OutputListener listenerForLine(int line) {
+ OutWriter out = io.out();
+ if (out != null) {
+ return out.getLines().getListenerForLine(line);
+ }
+ return null;
+ }
+ /**
+ * Flag used to block navigating the editor to the first error line when
+ * selecting the error line in the output window after a build (or maybe
+ * it should navigate the editor there? Could be somewhat rude...)
+ */
+ boolean ignoreCaretChanges = false;
+
+ /**
+ * Called when the text caret has changed lines - will call OutputListener.outputLineSelected if
+ * there is a listener for that line.
+ *
+ * @param line The line the caret is in
+ */
+ void caretEnteredLine(int line) {
+ if (!ignoreCaretChanges) {
+ OutputListener l = listenerForLine(line);
+ if (l != null) {
+ ControllerOutputEvent oe = new ControllerOutputEvent(io, line);
+ l.outputLineSelected(oe);
+ }
+ }
+ }
+
+ /**
+ * Sends the caret in a tab to the nearest error line to its current position, selecting
+ * that line.
+ *
+ * @param backward If the search should be done in reverse
+ */
+ private void sendCaretToError(boolean backward) {
+ OutWriter out = io.out();
+ if (out != null) {
+ int line = getOutputPane().getCaretLine();
+ if (!getOutputPane().isLineSelected(line)) {
+ line += backward ? 1 : -1;
+ }
+
+ if (line >= getOutputPane().getLineCount() - 1) {
+ line = 0;
+ }
+ //FirstF12: #48485 - caret is already on the first listener line,
+ //so F12 jumps to the second error. So search from 0 the first time after a reset
+ int newline = out.getLines().nearestListenerLine(line, backward);
+ if (newline == line) {
+ if (!backward && line != getOutputPane().getLineCount()) {
+ newline = out.getLines().nearestListenerLine(line + 1, backward);
+ } else if (backward && line > 0) {
+ newline = out.getLines().nearestListenerLine(line - 1, backward);
+ } else {
+ return;
+ }
+ }
+ if (newline != -1) {
+ getOutputPane().sendCaretToLine(newline, true);
+ if (!io.getIOContainer().isActivated()) {
+ OutputListener l = out.getLines().getListenerForLine(newline);
+ ControllerOutputEvent ce = new ControllerOutputEvent(io, newline);
+ l.outputLineAction(ce);
+ }
+ }
+ }
+ }
+
+ /**
+ * Find the next match for the previous search contents, starting at
+ * the current caret position.
+ *
+ */
+ private void findNext() {
+ OutWriter out = io.out();
+ if (out != null) {
+ String lastPattern = FindDialogPanel.getPanel().getPattern();
+ if (lastPattern != null) {
+ out.getLines().find(lastPattern);
+ }
+ Matcher matcher = out.getLines().getForwardMatcher();
+ int pos = getOutputPane().getCaretPos();
+ if (pos >= getOutputPane().getLength() || pos < 0) {
+ pos = 0;
+ }
+
+ if (matcher != null && matcher.find(pos)) {
+ getOutputPane().setSelection(matcher.start(), matcher.end());
+ copyAction.setEnabled(true);
+ } else {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+ }
+
+ /**
+ * Find the match before the current caret position, using the previously
+ * searched for value.
+ *
+ * @param tab The tab
+ */
+ private void findPrevious() {
+ OutWriter out = io.out();
+ if (out != null) {
+ String lastPattern = FindDialogPanel.getPanel().getPattern();
+ if (lastPattern != null) {
+ out.getLines().find(lastPattern);
+ }
+ Matcher matcher = out.getLines().getReverseMatcher();
+
+ int length = getOutputPane().getLength();
+ int pos = length - getOutputPane().getSelectionStart();
+
+ if (pos >= getOutputPane().getLength() - 1 || pos < 0) {
+ pos = 0;
+ }
+ if (matcher != null && matcher.find(pos)) {
+ int start = length - matcher.end();
+ int end = length - matcher.start();
+ getOutputPane().setSelection(start, end);
+ copyAction.setEnabled(true);
+ } else {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+ }
+
+ /**
+ * Holds the last written to directory for the save as file chooser.
+ */
+ private static String lastDir = null;
+
+ /**
+ * Invokes a file dialog and if a file is chosen, saves the output to that file.
+ */
+ void saveAs() {
+ OutWriter out = io.out();
+ if (out == null) {
+ return;
+ }
+ File f = showFileChooser(this);
+ if (f != null) {
+ try {
+ synchronized (out) {
+ out.getLines().saveAs(f.getPath());
+ }
+ } catch (IOException ioe) {
+ NotifyDescriptor notifyDesc = new NotifyDescriptor(
+ NbBundle.getMessage(OutputTab.class, "MSG_SaveAsFailed", f.getPath()),
+ NbBundle.getMessage(OutputTab.class, "LBL_SaveAsFailedTitle"),
+ NotifyDescriptor.DEFAULT_OPTION,
+ NotifyDescriptor.ERROR_MESSAGE,
+ new Object[]{NotifyDescriptor.OK_OPTION},
+ NotifyDescriptor.OK_OPTION);
+
+ DialogDisplayer.getDefault().notify(notifyDesc);
+ }
+ }
+ }
+
+ /**
+ * Shows a file dialog and an overwrite dialog if the file exists, returning
+ * null if the user chooses not to overwrite. Will use an AWT FileDialog for
+ * Aqua, per Apple UI guidelines.
+ *
+ * @param owner A parent component for the dialog - the top level ancestor will
+ * actually be used so positioning is correct
+ * @return A file to write to
+ */
+ private static File showFileChooser(JComponent owner) {
+ File f = null;
+ String dlgTtl = NbBundle.getMessage(Controller.class, "TITLE_SAVE_DLG"); //NOI18N
+
+ boolean isAqua = "Aqua".equals(UIManager.getLookAndFeel().getID()); //NOI18N
+
+ if (isAqua) {
+ //Apple UI guidelines recommend against ever using JFileChooser
+ FileDialog fd = new FileDialog((Frame) owner.getTopLevelAncestor(), dlgTtl, FileDialog.SAVE);
+ if (lastDir != null && new File(lastDir).exists()) {
+ fd.setDirectory(lastDir);
+ }
+ fd.setModal(true);
+ fd.setVisible(true);
+ String s = fd.getDirectory() + fd.getFile();
+ f = new File(s);
+ if (f.exists() && f.isDirectory()) {
+ f = null;
+ }
+ } else {
+ JFileChooser jfc = new JFileChooser();
+ if (lastDir != null && new File(lastDir).exists()) {
+ File dir = new File(lastDir);
+ if (dir.exists()) {
+ jfc.setCurrentDirectory(dir);
+ }
+ }
+ jfc.setName(dlgTtl);
+ jfc.setDialogTitle(dlgTtl);
+
+ if (jfc.showSaveDialog(owner.getTopLevelAncestor()) == JFileChooser.APPROVE_OPTION) {
+ f = jfc.getSelectedFile();
+ }
+ }
+
+ if (f != null && f.exists() && !isAqua) { //Aqua's file dialog takes care of this
+ String msg = NbBundle.getMessage(Controller.class,
+ "FMT_FILE_EXISTS", new Object[]{f.getName()}); //NOI18N
+ String title = NbBundle.getMessage(Controller.class,
+ "TITLE_FILE_EXISTS"); //NOI18N
+ if (JOptionPane.showConfirmDialog(owner.getTopLevelAncestor(), msg, title,
+ JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) {
+ f = null;
+ }
+ }
+ if (f != null) {
+ lastDir = f.getParent();
+ }
+ return f;
+ }
+
+ /**
+ * Called when a line is clicked - if an output listener is listening on that
+ * line, it will be sent outputLineAction.
+ */
+ private void openLineIfError() {
+ OutWriter out = io.out();
+ if (out != null) {
+ int line = getOutputPane().getCaretLine();
+ OutputListener lis = out.getLines().getListenerForLine(line);
+ if (lis != null) {
+ ignoreCaretChanges = true;
+ getOutputPane().sendCaretToLine(line, true);
+ ignoreCaretChanges = false;
+ ControllerOutputEvent coe = new ControllerOutputEvent(io, line);
+ lis.outputLineAction(coe);
+ }
+ }
+ }
+
+ /**
+ * Post the output window's popup menu
+ *
+ * @param p The point clicked
+ * @param src The source of the click event
+ */
+ void postPopupMenu(Point p, Component src) {
+ JPopupMenu popup = new JPopupMenu();
+ Action[] a = getToolbarActions();
+ if (a.length > 0) {
+ boolean added = false;
+ for (int i = 0; i < a.length; i++) {
+ if (a[i].getValue(Action.NAME) != null) {
+ // add the proxy that doesn't show icons #67451
+ popup.add(new ProxyAction(a[i]));
+ added = true;
+ }
+ }
+ if (added) {
+ popup.add(new JSeparator());
+ }
+ }
+
+ for (int i = 0; i < popupItems.length; i++) {
+ if (popupItems[i] instanceof JSeparator) {
+ popup.add((JSeparator) popupItems[i]);
+ } else {
+ if (popupItems[i] != wrapAction) {
+ if (popupItems[i] == closeAction && !io.getIOContainer().isCloseable(this)) {
+ continue;
+ }
+ JMenuItem item = popup.add((Action) popupItems[i]);
+ if (popupItems[i] == findAction) {
+ item.setMnemonic(KeyEvent.VK_F);
+ }
+ } else {
+ JCheckBoxMenuItem item =
+ new JCheckBoxMenuItem((Action) popupItems[i]);
+
+ item.setSelected(getOutputPane().isWrapped());
+ popup.add(item);
+ }
+ }
+ }
+ // hack to remove the esc keybinding when doing popup..
+ KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ JComponent c = getOutputPane().getTextView();
+ Object escHandle = c.getInputMap().get(esc);
+ c.getInputMap().remove(esc);
+ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(esc);
+
+ popup.addPopupMenuListener(new PMListener(popupItems, escHandle));
+ popup.show(src, p.x, p.y);
+
+ }
+
+ void updateActions() {
+ OutputPane pane = (OutputPane) getOutputPane();
+ int len = pane.getLength();
+ boolean enable = len > 0;
+ findAction.setEnabled(enable);
+ OutWriter out = io.out();
+ saveAsAction.setEnabled(enable);
+ selectAllAction.setEnabled(enable);
+ copyAction.setEnabled(pane.hasSelection());
+ boolean hasErrors = out == null ? false : out.getLines().firstListenerLine() != -1;
+ nextErrorAction.setEnabled(hasErrors);
+ prevErrorAction.setEnabled(hasErrors);
+ }
+
+ private void disableHtmlName() {
+ Controller.getDefault().removeFromUpdater(this);
+ String escaped;
+ try {
+ escaped = XMLUtil.toAttributeValue(io.getName() + " ");
+ } catch (CharConversionException e) {
+ escaped = io.getName() + " ";
+ }
+ //#88204 apostophes are escaped in xm but not html
+ io.getIOContainer().setTitle(this, escaped.replace("'", "'"));
+ }
+ private static final int ACTION_COPY = 0;
+ private static final int ACTION_WRAP = 1;
+ private static final int ACTION_SAVEAS = 2;
+ private static final int ACTION_CLOSE = 3;
+ private static final int ACTION_NEXTERROR = 4;
+ private static final int ACTION_PREVERROR = 5;
+ private static final int ACTION_SELECTALL = 6;
+ private static final int ACTION_FIND = 7;
+ private static final int ACTION_FINDNEXT = 8;
+ private static final int ACTION_NAVTOLINE = 9;
+ private static final int ACTION_POSTMENU = 10;
+ private static final int ACTION_FINDPREVIOUS = 11;
+ private static final int ACTION_CLEAR = 12;
+ private static final int ACTION_NEXTTAB = 13;
+ private static final int ACTION_PREVTAB = 14;
+
+ Action copyAction = new TabAction(ACTION_COPY, "ACTION_COPY"); //NOI18N
+ Action wrapAction = new TabAction(ACTION_WRAP, "ACTION_WRAP"); //NOI18N
+ Action saveAsAction = new TabAction(ACTION_SAVEAS, "ACTION_SAVEAS"); //NOI18N
+ Action closeAction = new TabAction(ACTION_CLOSE, "ACTION_CLOSE"); //NOI18N
+ Action nextErrorAction = new TabAction(ACTION_NEXTERROR, "ACTION_NEXT_ERROR"); //NOI18N
+ Action prevErrorAction = new TabAction(ACTION_PREVERROR, "ACTION_PREV_ERROR"); //NOI18N
+ Action selectAllAction = new TabAction(ACTION_SELECTALL, "ACTION_SELECT_ALL"); //NOI18N
+ Action findAction = new TabAction(ACTION_FIND, "ACTION_FIND"); //NOI18N
+ Action findNextAction = new TabAction(ACTION_FINDNEXT, "ACTION_FIND_NEXT"); //NOI18N
+ Action findPreviousAction = new TabAction(ACTION_FINDPREVIOUS, "ACTION_FIND_PREVIOUS"); //NOI18N
+ Action navToLineAction = new TabAction(ACTION_NAVTOLINE, "navToLine", //NOI18N
+ KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
+ Action postMenuAction = new TabAction(ACTION_POSTMENU, "postMenu", //NOI18N
+ KeyStroke.getKeyStroke(KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK));
+ Action clearAction = new TabAction(ACTION_CLEAR, "ACTION_CLEAR");
+ Action nextTabAction = new TabAction(ACTION_NEXTTAB, "NextViewAction", //NOI18N
+ (KeyStroke) null);
+ Action prevTabAction = new TabAction(ACTION_PREVTAB, "PreviousViewAction", //NOI18N
+ (KeyStroke) null);
+ private Object[] popupItems = new Object[]{
+ copyAction, new JSeparator(), findAction, findNextAction, new JSeparator(),
+ wrapAction, new JSeparator(), saveAsAction, clearAction, closeAction,};
+
+ /**
+ * A stateless action which will find the owning OutputTab's controller and call
+ * actionPerformed with its ID as an argument.
+ */
+ class TabAction extends AbstractAction {
+
+ private int id;
+
+ /**
+ * Create a ControllerAction with the specified action ID (constants defined in Controller),
+ * using the specified bundle key. Expects the following contents in the bundle:
+ *
+ *
A name for the action matching the passed key
+ *
An accelerator for the action matching [key].accel
+ *
+ * @param id An action ID
+ * @param bundleKey A key for the bundle associated with the Controller class
+ * @see org.openide.util.Utilities#stringToKey
+ */
+ TabAction(int id, String bundleKey) {
+ if (bundleKey != null) {
+ String name = NbBundle.getMessage(OutputTab.class, bundleKey);
+ KeyStroke accelerator = getAcceleratorFor(bundleKey);
+ this.id = id;
+ putValue(NAME, name);
+ putValue(ACCELERATOR_KEY, accelerator);
+ }
+ }
+
+ /**
+ * Create a ControllerAction with the specified ID, name and keystroke. Actions created
+ * using this constructor will not be added to the popup menu of the component.
+ *
+ * @param id The ID
+ * @param name A programmatic name for the item
+ * @param stroke An accelerator keystroke
+ */
+ TabAction(int id, String name, KeyStroke stroke) {
+ this.id = id;
+ putValue(NAME, name);
+ putValue(ACCELERATOR_KEY, stroke);
+ }
+
+ void clearListeners() {
+ PropertyChangeListener[] l = changeSupport.getPropertyChangeListeners();
+ for (int i = 0; i < l.length; i++) {
+ removePropertyChangeListener(l[i]);
+ }
+ }
+
+ /**
+ * Get a keyboard accelerator from the resource bundle, with special handling
+ * for the mac keyboard layout.
+ *
+ * @param name The bundle key prefix
+ * @return A keystroke
+ */
+ private KeyStroke getAcceleratorFor(String name) {
+ String key = name + ".accel"; //NOI18N
+ if (Utilities.isMac()) {
+ key += ".mac"; //NOI18N
+ }
+ return Utilities.stringToKey(NbBundle.getMessage(OutputTab.class, key));
+ }
+
+ public int getID() {
+ return id;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ switch (id) {
+ case ACTION_COPY:
+ getOutputPane().copy();
+ break;
+ case ACTION_WRAP:
+ boolean wrapped = getOutputPane().isWrapped();
+ getOutputPane().setWrapped(!wrapped);
+ break;
+ case ACTION_SAVEAS:
+ saveAs();
+ break;
+ case ACTION_CLOSE:
+ io.getIOContainer().remove(OutputTab.this);
+ break;
+ case ACTION_NEXTERROR:
+ sendCaretToError(false);
+ break;
+ case ACTION_PREVERROR:
+ sendCaretToError(true);
+ break;
+ case ACTION_SELECTALL:
+ getOutputPane().selectAll();
+ break;
+ case ACTION_FIND:
+ int start = getOutputPane().getSelectionStart();
+ int end = getOutputPane().getSelectionEnd();
+ String str = null;
+ if (start > 0 && end > start) {
+ try {
+ str = getOutputPane().getDocument().getText(start, end - start);
+ } catch (BadLocationException ex) {
+ ex.printStackTrace();
+ }
+ }
+ FindDialogPanel.showFindDialog(getFindActionListener(findNextAction, findPreviousAction, copyAction), str);
+ break;
+ case ACTION_FINDNEXT:
+ findNext();
+ break;
+ case ACTION_FINDPREVIOUS:
+ findPrevious();
+ break;
+ case ACTION_NAVTOLINE:
+ openLineIfError();
+ break;
+ case ACTION_POSTMENU:
+ postPopupMenu(new Point(0, 0), OutputTab.this);
+ break;
+ case ACTION_CLEAR:
+ NbWriter writer = io.writer();
+ if (writer != null) {
+ try {
+ writer.reset();
+ disableHtmlName();
+ } catch (IOException ioe) {
+ Exceptions.printStackTrace(ioe);
+ }
+ }
+ break;
+ default:
+ assert false;
+ }
+ }
+ }
+
+ private static class ProxyAction implements Action {
+
+ private Action orig;
+
+ ProxyAction(Action original) {
+ orig = original;
+ }
+
+ public Object getValue(String key) {
+ if (Action.SMALL_ICON.equals(key)) {
+ return null;
+ }
+ return orig.getValue(key);
+ }
+
+ public void putValue(String key, Object value) {
+ orig.putValue(key, value);
+ }
+
+ public void setEnabled(boolean b) {
+ orig.setEnabled(b);
+ }
+
+ public boolean isEnabled() {
+ return orig.isEnabled();
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ orig.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ orig.removePropertyChangeListener(listener);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ orig.actionPerformed(e);
+ }
+ }
+
+ /**
+ * #47166 - a disposed tab which has had its popup menu shown remains
+ * referenced through PopupItems->JSeparator->PopupMenu->Invoker->OutputPane->OutputTab
+ */
+ private class PMListener implements PopupMenuListener {
+
+ private Object[] popupItems;
+ private Object handle;
+
+ PMListener(Object[] popupItems, Object escHandle) {
+ this.popupItems = popupItems;
+ handle = escHandle;
+ }
+
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ JPopupMenu popup = (JPopupMenu) e.getSource();
+ popup.removeAll();
+ popup.setInvoker(null);
+ // hack
+ KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ JComponent c = getOutputPane().getTextView();
+ c.getInputMap().put(esc, handle);
+ getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(esc, handle);
+
+ //hack end
+ popup.removePopupMenuListener(this);
+ for (int i = 0; i < popupItems.length; i++) {
+ if (popupItems[i] instanceof OutputTab.TabAction) {
+ ((OutputTab.TabAction) popupItems[i]).clearListeners();
+ }
+ }
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ popupMenuWillBecomeInvisible(e);
+ }
+
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ //do nothing
+ }
+ }
}
diff --git a/core.output2/src/org/netbeans/core/output2/OutputWindow.java b/core.output2/src/org/netbeans/core/output2/OutputWindow.java
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/OutputWindow.java
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2007 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-2006 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.netbeans.core.output2;
-
-import java.awt.AWTEvent;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Insets;
-import java.awt.Point;
-import java.awt.event.FocusEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.util.HashSet;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.swing.UIManager;
-import org.netbeans.core.output2.ui.AbstractOutputTab;
-import org.netbeans.core.output2.ui.AbstractOutputWindow;
-import org.openide.util.ImageUtilities;
-import org.openide.util.NbBundle;
-import org.openide.util.Utilities;
-import org.openide.windows.TopComponent;
-import org.openide.windows.WindowManager;
-
-/**
- * An output window. Note this class contains no logic of interest - all
- * events of interest are passed to the Controller which
- * manages this instance (and possibly others).
- *
- * The mechanism for displaying/not displaying the tabbed pane is handled in
- * the superclass, which overrides addImpl() and remove() to automatically install
- * the tabbed pane if more than one view is added, and remove it if only one
- * is present - so it is enough to simply call add() and remove() with instances
- * of OutputTab and the management of tabs will be taken care of automatically.
- */
-public class OutputWindow extends AbstractOutputWindow {
- private Controller controller;
- static OutputWindow DEFAULT = null;
- public static final String ICON_RESOURCE =
- "org/netbeans/core/resources/frames/output.png"; // NOI18N
-
- private MouseListener activateListener = new MouseAdapter() {
- @Override
- public void mouseClicked(MouseEvent e) {
- //#83829
- requestActive();
- }
- };
-
- public OutputWindow() {
- this (new Controller());
- enableEvents(AWTEvent.FOCUS_EVENT_MASK);
- putClientProperty ("dontActivate", Boolean.TRUE);
- getActionMap().put("PreviousViewAction", controller.prevTabAction);
- getActionMap().put("NextViewAction", controller.nextTabAction);
- }
-
- @Override
- public void addNotify() {
- super.addNotify();
- pane.addMouseListener(activateListener);
- }
-
- @Override
- public void removeNotify() {
- super.removeNotify();
- pane.removeMouseListener(activateListener);
- }
-
-
- protected void closeRequest(AbstractOutputTab tab) {
- controller.close (this, (OutputTab) tab, false);
- }
-
- OutputWindow (Controller controller) {
- if (Controller.LOG) Controller.log("Created an output window");
- this.controller = controller;
- setDisplayName (NbBundle.getMessage(OutputWindow.class, "LBL_OUTPUT")); //NOI18N
- // setting name to satisfy the accesible name requirement for window.
- setName (NbBundle.getMessage(OutputWindow.class, "LBL_OUTPUT")); //NOI18N
-
- setIcon(ImageUtilities.loadImage(ICON_RESOURCE)); // NOI18N
- // special title for sliding mode
- // XXX - please rewrite to regular API when available - see issue #55955
- putClientProperty("SlidingName", getDisplayName()); //NOI18N
- }
-
- public static synchronized OutputWindow findDefault() {
- if (DEFAULT == null) {
- //If settings file is correctly defined call of WindowManager.findTopComponent() will
- //call TestComponent00.getDefault() and it will set static field component.
- TopComponent tc = WindowManager.getDefault().findTopComponent("output"); // NOI18N
- if (tc != null) {
- if (!(tc instanceof OutputWindow)) {
- //This should not happen. Possible only if some other module
- //defines different settings file with the same name but different class.
- //Incorrect settings file?
- IllegalStateException exc = new IllegalStateException
- ("Incorrect settings file. Unexpected class returned." // NOI18N
- + " Expected:" + OutputWindow.class.getName() // NOI18N
- + " Returned:" + tc.getClass().getName()); // NOI18N
- Logger.getLogger(OutputWindow.class.getName()).log(Level.WARNING, null, exc);
- //Fallback to accessor reserved for window system.
- OutputWindow.getDefault();
- }
- } else {
- OutputWindow.getDefault();
- }
- }
- return DEFAULT;
- }
- /* Singleton accessor reserved for window system ONLY. Used by window system to create
- * OutputWindow instance from settings file when method is given. Use findDefault
- * to get correctly deserialized instance of OutputWindow. */
- public static synchronized OutputWindow getDefault() {
- if (DEFAULT == null) {
- DEFAULT = new OutputWindow();
- }
- return DEFAULT;
- }
-
- @Override
- public int getPersistenceType() {
- return PERSISTENCE_ALWAYS;
- }
-
- @Override
- public String preferredID() {
- return "output"; //NOI18N
- }
-
- public Object readResolve() throws java.io.ObjectStreamException {
- return getDefault();
- }
-
- @Override
- public String getToolTipText() {
- return getDisplayName();
- }
-
- Controller getController() {
- return controller;
- }
-
- @Override
- public void requestVisible () {
- if (Controller.LOG) {
- Controller.log("Request visible");
- Controller.logStack();
- }
- super.requestVisible();
- }
-
- @Override
- public void processFocusEvent (FocusEvent fe) {
- super.processFocusEvent (fe);
- if (Boolean.TRUE.equals(getClientProperty("isSliding"))) { //NOI18N
- repaint(200);
- }
- }
-
- @Override
- public void paintComponent (Graphics g) {
- super.paintComponent (g);
- if (hasFocus()) {
- Insets ins = getInsets();
- Color col = UIManager.getColor ("controlShadow"); //NOI18N
- //Draw *some* focus indication
- if (col == null) {
- col = java.awt.Color.GRAY;
- }
- g.setColor(col);
- g.drawRect (
- ins.left + 2,
- ins.top + 2,
- getWidth() - (ins.left + ins.right + 4),
- getHeight() - (ins.top + ins.bottom + 4));
- }
- }
-
- @Override
- public void requestActive() {
- boolean act = isActivated();
- if (Controller.LOG) Controller.log("Request active");
- super.requestActive();
- if (!act) {
- requestFocus();
- }
- }
-
- private boolean activated = false;
- @Override
- protected void componentActivated () {
- if (Controller.LOG) Controller.log("ComponentActivated");
- super.componentActivated();
- activated = true;
- controller.notifyActivated (this);
- requestFocus();
- }
-
- @Override
- protected void componentDeactivated() {
- if (Controller.LOG) Controller.log("ComponentDeactivated");
- super.componentDeactivated();
- activated = false;
- }
-
- protected void removed(AbstractOutputTab view) {
- if (Controller.LOG) Controller.log("Removed tab " + view);
- if (Controller.LOG) Controller.log ("Tab has been removed. Notifying controller.");
- controller.notifyRemoved((OutputTab) view);
- }
-
- protected void selectionChanged(AbstractOutputTab former, AbstractOutputTab current) {
- controller.selectionChanged (this, (OutputTab) former, (OutputTab) current);
- }
-
- void lineClicked(OutputTab outputComponent, int line) {
- controller.lineClicked (this, outputComponent, line);
- }
-
- void postPopupMenu(OutputTab outputComponent, Point p, Component src) {
- controller.postPopupMenu (this, outputComponent, p, src);
- }
-
- void caretEnteredLine(OutputTab outputComponent, int line) {
- controller.caretEnteredLine(outputComponent, line);
- }
-
- void documentChanged(OutputTab comp) {
- controller.documentChanged (this, comp);
- }
-
- private HashSet hiddenTabs = null;
- void putHiddenView (OutputTab comp) {
- if (hiddenTabs == null) {
- hiddenTabs = new HashSet();
- }
- comp.putClientProperty("outputWindow", this); //NOI18N
- hiddenTabs.add(comp);
- if (comp.getParent() != null) {
- comp.getParent().remove(comp);
- }
- }
-
- void removeHiddenView (OutputTab comp) {
- hiddenTabs.remove(comp);
- comp.putClientProperty("outputWindow", null); //NOI18N
- }
-
- @Override
- public void setSelectedTab (AbstractOutputTab op) {
- if (op.getParent() == null && hiddenTabs.contains(op)) {
- removeHiddenView ((OutputTab) op);
- add(op);
- }
- super.setSelectedTab (op);
- }
-
- protected void updateSingletonName(String name) {
- String winName = NbBundle.getMessage(OutputWindow.class, "LBL_OUTPUT"); //NOI18N
- if (name != null) {
- String newName = NbBundle.getMessage(OutputWindow.class,
- "FMT_OUTPUT", new Object[] {winName, name}); //NOI18N
- if (newName.indexOf ("") != -1) {
- newName = Utilities.replaceString(newName, "", ""); //NOI18N
- setHtmlDisplayName("" + newName); //NOI18N
- } else {
- setDisplayName(newName);
- setHtmlDisplayName(null);
- }
- } else {
- setDisplayName(winName);
- setHtmlDisplayName(null);
- }
- }
-
-
- OutputTab[] getHiddenTabs() {
- if (hiddenTabs != null && !hiddenTabs.isEmpty()) {
- OutputTab[] result = new OutputTab[hiddenTabs.size()];
- return hiddenTabs.toArray(result);
- }
- return new OutputTab[0];
- }
-
- OutputTab getTabForIO (NbIO io) {
- AbstractOutputTab[] views = getTabs();
- for (int i=0; i < views.length; i++) {
- if (((OutputTab) views[i]).getIO() == io) {
- return ((OutputTab) views[i]);
- }
- }
- OutputTab[] hidden = getHiddenTabs();
- for (int i=0; i < hidden.length; i++) {
- if (hidden[i].getIO() == io) {
- return hidden[i];
- }
- }
- return null;
- }
-
- void eventDispatched(IOEvent ioe) {
- if (Controller.LOG) Controller.log ("Event received: " + ioe);
- NbIO io = ioe.getIO();
- int command = ioe.getCommand();
- boolean value = ioe.getValue();
- Object data = ioe.getData();
- OutputTab comp = getTabForIO (io);
- if (command == IOEvent.CMD_DETACH) {
- if (!ioe.isConsumed()) {
- //Can be used by ModuleInstall to dispose of the current output window if desired
- ioe.consume();
- DEFAULT = null;
- return;
- }
- }
- if (Controller.LOG) Controller.log ("Passing command to controller " + ioe);
- controller.performCommand (this, comp, io, command, value, data);
- ioe.consume();
- }
-
- void hasSelectionChanged(OutputTab tab, boolean val) {
- controller.hasSelectionChanged(this, tab, val);
- }
-
- public boolean isActivated() {
- return activated;
- }
-
- void hasOutputListenersChanged(OutputTab tab, boolean hasOutputListeners) {
- controller.hasOutputListenersChanged(this, tab, hasOutputListeners);
- }
-
- void inputEof(OutputTab tab) {
- if (Controller.LOG) Controller.log ("Input EOF on " + this);
- controller.inputEof(tab);
- }
-
- void inputSent(OutputTab c, String txt) {
- if (Controller.LOG) Controller.log ("Notifying controller input sent " + txt);
- controller.notifyInput(this, c, txt);
- }
-}
diff --git a/core.output2/src/org/netbeans/core/output2/OutputWindowAction.java b/core.output2/src/org/netbeans/core/output2/OutputWindowAction.java
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/OutputWindowAction.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2007 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-2006 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.netbeans.core.output2;
-
-import org.openide.util.HelpCtx;
-import org.openide.util.NbBundle;
-import org.openide.util.actions.CallableSystemAction;
-import org.openide.windows.Mode;
-import org.openide.windows.TopComponent;
-import org.openide.windows.WindowManager;
-
-/** The action which shows standard IO component.
-*
-* @author Dafe Simonek
-*/
-public final class OutputWindowAction extends CallableSystemAction {
-
- public void performAction() {
- OutputWindow output = OutputWindow.findDefault();
- output.open();
- output.requestActive();
- }
-
- @Override
- protected boolean asynchronous() {
- return false;
- }
-
- public String getName() {
- return NbBundle.getBundle(OutputWindowAction.class).getString("OutputWindow");
- }
-
- public HelpCtx getHelpCtx() {
- return new HelpCtx (OutputWindowAction.class);
- }
-
- @Override
- protected String iconResource () {
- return "org/netbeans/core/resources/frames/output.png"; // NOI18N
- }
-}
diff --git a/core.output2/src/org/netbeans/core/output2/layer.xml b/core.output2/src/org/netbeans/core/output2/layer.xml
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/layer.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core.output2/src/org/netbeans/core/output2/resources/output.settings b/core.output2/src/org/netbeans/core/output2/resources/output.settings
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/resources/output.settings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/core.output2/src/org/netbeans/core/output2/resources/output.wsmode b/core.output2/src/org/netbeans/core/output2/resources/output.wsmode
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/resources/output.wsmode
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core.output2/src/org/netbeans/core/output2/resources/output.wstcgrp b/core.output2/src/org/netbeans/core/output2/resources/output.wstcgrp
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/resources/output.wstcgrp
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/core.output2/src/org/netbeans/core/output2/resources/output.wstcref b/core.output2/src/org/netbeans/core/output2/resources/output.wstcref
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/resources/output.wstcref
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputTab.java b/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputTab.java
--- a/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputTab.java
+++ b/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputTab.java
@@ -255,5 +255,4 @@
JButton[] getToolbarButtons() {
return buttons;
}
-
}
diff --git a/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java b/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java
deleted file mode 100644
--- a/core.output2/src/org/netbeans/core/output2/ui/AbstractOutputWindow.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2008 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-2006 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.netbeans.core.output2.ui;
-
-import java.awt.event.MouseEvent;
-import javax.swing.border.Border;
-import org.netbeans.core.output2.Controller;
-import org.openide.util.Utilities;
-import org.openide.windows.TopComponent;
-import org.openide.awt.TabbedPaneFactory;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
-import java.lang.reflect.Method;
-import javax.swing.plaf.TabbedPaneUI;
-import org.openide.awt.MouseUtils;
-import org.openide.util.NbBundle;
-
-/**
- * A panel which, if more than one AbstractOutputTab is added to it, instead
- * adds additional views to an internal tabbed pane.
- *
- * @author Tim Boudreau
- */
-public abstract class AbstractOutputWindow extends TopComponent implements ChangeListener, PropertyChangeListener {
- protected JTabbedPane pane = TabbedPaneFactory.createCloseButtonTabbedPane();
- private static final String ICON_PROP = "tabIcon"; //NOI18N
- private JToolBar toolbar = null;
- private JPopupMenu popupMenu;
-
- /** Creates a new instance of AbstractOutputWindow */
- public AbstractOutputWindow() {
- pane.addChangeListener(this);
- pane.addPropertyChangeListener(TabbedPaneFactory.PROP_CLOSE, this);
- setFocusable(true);
- toolbar = new JToolBar();
- toolbar.setOrientation(JToolBar.VERTICAL);
- toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.Y_AXIS));
- toolbar.setFloatable(false);
- Insets ins = toolbar.getMargin();
- JButton sample = new JButton();
- sample.setBorderPainted(false);
- sample.setOpaque(false);
- sample.setText(null);
- sample.setIcon(new Icon() {
- public int getIconHeight() {
- return 16;
- }
- public int getIconWidth() {
- return 16;
- }
- public void paintIcon(Component c, Graphics g, int x, int y) {
- }
- });
- toolbar.add(sample);
- Dimension buttonPref = sample.getPreferredSize();
- Dimension minDim = new Dimension(buttonPref.width + ins.left + ins.right, buttonPref.height + ins.top + ins.bottom);
- toolbar.setMinimumSize(minDim);
- toolbar.setPreferredSize(minDim);
- toolbar.remove(sample);
- setLayout(new BorderLayout());
- add(toolbar, BorderLayout.WEST);
- toolbar.setBorder(new VariableRightBorder(pane));
- toolbar.setBorderPainted(true);
-
- popupMenu = new JPopupMenu();
- popupMenu.add(new Close());
- popupMenu.add(new CloseAll());
- popupMenu.add(new CloseOthers());
- pane.addMouseListener(new MouseUtils.PopupMouseAdapter() {
-
- @Override
- protected void showPopup(MouseEvent evt) {
- popupMenu.show(AbstractOutputWindow.this, evt.getX(), evt.getY());
- }
- });
- }
-
- public void propertyChange(PropertyChangeEvent pce) {
- if (TabbedPaneFactory.PROP_CLOSE.equals(pce.getPropertyName())) {
- AbstractOutputTab tab = (AbstractOutputTab) pce.getNewValue();
- closeRequest(tab);
- }
- }
-
- protected abstract void closeRequest(AbstractOutputTab tab);
-
- protected abstract void removed(AbstractOutputTab view);
-
- @Override
- protected void addImpl(Component c, Object constraints, int idx) {
- setFocusable(false);
- Component focusOwner =
- KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
- boolean hadFocus = hasFocus() || isAncestorOf(focusOwner);
-
- synchronized (getTreeLock()) {
- if (c instanceof AbstractOutputTab) {
- AbstractOutputTab aop = getInternalTab();
- if (aop != null) {
- if (aop == c) {
- return;
- }
- super.remove(aop);
- assert pane.getParent() != this;
- pane.add(aop);
- setTabIcon(aop, (Icon)aop.getClientProperty(ICON_PROP));
- pane.add(c);
- setTabIcon((AbstractOutputTab)c, (Icon)((AbstractOutputTab)c).getClientProperty(ICON_PROP));
-
- super.addImpl(pane, constraints, idx);
- updateSingletonName(null);
- revalidate();
- } else if (pane.getParent() == this) {
- pane.add(c);
- setTabIcon((AbstractOutputTab) c, (Icon)((AbstractOutputTab)c).getClientProperty(ICON_PROP));
- revalidate();
- } else {
- super.addImpl(c, constraints, idx);
- setTabIcon((AbstractOutputTab) c, (Icon)((AbstractOutputTab)c).getClientProperty(ICON_PROP));
- setToolbarButtons(((AbstractOutputTab)c).getToolbarButtons());
- //#48819 - a bit obscure usecase, but revalidate() is call in the if branches above as well..
- revalidate();
- }
- if (hadFocus) {
- //Do not call c.requestFocus() directly, it can be
- //discarded when adding tabs and focus will go to null.
- //@see AbstractOutputWindow.requestFocus()
- requestFocus();
- }
-
- return;
- }
- super.addImpl(c, constraints, idx);
- }
- if (getComponentCount() == 2 && getComponent(1) instanceof AbstractOutputTab) {
- updateSingletonName(getComponent(1).getName());
- }
- revalidate();
- }
-
- public final AbstractOutputTab[] getTabs() {
- ArrayList al =
- new ArrayList(pane.getParent() == this ? pane.getTabCount() : getComponentCount());
- if (pane.getParent() == this) {
- int tabs = pane.getTabCount();
- for (int i=0; i < tabs; i++) {
- Component c = pane.getComponentAt(i);
- if (c instanceof AbstractOutputTab) {
- al.add((AbstractOutputTab)c);
- }
- }
- } else {
- Component[] c = getComponents();
- for (int i=0; i < c.length; i++) {
- if (c[i] instanceof AbstractOutputTab) {
- al.add((AbstractOutputTab)c[i]);
- }
- }
- }
- AbstractOutputTab[] result = new AbstractOutputTab[al.size()];
- return al.toArray(result);
- }
-
-
- @Override
- public void remove(Component c) {
- AbstractOutputTab removedSelectedView = null;
- synchronized (getTreeLock()) {
- if (c.getParent() == pane && c instanceof AbstractOutputTab) {
- if (c == pane.getSelectedComponent()) {
- if (Controller.LOG) Controller.log("Selected view is being removed: " + c.getName());
- removedSelectedView = (AbstractOutputTab) c;
- }
- checkWinXPLFBug();
- pane.remove(c);
- if (pane.getTabCount() == 1) {
- Component comp = pane.getComponentAt(0);
- pane.remove(comp);
- super.remove(pane);
- add(comp);
- updateSingletonName(c.getName());
- setToolbarButtons(((AbstractOutputTab)comp).getToolbarButtons());
- revalidate();
- }
- } else {
- if (c == getSelectedTab()) {
- removedSelectedView = (AbstractOutputTab) c;
- }
- super.remove(c);
- setToolbarButtons(new JButton[0]);
- updateSingletonName(null);
- }
- if (removedSelectedView != null) {
- fire(removedSelectedView);
- }
- }
- if (c instanceof AbstractOutputTab && c.getParent() == null) {
- removed((AbstractOutputTab) c);
- }
- if (getComponentCount() == 2 && getComponent(1) instanceof AbstractOutputTab) {
- updateSingletonName(getComponent(1).getName());
- }
- revalidate();
- setFocusable(getComponentCount() == 1);
- }
-
- private AbstractOutputTab getInternalTab() {
- Component[] c = getComponents();
- for (int i=0; i < c.length; i++) {
- if (c[i] instanceof AbstractOutputTab) {
- return (AbstractOutputTab) c[i];
- }
- }
- return null;
- }
-
- public final AbstractOutputTab getSelectedTab() {
- if (pane.getParent() == this) {
- return (AbstractOutputTab) pane.getSelectedComponent();
- } else {
- return getInternalTab();
- }
- }
-
- public void setSelectedTab(AbstractOutputTab op) {
- assert (op.getParent() == this || op.getParent() == pane);
- if (Controller.LOG) {
- Controller.log("SetSelectedTab: " + op + " parent is " + op.getParent());
- }
- if (pane.getParent() == this && op != pane.getSelectedComponent()) {
- pane.setSelectedComponent(op);
- }
-
- getActionMap().setParent(op.getActionMap());
- }
-
- public void setTabTitle(AbstractOutputTab tab, String name) {
- if (tab.getParent() == pane) {
- int index = pane.indexOfComponent(tab);
- if (Controller.LOG) {
- Controller.log("setTabTitle: #" + index + " '" + pane.getTitleAt(index) + "' -> '" + name + "'");
- }
- pane.setTitleAt(index, name);
- } else if (tab.getParent() == this) {
- updateSingletonName(name);
- }
- tab.setName(name);
- }
-
- public void setTabIcon(AbstractOutputTab tab, Icon icon) {
- if (icon != null) {
- tab.putClientProperty(ICON_PROP, icon);
- if (pane.indexOfComponent(tab) != -1) {
- pane.setIconAt(pane.indexOfComponent(tab), icon);
- pane.setDisabledIconAt(pane.indexOfComponent(tab), icon);
- }
- }
- }
-
- @SuppressWarnings("deprecation")
- @Override public void requestFocus() {
- if (!isShowing()) {
- return;
- }
- AbstractOutputTab tab = getSelectedTab();
- if (tab != null && pendingFocusRunnable == null) {
- //Adding the tab may yet need to be processed, so escape the
- //current event loop via invokeLater()
- pendingFocusRunnable = new Runnable() {
- public void run() {
- AbstractOutputTab tab = getSelectedTab();
- if (tab != null) {
- tab.requestFocus();
- }
- pendingFocusRunnable = null;
- }
- };
- SwingUtilities.invokeLater(pendingFocusRunnable);
- } else {
- super.requestFocus();
- }
- }
-
- private Runnable pendingFocusRunnable = null;
-
- /**
- * Updates the component name to include the name of a tab. If passed null
- * arguments, should update the name to the default which does not include the
- * tab name.
- *
- * @param name A name for the tab
- */
- protected abstract void updateSingletonName(String name);
-
-
- private AbstractOutputTab lastKnownSelection = null;
- protected void fire(AbstractOutputTab formerSelection) {
- AbstractOutputTab selection = getSelectedTab();
- if (formerSelection != selection) {
- selectionChanged(formerSelection, selection);
- lastKnownSelection = selection;
- if (selection != null) {
- setToolbarButtons(selection.getToolbarButtons());
- } else {
- setToolbarButtons(new JButton[0]);
- }
- }
- }
-
- private void setToolbarButtons(JButton[] buttons) {
- toolbar.removeAll();
- for (int i = 0; i < buttons.length; i++) {
- toolbar.add(buttons[i]);
- }
- toolbar.revalidate();
- toolbar.repaint();
-
- }
-
- public void stateChanged(ChangeEvent e) {
- if (pane.getSelectedComponent() instanceof AbstractOutputPane) {
- ((AbstractOutputPane) pane.getSelectedComponent()).ensureCaretPosition();
- }
- fire(lastKnownSelection);
- }
-
- protected abstract void selectionChanged(AbstractOutputTab former, AbstractOutputTab current);
-
- private final boolean isGtk = "GTK".equals(UIManager.getLookAndFeel().getID()) || //NOI18N
- UIManager.getLookAndFeel().getClass().getSuperclass().getName().indexOf("Synth") != -1; //NOI18N
- /**
- * Overridden to fill in the background color, since Synth/GTKLookAndFeel ignores
- * setOpaque(true).
- * @see http://www.netbeans.org/issues/show_bug.cgi?id=43024
- */
- @Override
- public void paint(Graphics g) {
- if (isGtk) {
- //Presumably we can get this fixed for JDK 1.5.1
- Color c = getBackground();
- if (c == null) {
- c = java.awt.Color.WHITE;
- }
- g.setColor(c);
- g.fillRect(0, 0, getWidth(), getHeight());
- }
- super.paint(g);
- }
-
- /**
- * Set next tab relatively to the given tab. If the give tab is the last one
- * the first is selected.
- *
- * @param tab relative tab
- */
- public final void selectNextTab(AbstractOutputTab tab) {
- AbstractOutputTab[] tabs = this.getTabs();
- if (tabs.length > 1) {
- int nextTabIndex = getSelectedTabIndex(tabs, tab) + 1;
- if (nextTabIndex > (tabs.length - 1)) {
- nextTabIndex = 0;
- }
- this.setSelectedTab(tabs[nextTabIndex]);
- }
- }
-
- /**
- * Set previous tab relatively to the given tab. If the give tab is the
- * first one the last is selected.
- *
- * @param tab relative tab
- */
- public final void selectPreviousTab(AbstractOutputTab tab) {
- AbstractOutputTab[] tabs = this.getTabs();
- if (tabs.length > 1) {
- int prevTabIndex = getSelectedTabIndex(tabs, tab) - 1;
- if (prevTabIndex < 0) {
- prevTabIndex = tabs.length - 1;
- }
- this.setSelectedTab(tabs[prevTabIndex]);
- }
- }
-
- private int getSelectedTabIndex(AbstractOutputTab[] tabs, AbstractOutputTab tab) {
- for (int i = 0; i < tabs.length; i++) {
- if (tabs[i] == tab) {
- return i;
- }
- }
- return -1;
- }
-
- // JDK 1.5, Win L&F - removing a tab causes a relayout and that uses onl data in UI class,
- // causing it to throw ArrayOutofbounds if removing the last one.
- // hacking around it by resetting the bad old data before removal.
- // #56628
- private void checkWinXPLFBug() {
- if ("Windows".equals(UIManager.getLookAndFeel().getID())) { //NOi18N
- TabbedPaneUI ui = pane.getUI();
- try {
- Method method = ui.getClass().getDeclaredMethod("setRolloverTab", new Class[] {Integer.TYPE}); //NOI18N
- if (method != null) {
- method.setAccessible(true);
- method.invoke(ui, new Object[] { new Integer(-1) });
- method.setAccessible(false);
- }
- } catch (Exception exc) {
- // well let's cross fingers and see..
- }
- }
- }
-
- private class VariableRightBorder implements Border {
-
- private JTabbedPane pane;
-
- public VariableRightBorder(JTabbedPane pane) {
- this.pane = pane;
- }
-
- public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
- if (pane.getParent() != AbstractOutputWindow.this) {
- Color old = g.getColor();
- g.setColor(getColor());
- g.drawLine(x + width - 1, y, x + width - 1, y + height);
- g.setColor(old);
- }
- }
-
- public Color getColor() {
- if (Utilities.isMac()) {
- Color c1 = UIManager.getColor("controlShadow");
- Color c2 = UIManager.getColor("control");
- return new Color((c1.getRed() + c2.getRed()) / 2,
- (c1.getGreen() + c2.getGreen()) / 2,
- (c1.getBlue() + c2.getBlue()) / 2);
- } else {
- return UIManager.getColor("controlShadow");
- }
- }
-
- public Insets getBorderInsets(Component c) {
- if (pane.getParent() == AbstractOutputWindow.this) {
- return new Insets(0,0,0,0);
- }
- return new Insets(0, 0, 0, 2);
- }
-
- public boolean isBorderOpaque() {
- return true;
- }
-
- }
-
- private void closeOtherTabs() {
- AbstractOutputTab[] tabs = getTabs();
- AbstractOutputTab curTab = getSelectedTab();
- for (int i = 0; i < tabs.length; i++) {
- AbstractOutputTab tab = tabs[i];
- if (tab != curTab) {
- closeRequest(tab);
- }
- }
- }
-
- private void closeAllTabs() {
- AbstractOutputTab[] tabs = getTabs();
- for (int i = 0; i < tabs.length; i++) {
- closeRequest(tabs[i]);
- }
- }
-
- private class Close extends AbstractAction {
-
- public Close() {
- super(NbBundle.getMessage(AbstractOutputWindow.class, "LBL_Close"));
- }
-
- public void actionPerformed(ActionEvent e) {
- closeRequest(getSelectedTab());
- }
- }
-
- private class CloseAll extends AbstractAction {
-
- public CloseAll() {
- super(NbBundle.getMessage(AbstractOutputWindow.class, "LBL_CloseAll"));
- }
-
- public void actionPerformed(ActionEvent e) {
- closeAllTabs();
- }
- }
-
- private class CloseOthers extends AbstractAction {
-
- public CloseOthers() {
- super(NbBundle.getMessage(AbstractOutputWindow.class, "LBL_CloseOthers"));
- }
-
- public void actionPerformed(ActionEvent e) {
- closeOtherTabs();
- }
- }
-}
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
@@ -43,9 +43,15 @@
import java.awt.BorderLayout;
import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import junit.framework.TestCase;
+import org.openide.util.Exceptions;
+import org.openide.windows.IOContainer;
/**
*
@@ -57,40 +63,38 @@
super(testName);
}
- private OutputWindow win;
+ private IOContainer container;
private NbIO io;
- private OutWriter out = null;
JFrame jf = null;
OutputTab tab = null;
OutputPane pane = null;
+ @Override
protected void setUp() throws java.lang.Exception {
-// Controller.logStdOut = true;
-// Controller.log = true;
-
- jf = new JFrame();
- win = new OutputWindow();
- OutputWindow.DEFAULT = win;
- jf.getContentPane().setLayout (new BorderLayout());
- jf.getContentPane().add (win, BorderLayout.CENTER);
- jf.setBounds (20, 20, 700, 300);
- io = (NbIO) new NbIOProvider().getIO ("Test", false);
- SwingUtilities.invokeAndWait (new Shower());
- io.select();
- sleep();
- sleep();
- tab = (OutputTab) win.getSelectedTab();
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ public void run() {
+ container = IOContainer.getDefault();
+ jf = new JFrame();
+ jf.getContentPane().setLayout(new BorderLayout());
+ jf.getContentPane().add(getIOWindow(), BorderLayout.CENTER);
+ jf.setBounds(20, 20, 700, 300);
+ jf.setVisible(true);
+ io = (NbIO) new NbIOProvider().getIO("Test", false);
+ io.select();
+ tab = (OutputTab) container.getSelected();
+ pane = (OutputPane) tab.getOutputPane();
+ }
+ });
if (tab == null) {
- fail ("Failed in setup - selected tab was null");
+ fail("Failed in setup - selected tab was null");
}
- pane = (OutputPane) tab.getOutputPane();
- sleep();
}
+ @Override
protected void tearDown() {
tab = null;
pane = null;
- out = null;
if (jf != null) {
jf.dispose();
}
@@ -98,9 +102,9 @@
if (io != null) {
NbIOProvider.dispose(io);
}
+ io.closeInputOutput();
io = null;
- win = null;
- OutputWindow.DEFAULT = null;
+ container = null;
sleep();
}
@@ -120,24 +124,18 @@
private final void dosleep() {
try {
- Thread.currentThread().sleep(200);
+ Thread.sleep(200);
SwingUtilities.invokeAndWait (new Runnable() {
public void run() {
System.currentTimeMillis();
}
});
- Thread.currentThread().sleep(200);
+ Thread.sleep(200);
} catch (Exception e) {
fail (e.getMessage());
}
}
- public class Shower implements Runnable {
- public void run() {
- jf.setVisible(true);
- }
- }
-
public void testGetErr() throws Exception {
System.out.println("testGetOut");
ErrWriter err = io.writer().err();
@@ -260,11 +258,9 @@
sleep();
writer.close();
sleep();
-
io.closeInputOutput();
sleep();
-
- assertNull ("Should be no selected tab after closeInputOutput", win.getSelectedTab());
+ assertNull ("Should be no selected tab after closeInputOutput", getSelectedTab());
}
public void testFilesCleanedUp() throws Exception {
@@ -320,5 +316,51 @@
assertFalse ("Reset on a used writer should replace its underlying output", writer.out() == out);
}
+
+ static JComponent getIOWindow() {
+ IOContainer container = IOContainer.getDefault();
+ JComponent comp = null;
+ try {
+ try {
+ Field f = container.getClass().getDeclaredField("provider");
+ f.setAccessible(true);
+ IOContainer.Provider prov = (IOContainer.Provider) f.get(container);
+ Method m = prov.getClass().getDeclaredMethod("impl", new Class[0]);
+ m.setAccessible(true);
+ comp = (JComponent) m.invoke(prov);
+ } catch (InvocationTargetException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (NoSuchMethodException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IllegalArgumentException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IllegalAccessException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ } catch (NoSuchFieldException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (SecurityException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return comp;
+ }
+
+ JComponent getSelectedTab() {
+ class R implements Runnable {
+ JComponent tab;
+ public void run() {
+ tab = container.getSelected();
+ }
+ }
+ R r = new R();
+ try {
+ SwingUtilities.invokeAndWait(r);
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (InvocationTargetException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return r.tab;
+ }
}
diff --git a/core.output2/test/unit/src/org/netbeans/core/output2/OutputWindowTest.java b/core.output2/test/unit/src/org/netbeans/core/output2/OutputWindowTest.java
deleted file mode 100644
--- a/core.output2/test/unit/src/org/netbeans/core/output2/OutputWindowTest.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2007 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-2006 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.netbeans.core.output2;
-
-import java.awt.BorderLayout;
-import java.awt.Point;
-import java.awt.event.ActionEvent;
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-import junit.framework.TestCase;
-import org.netbeans.core.output2.ui.AbstractOutputPane;
-import org.netbeans.core.output2.ui.AbstractOutputTab;
-import org.openide.windows.OutputEvent;
-import org.openide.windows.OutputListener;
-
-/**
- *
- * @author Tim Boudreau
- */
-public class OutputWindowTest extends TestCase {
-
- public OutputWindowTest(String testName) {
- super(testName);
- }
-
- private OutputWindow win;
- private NbIO io;
- private OutWriter out = null;
- JFrame jf = null;
- NbIOProvider provider = null;
-
- protected void setUp() throws Exception {
- jf = new JFrame();
- win = new OutputWindow();
- OutputWindow.DEFAULT = win;
- jf.getContentPane().setLayout (new BorderLayout());
- jf.getContentPane().add (win, BorderLayout.CENTER);
- jf.setBounds (20, 20, 700, 300);
- provider = new NbIOProvider();
- io = (NbIO) provider.getIO ("Test", false);
- SwingUtilities.invokeAndWait (new Shower());
- }
-
- private final void sleep() {
- try {
- Thread.currentThread().sleep(200);
- SwingUtilities.invokeAndWait (new Runnable() {
- public void run() {
- System.currentTimeMillis();
- }
- });
- Thread.currentThread().sleep(200);
- } catch (Exception e) {
- fail (e.getMessage());
- }
- }
-
- public class Shower implements Runnable {
- public void run() {
- jf.setVisible(true);
- }
- }
-
- public void testTabsShownAndHidden() {
- System.out.println ("testTabsShownAndHidden");
- int n = win.getTabs().length;
- assertTrue ("Number of tabs should be 1, not " + n, n == 1);
- NbIO io2 = (NbIO) provider.getIO("Test2", true);
- sleep();
- n = win.getTabs().length;
- assertTrue ("Number of tabs should be 2, not " + n, n == 2);
-
- io2.closeInputOutput();
- sleep();
-
- n = win.getTabs().length;
- assertTrue ("After closeInputOutput on second tab, number of tabs should be 1, not " + n, n == 1);
- }
-
- public void testTabNamesUpdatedCorrectly() throws Exception {
- System.out.println ("testTabNamesUpdatedCorrectly");
- io.select();
- for (int i=0; i < 100; i++) {
- io.getOut().println ("Here is some text we can delete");
- }
- sleep();
- sleep();
- sleep();
- sleep();
- io.getOut().flush();
-
- assertTrue ("Tab name should be html but is " + win.getDisplayName(),
- win.getHtmlDisplayName() != null && win.getHtmlDisplayName().indexOf("<") >= 0);
-
- io.getOut().close();
- sleep();
- sleep();
- assertFalse ("Tab name should not be html", win.getHtmlDisplayName() != null && win.getHtmlDisplayName().indexOf("<") >= 0);
-
- final OutputTab tab = (OutputTab) win.getSelectedTab();
-
- //Ensure the actions are paying attention
- SwingUtilities.invokeLater (new Runnable() {
- public void run() {
- win.getController().postPopupMenu(win, tab, new Point(0,0), tab);
- win.getController().clearAction.actionPerformed(new ActionEvent (tab, ActionEvent.ACTION_PERFORMED, "clear"));
- }
- });
- sleep();
- sleep();
- assertFalse ("Tab name should not be html", win.getHtmlDisplayName() != null && win.getHtmlDisplayName().indexOf("<") >= 0);
-
- io.getOut().reset();
- sleep();
- io.getOut().println("And here is some more text");
- sleep();
-
- assertTrue ("Tab name should be html", win.getHtmlDisplayName() != null && win.getHtmlDisplayName().indexOf("<") >= 0);
-
- io.getOut().close();
- sleep();
- sleep();
- assertFalse ("Tab name should not be html", win.getHtmlDisplayName() != null && win.getHtmlDisplayName().indexOf("<") >= 0);
-
- }
-
-// mkleint: this test is non deterministic, teh sleep() calls are not a guarantee for reproducibility.
-
-// public void testScrollToEnd() throws Exception {
-// System.out.println("testScrollToEnd");
-// NbIO io2 = (NbIO) provider.getIO("ScrollDown", true);
-// io2.select();
-// sleep();
-// AbstractOutputTab tab = win.getSelectedTab();
-// assertNotNull("Selected tab should not be null", tab);
-//
-// AbstractOutputPane pane = tab.getOutputPane();
-// OutputDocument doc = (OutputDocument) pane.getDocument();
-//
-// for (int i = 0; i < 20; i++) {
-// io2.getOut().println("Hellooo... ");
-// }
-// sleep();
-// int end = doc.getEndPosition().getOffset();
-// int carretPos = pane.getCaretPos();
-// assertEquals("Caret position should be at the end (end: " + end
-// + ", carretPos: " + carretPos + ")",
-// end, carretPos);
-// io2.closeInputOutput();
-// sleep();
-// }
-
- public void testAbleToRetrieveSameInputOutputInstance() {
- System.out.println ("testAbleToRetrieveSameInputOutputInstance");
- NbIO io2 = (NbIO) provider.getIO("Test2", true);
- sleep();
-
- NbIO io3 = (NbIO) provider.getIO("Test", false);
- assertSame ("Requesting a tab with a name already in use should return the original InputOutput", io3, io);
-
- NbIO io4 = (NbIO) provider.getIO("Test2", false);
- assertSame ("Requesting a second tab with a name already in use should return the same InputOutput", io4, io2);
-
- NbIO io5 = (NbIO) provider.getIO("Test", true);
- assertNotSame ("Requesting a new InputOutput with a name matching another tab should not return the other tab", io5, io);
- }
-
- public void testIOclosed() {
- System.out.println ("testIOclosed");
- assertFalse ("If a tab is showing, its InputOutput should not say it is closed", io.isClosed());
- NbIO io2 = (NbIO) provider.getIO("Test2", true);
- sleep();
- assertFalse ("If a tab is showing, its InputOutput should not say it is closed", io2.isClosed());
-
- assertFalse ("Adding another tab should not make the first tab think it has been closed, its InputOutput should not say it is closed", io.isClosed());
-
- io2.closeInputOutput();
- sleep();
-
- assertTrue ("After programmatically closing a tab, its InputOutput should return true from isClosed()", io2.isClosed());
-
- io2 = (NbIO) provider.getIO("Test3", true);
- sleep();
-
- NbWriter writer = (NbWriter) io.getOut();
- writer.println ("Hello world");
- sleep();
- OutWriter outwriter = writer.out();
-
- assertFalse ("After removing and adding another tab, the last tab added should not say it has been closed", io2.isClosed());
- io.select();
- sleep();
-
- final OutputTab tab = (OutputTab) win.getSelectedTab();
- assertSame ("After calling InputOutput.select(), a tab owing the IO it was requested on should be the selected tab", tab.getIO(), io);
-
- //Ensure the actions are paying attention
- SwingUtilities.invokeLater (new Runnable() {
- public void run() {
- win.getController().postPopupMenu(win, tab, new Point(0,0), tab);
- win.getController().clearAction.actionPerformed(new ActionEvent (tab, ActionEvent.ACTION_PERFORMED, "clear"));
- }
- });
- sleep();
- sleep();
-
- io.getOut().println ("Goodbye world");
-
- assertSame ("OutputWriter should not be replaced by calling clearing/reset() on it", writer, io.getOut());
- assertNotSame ("Underlying OutWriter should be replaced by calling reset() on a used NbWriter", outwriter, writer.out());
- }
-
-
- public void testListenersCleared() throws Exception {
-// Controller.log = true;
-// Controller.logStdOut = true;
-
- System.out.println ("testListenersCleared");
- io.select();
- io.getOut().println ("Helloooooo....");
- sleep();
- L[] ls = new L[20];
- for (int i=0; i < ls.length; i++) {
- L l = new L();
- io.getOut().println ("Hyperlink " + i, l);
- ls[i] = l;
- }
- sleep();
-
- for (int i=0; i < ls.length; i++) {
- ls[i].assertNotCleared("Newly written listeners should be cleared");
- }
-
- sleep();
-
- final OutputTab tab = (OutputTab) win.getSelectedTab();
- assertNotNull ("Selected tab should not be null", tab);
- assertSame ("After calling InputOutput.select(), a tab owing the IO it was requested on should be the selected tab", tab.getIO(), io);
-
- //Ensure the actions are paying attention
- SwingUtilities.invokeLater (new Runnable() {
- public void run() {
- win.getController().postPopupMenu(win, tab, new Point(0,0), tab);
- win.getController().clearAction.actionPerformed(new ActionEvent (tab, ActionEvent.ACTION_PERFORMED, "clear"));
- }
- });
- sleep();
- sleep();
-
- for (int i=0; i < ls.length; i++) {
- ls[i].assertCleared("After invoking the GUI's clear action, listeners should be cleared");
- }
-
- L[] ls2 = new L[20];
- for (int i=0; i < ls2.length; i++) {
- L l = new L();
- io.getOut().println ("Second round of hyperlinks " + i, l);
- ls2[i] = l;
- }
- sleep();
-
- for (int i=0; i < ls2.length; i++) {
- ls2[i].assertNotCleared("The second round of listeners were cleared prematurely");
- }
-
- //Make sure the old ones are untouched
- for (int i=0; i < ls.length; i++) {
- //These should not have been touched. The last assertCleared() cleared the cleared flag :-o
- ls[i].assertNotCleared("Already cleared listeners should be unreferenced and should not be cleared a second time");
- }
-
- //Ensure the actions are paying attention
- SwingUtilities.invokeLater (new Runnable() {
- public void run() {
- win.getController().postPopupMenu(win, tab, new Point(0,0), tab);
- win.getController().clearAction.actionPerformed(new ActionEvent (tab, ActionEvent.ACTION_PERFORMED, "clear"));
- }
- });
- sleep();
- sleep();
-
- for (int i=0; i < ls2.length; i++) {
- ls2[i].assertCleared("After invoking the Clear Output action a second time, the newly written listeners were not cleared - " + i);
- }
-
- //Make sure the old ones are untouched again - clearing a new set of lines should not
- //touch the old listeners - they are already forgotten
- for (int i=0; i < ls.length; i++) {
- //These should not have been touched. The last assertCleared() cleared the cleared flag :-o
- ls[i].assertNotCleared("Already cleared listeners should not be touched by clearing or writing new data");
- }
-
- L[] ls3 = new L[20];
- for (int i=0; i < ls3.length; i++) {
- L l = new L();
- io.getOut().println ("Third round of hyperlinks " + i, l);
- ls3[i] = l;
- }
- sleep();
-
- for (int i=0; i < ls3.length; i++) {
- ls3[i].assertNotCleared("Third round of writes with listeners had those listeners prematurely cleared");
- }
-
- //This time we test it using reset(), not programmatically invoking the GUI call to do the same
- io.reset();
- sleep();
- sleep();
-
- for (int i=0; i < ls3.length; i++) {
- ls3[i].assertCleared("InputOutput.reset() should cause all OutputListeners to be cleared");
- }
-
- io = (NbIO) provider.getIO("Another tab", true);
-
- L[] ls4 = new L[20];
- for (int i=0; i < ls4.length; i++) {
- L l = new L();
- io.getOut().println ("Third round of hyperlinks " + i, l);
- ls4[i] = l;
- }
- sleep();
-
- for (int i=0; i < ls4.length; i++) {
- ls4[i].assertNotCleared("Premature clear");
- }
-
- io.getOut().close(); //Close the stream
- sleep();
- //And this time with closeInputOutput()
- io.closeInputOutput();
- sleep();
- sleep();
- sleep();
- sleep();
- sleep();
-
- for (int i=0; i < ls4.length; i++) {
- ls4[i].assertCleared("CloseInputOutput should cause all OutputListeners to be cleared");
- }
- }
-
-
- public class L implements OutputListener {
- private OutputEvent clearedEvent = null;
- public void assertCleared(String msg) {
- assertNotNull (msg, clearedEvent);
- clearedEvent = null;
- }
-
- public void assertNotCleared(String msg) {
- assertNull (msg, clearedEvent);
- }
-
- public void outputLineSelected(OutputEvent ev) {
- }
-
- public void outputLineAction(OutputEvent ev) {
- }
-
- public void outputLineCleared(OutputEvent ev) {
- clearedEvent = ev;
- }
- }
-
-}
diff --git a/core.output2/test/unit/src/org/netbeans/core/output2/WrappedTextViewTest.java b/core.output2/test/unit/src/org/netbeans/core/output2/WrappedTextViewTest.java
--- a/core.output2/test/unit/src/org/netbeans/core/output2/WrappedTextViewTest.java
+++ b/core.output2/test/unit/src/org/netbeans/core/output2/WrappedTextViewTest.java
@@ -47,17 +47,21 @@
import java.awt.Graphics;
import java.awt.Rectangle;
import java.io.File;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
+import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
import javax.swing.text.View;
import junit.framework.TestCase;
import org.netbeans.core.output2.ui.AbstractOutputPane;
-import org.netbeans.core.output2.ui.AbstractOutputTab;
+import org.openide.util.Exceptions;
import org.openide.util.Utilities;
+import org.openide.windows.IOContainer;
import org.openide.windows.OutputEvent;
import org.openide.windows.OutputListener;
@@ -70,23 +74,30 @@
public WrappedTextViewTest(String testName) {
super(testName);
}
-
- private OutputWindow win;
+
+ IOContainer iowin;
private NbIO io;
- private OutWriter out = null;
JFrame jf = null;
static int testNum;
+ @Override
protected void setUp() throws Exception {
- jf = new JFrame();
- win = new OutputWindow();
- OutputWindow.DEFAULT = win;
- jf.getContentPane().setLayout (new BorderLayout());
- jf.getContentPane().add (win, BorderLayout.CENTER);
- jf.setBounds (20, 20, 700, 300);
- io = (NbIO) new NbIOProvider().getIO ("Test" + testNum++, false);
- SwingUtilities.invokeAndWait (new Shower());
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ public void run() {
+ iowin = IOContainer.getDefault();
+ JComponent wnd = LifecycleTest.getIOWindow();
+ jf = new JFrame();
+ jf.getContentPane().setLayout(new BorderLayout());
+ jf.getContentPane().add(wnd, BorderLayout.CENTER);
+ jf.setBounds(20, 20, 700, 300);
+ jf.setVisible(true);
+ io = (NbIO) new NbIOProvider().getIO("Test" + testNum++, false);
+ }
+ });
+
sleep();
+ io.select();
io.getOut().println ("Test line 1");
sleep();
sleep();
@@ -108,45 +119,56 @@
SwingUtilities.invokeAndWait (new Runnable() {
public void run() {
- win.getSelectedTab().getOutputPane().setWrapped(true);
+ ((OutputTab) iowin.getSelected()).getOutputPane().setWrapped(true);
}
});
}
private final void sleep() {
try {
- Thread.currentThread().sleep(200);
+ Thread.sleep(200);
SwingUtilities.invokeAndWait (new Runnable() {
public void run() {
System.currentTimeMillis();
}
});
- Thread.currentThread().sleep(200);
+ Thread.sleep(200);
} catch (Exception e) {
fail (e.getMessage());
}
}
- public class Shower implements Runnable {
- public void run() {
- jf.setVisible(true);
- }
- }
-
/**
* tests if caret position is computed correctly (see issue #122492)
*/
public void testViewToModel() {
- Graphics g = win.getSelectedTab().getOutputPane().getGraphics();
- FontMetrics fm = g.getFontMetrics(win.getSelectedTab().getOutputPane().getTextView().getFont());
- int charWidth = fm.charWidth('m');
- int charHeight = fm.getHeight();
- int fontDescent = fm.getDescent();
- float x = charWidth * 50;
- float y = charHeight * 1 + fontDescent;
- int charPos = win.getSelectedTab().getOutputPane().getTextView().getUI().getRootView(null).viewToModel(x, y, new Rectangle(), new Position.Bias[]{});
- int expCharPos = (Utilities.getOperatingSystem() & Utilities.OS_WINDOWS_MASK) != 0 ? 45 : 43;
- assertTrue("viewToModel returned wrong value (it would result in bad caret position)!", charPos == expCharPos);
+ final Integer pos1 = new Integer(-2);
+ final Integer pos2 = new Integer(-1);
+ class R implements Runnable {
+ int charPos;
+ int expCharPos;
+ public void run() {
+ AbstractOutputPane pane = ((OutputTab) iowin.getSelected()).getOutputPane();
+ Graphics g = pane.getGraphics();
+ FontMetrics fm = g.getFontMetrics(pane.getTextView().getFont());
+ int charWidth = fm.charWidth('m');
+ int charHeight = fm.getHeight();
+ int fontDescent = fm.getDescent();
+ float x = charWidth * 50;
+ float y = charHeight * 1 + fontDescent;
+ charPos = pane.getTextView().getUI().getRootView(null).viewToModel(x, y, new Rectangle(), new Position.Bias[]{});
+ expCharPos = (Utilities.getOperatingSystem() & Utilities.OS_WINDOWS_MASK) != 0 ? 45 : 43;
+ }
+ }
+ R r = new R();
+ try {
+ SwingUtilities.invokeAndWait(r);
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (InvocationTargetException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ assertTrue("viewToModel returned wrong value (it would result in bad caret position)!", r.charPos == r.expCharPos);
}
public void testModelToView() throws Exception {
@@ -157,87 +179,88 @@
//FOR PRODUCTION AND USE IT JUST FOR DEBUGGING
return;
}
-
- AbstractOutputTab tab = win.getSelectedTab();
- AbstractOutputPane pane = tab.getOutputPane();
- JTextComponent text = pane.getTextView();
-
- View view = text.getUI().getRootView(text);
-
- Rectangle r = new Rectangle(1,1,1,1);
- Rectangle alloc = new Rectangle();
-
- java.awt.image.ColorModel model = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().
- getDefaultScreenDevice().getDefaultConfiguration().getColorModel(java.awt.Transparency.TRANSLUCENT);
- java.awt.image.BufferedImage img = new java.awt.image.BufferedImage(model,
- model.createCompatibleWritableRaster(text.getWidth() + 10, text.getHeight() + 10), model.isAlphaPremultiplied(), null);
-
- text.paint (img.getGraphics());
- boolean errorsFound = false;
- ArrayList errors = new ArrayList();
-
- System.out.println("...scanning " + (text.getWidth() * text.getHeight() + " pixels to make sure viewToModel() matches modeltoView(). Expect it to take about 10 minutes."));
-
- for (int y=0; y < text.getHeight(); y++) {
- r.y = y;
- for (int x=0; x < text.getWidth(); x++) {
- r.x = x;
- alloc.setBounds (0, 0, text.getWidth(), text.getHeight());
-
- int vtm = view.viewToModel (x, y, alloc, new Position.Bias[1]);
-
- Rectangle mtv = (Rectangle) view.modelToView (vtm, Position.Bias.Forward, vtm, Position.Bias.Forward, new Rectangle (0, 0, text.getWidth(), text.getHeight()));
-
- int xvtm = view.viewToModel (mtv.x, mtv.y, alloc, new Position.Bias[1]);
+ class R implements Runnable {
+ boolean errorsFound;
+ java.awt.image.BufferedImage img;
+ ArrayList errors;
- if (vtm != xvtm) {
- errorsFound = true;
- try {
- errors.add ("ViewToModel(" + x + "," + y + ") returns character position " + vtm + "; modelToView on " + vtm + " returns " + mtv + "; that Rectangle's corner, passed back to viewToModel maps to a different character position: " + xvtm + "\n");
- img.setRGB(x, y, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
- img.setRGB(x-1, y-1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
- img.setRGB(x+1, y-1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
- img.setRGB(x+1, y+1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
- img.setRGB(x-1, y+1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
- } catch (ArrayIndexOutOfBoundsException aioobe) {
- System.err.println("OUT OF BOUNDS: " + x + "," + y + " image width " + img.getWidth() + " img height " + img.getHeight());
+ public void run() {
+ AbstractOutputPane pane = ((OutputTab) iowin.getSelected()).getOutputPane();
+ JTextComponent text = pane.getTextView();
+
+ View view = text.getUI().getRootView(text);
+
+ Rectangle r = new Rectangle(1, 1, 1, 1);
+ Rectangle alloc = new Rectangle();
+
+ java.awt.image.ColorModel model = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().getDefaultConfiguration().getColorModel(java.awt.Transparency.TRANSLUCENT);
+ img = new java.awt.image.BufferedImage(model,
+ model.createCompatibleWritableRaster(text.getWidth() + 10, text.getHeight() + 10), model.isAlphaPremultiplied(), null);
+
+ text.paint(img.getGraphics());
+ errorsFound = false;
+ errors = new ArrayList();
+
+ System.out.println("...scanning " + (text.getWidth() * text.getHeight() + " pixels to make sure viewToModel() matches modeltoView(). Expect it to take about 10 minutes."));
+
+ for (int y = 0; y < text.getHeight(); y++) {
+ r.y = y;
+ for (int x = 0; x < text.getWidth(); x++) {
+ r.x = x;
+ alloc.setBounds(0, 0, text.getWidth(), text.getHeight());
+
+ int vtm = view.viewToModel(x, y, alloc, new Position.Bias[1]);
+
+ Rectangle mtv = null;
+ try {
+ mtv = (Rectangle) view.modelToView(vtm, Position.Bias.Forward, vtm, Position.Bias.Forward, new Rectangle(0, 0, text.getWidth(), text.getHeight()));
+ } catch (BadLocationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ int xvtm = view.viewToModel(mtv.x, mtv.y, alloc, new Position.Bias[1]);
+
+ if (vtm != xvtm) {
+ errorsFound = true;
+ try {
+ errors.add("ViewToModel(" + x + "," + y + ") returns character position " + vtm + "; modelToView on " + vtm + " returns " + mtv + "; that Rectangle's corner, passed back to viewToModel maps to a different character position: " + xvtm + "\n");
+ img.setRGB(x, y, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
+ img.setRGB(x - 1, y - 1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
+ img.setRGB(x + 1, y - 1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
+ img.setRGB(x + 1, y + 1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
+ img.setRGB(x - 1, y + 1, vtm > xvtm ? Color.RED.getRGB() : Color.BLUE.getRGB());
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ System.err.println("OUT OF BOUNDS: " + x + "," + y + " image width " + img.getWidth() + " img height " + img.getHeight());
+ }
+
+ System.err.println(x + "," + y + "=" + vtm + " -> [" + mtv.x + "," + mtv.y + "," + mtv.width + "," + mtv.height + "]->" + xvtm);
+ }
+
+ r.y = y; //just in case
+ r.width = 1;
+ r.height = 1;
}
-
- System.err.println(x + "," + y + "=" + vtm + " -> [" + mtv.x + "," + mtv.y + "," + mtv.width + "," + mtv.height + "]->" + xvtm);
}
-
- r.y = y; //just in case
- r.width = 1;
- r.height = 1;
}
}
+ R r = new R();
+ SwingUtilities.invokeAndWait(r);
- if (errorsFound) {
+ if (r.errorsFound) {
String dir = System.getProperty ("java.io.tmpdir");
if (!dir.endsWith(File.separator)) {
dir += File.separator;
}
String fname = dir + "outputWindowDiffs.png";
- ImageIO.write (img, "png", new File (fname));
+ ImageIO.write (r.img, "png", new File (fname));
fail ("In a wrapped view, some points as mapped by viewToModel do " +
"not map back to the same coordinates in viewToModel. \nA bitmap " +
"of the problem coordinates is saved in " + fname + " Problem" +
- "spots are marked in red and blue.\n" + errors);
+ "spots are marked in red and blue.\n" + r.errors);
}
-
-
-
-/*
- try {
- Thread.currentThread().sleep (40000);
- } catch (Exception e) {}
- */
-
-// WrappedTextView wtv = win.getSelectedTab().getOutputPane().getTextView().getUI().getView();
}
-
-
public class L implements OutputListener {
public void outputLineSelected(OutputEvent ev) {
@@ -248,7 +271,5 @@
public void outputLineCleared(OutputEvent ev) {
}
-
}
-
}
diff --git a/junit/nbproject/project.xml b/junit/nbproject/project.xml
--- a/junit/nbproject/project.xml
+++ b/junit/nbproject/project.xml
@@ -209,6 +209,14 @@
+ org.openide.io
+
+
+
+ 1.15
+
+
+ org.openide.loaders
diff --git a/junit/src/org/netbeans/modules/junit/output/Manager.java b/junit/src/org/netbeans/modules/junit/output/Manager.java
--- a/junit/src/org/netbeans/modules/junit/output/Manager.java
+++ b/junit/src/org/netbeans/modules/junit/output/Manager.java
@@ -306,12 +306,12 @@
/* Called from the AntLogger's thread */
final ResultDisplayHandler displayHandler = getDisplayHandler(session);
+ displayInWindow(session, sessionType, displayHandler, sessionEnd);
if (!sessionEnd) {
displayHandler.displayMessage(message);
} else {
displayHandler.displayMessageSessionFinished(message);
}
- displayInWindow(session, sessionType, displayHandler, sessionEnd);
//
/*
@@ -413,6 +413,8 @@
final ResultWindow window = ResultWindow.getInstance();
if (displayHandler != null) {
window.addDisplayComponent(displayHandler.getDisplayComponent());
+ window.setOutputComp(displayHandler.getOutputComponent());
+ displayHandler.createIO(window.getIOContainer());
}
if (promote) {
window.promote();
diff --git a/junit/src/org/netbeans/modules/junit/output/OutputDocument.java b/junit/src/org/netbeans/modules/junit/output/OutputDocument.java
deleted file mode 100644
--- a/junit/src/org/netbeans/modules/junit/output/OutputDocument.java
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2007 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 2007 Sun Microsystems, Inc.
- */
-
-package org.netbeans.modules.junit.output;
-
-import java.awt.EventQueue;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.event.UndoableEditListener;
-import javax.swing.text.AttributeSet;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.Element;
-import javax.swing.text.Position;
-import javax.swing.text.Segment;
-
-/**
- * Simple document for displaying textual output produced by JUnit tests.
- *
- * @author Marian Petras
- */
-final class OutputDocument implements Document {
-
- static final AttributeSet attrs = new TrivialAttributeSet();
-
- final RootElement rootElement;
-
- private DocElement[] docElements = new DocElement[100];
- private int docElementsCount;
- private final DocElement lastDocElement
- = new DocElement(0, "", false); //NOI18N
- private int length = 0;
-
- private final Position startPosition = new SimplePosition(0);
- private final Position endPosition = new EndPosition();
- private final Element[] rootElements;
-
- private Map