1 19 20 package org.netbeans.core.output; 21 22 import java.util.WeakHashMap ; 23 import java.util.HashSet ; 24 import java.io.PipedWriter ; 25 26 import java.awt.*; 27 import java.awt.event.*; 28 import java.awt.datatransfer.*; 29 import java.beans.PropertyChangeListener ; 30 import java.beans.PropertyChangeEvent ; 31 import java.util.Map ; 32 import java.util.Set ; 33 import javax.swing.AbstractAction ; 34 35 import javax.swing.JPopupMenu ; 36 import javax.swing.JMenuItem ; 37 import javax.swing.JTabbedPane ; 38 import javax.swing.KeyStroke ; 39 import javax.swing.SwingUtilities ; 40 41 import org.openide.ErrorManager; 42 import org.openide.windows.*; 43 import org.openide.util.NbBundle; 44 import org.openide.util.Mutex; 45 import org.openide.util.Utilities; 46 import org.openide.util.WeakSet; 47 import org.openide.util.datatransfer.*; 48 import org.openide.nodes.Node; 49 50 import org.netbeans.lib.terminalemulator.*; 51 52 58 59 public class OutputView extends TopComponent implements PropertyChangeListener , ActionListener { 60 61 62 private static final boolean DEBUG = false; 63 64 public static final String ICON_RESOURCE = 65 "/org/netbeans/core/resources/frames/output.gif"; 67 68 69 70 static final Map ioCache = new WeakHashMap (7); 71 72 73 private static OutputTabInner standard; 74 75 private static final long serialVersionUID = 3276523892250080205L; 76 77 private static Factory factory; 78 79 80 private static OutputView DEFAULT; 81 82 private JTabbedPane tabbedPane; 83 84 85 private Set openedComps = new HashSet (10); 86 87 88 private Set closedComps = new WeakSet(10); 89 90 private String baseName; 91 92 97 private static class State { 98 private final String name; 99 private State(String name) { 100 this.name = name; 101 } 102 public String toString() { return name; } 103 104 public static final State init = new State("init"); 105 public static final State collect = new State("collect"); 106 public static final State pass = new State("pass"); 107 }; 108 109 private static void debug(String s) { 110 if (!DEBUG) return; 111 s = "OutputView:"+s+"\r\n"; try { 113 String dir = outputSettings().getDirectory().getAbsolutePath(); 114 java.io.FileOutputStream fos = new java.io.FileOutputStream (dir + "/debug.log", true); fos.write(s.getBytes()); 116 fos.close(); 117 } catch (java.io.IOException e) { 118 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 119 } 120 } 121 122 private OutputView () { 123 synchronized (OutputView.class) { 124 setActivatedNodes (null); 125 126 setIcon(Utilities.loadImage("org/netbeans/core/resources/outputSettings.gif")); 128 TopComponent.getRegistry().addPropertyChangeListener( 129 org.openide.util.WeakListener.propertyChange(this, TopComponent.getRegistry())); 130 131 getAccessibleContext ().setAccessibleName ( 133 NbBundle.getBundle (OutputView.class).getString ("ACSN_OutputWindow")); 134 getAccessibleContext ().setAccessibleDescription ( 135 NbBundle.getBundle (OutputView.class).getString ("ACSD_OutputWindow")); 136 setBorder(null); 137 setLayout(new BorderLayout()); 138 } 139 } 140 141 private OutputView (String name) { 142 this(); 143 setName(name); 144 baseName = name; 145 } 146 147 public void addNotify() { 148 super.addNotify(); 149 TabHandlePopupListener.install(); 150 } 151 152 153 protected String preferredID () { 154 return "output"; } 156 157 public void removeNotify() { 158 TabHandlePopupListener.uninstall(); 159 super.removeNotify(); 160 } 161 162 public void requestActive () { 163 requestActive(true); 164 } 165 166 public void requestActive(boolean focus) { 167 if (focus) { 172 Component c = getSelectedComponent(); 173 if (c != null) { 174 if (c instanceof OutputTabInner) { 175 boolean focused = c.requestFocusInWindow(); 176 if (focused) { 177 super.requestActive(); 178 } 179 } 180 } 181 } 182 } 183 184 189 public static synchronized OutputView findDefault () { 190 if (DEFAULT == null) { 191 TopComponent tc = WindowManager.getDefault().findTopComponent("output"); if (tc != null) { 193 if (tc instanceof OutputView) { 194 DEFAULT = (OutputView) tc; 195 } else { 196 IllegalStateException exc = new IllegalStateException 198 ("Incorrect settings file. Unexpected class returned." + " Expected:" + OutputView.class.getName() + " Returned:" + tc.getClass().getName()); ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, exc); 202 OutputView.getDefault(); 204 } 205 } else { 206 OutputView.getDefault(); 209 } 210 } 211 return DEFAULT; 212 } 213 214 217 public static synchronized OutputView getDefault () { 218 if (DEFAULT == null) { 219 DEFAULT = new OutputView(NbBundle.getBundle(OutputView.class).getString("CTL_OutputWindow_OutputTab")); 220 } 221 return DEFAULT; 222 } 223 224 225 public static synchronized void discardDefault() { 226 if (DEFAULT != null) { 227 final OutputView last = DEFAULT; 228 DEFAULT = null; 229 Mutex.EVENT.writeAccess(new Runnable () { 230 public void run() { 231 last.clear(); 232 } 233 }); 234 } 235 } 236 237 238 void clear() { 239 discardAllTabs(); 240 closedComps.clear(); 241 close(); 242 } 243 244 246 public int getPersistenceType() { 247 return TopComponent.PERSISTENCE_ALWAYS; 248 } 249 250 public static InputOutput getIO(String name, boolean newIO) { 251 InputOutput inpo = getFactory().getIO(name, newIO); 254 257 return inpo; 258 } 259 260 public static OutputWriter getStdOut() { 261 return getFactory().getStdOut (); 263 } 264 265 267 272 273 277 278 public Object readResolve() throws java.io.ObjectStreamException { 279 return OutputView.getDefault(); 280 } 281 282 283 private JTabbedPane getTabbedPane() { 284 if(tabbedPane == null) { 285 tabbedPane = new JTabbedPane (JTabbedPane.TOP); 286 tabbedPane.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( 287 KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK), 288 "discard"); tabbedPane.getActionMap().put("discard", new DiscardAction()); 290 } 291 return tabbedPane; 292 } 293 294 private class DiscardAction extends AbstractAction { 295 public void actionPerformed (ActionEvent ae) { 296 discardTab(); 297 } 298 } 299 300 302 void requestVisible (final Component c) { 303 307 Mutex.EVENT.readAccess(new Runnable () { 308 public void run() { 309 OutputView.this.requestVisible(); 311 312 317 if (isOpenedInOV(c) && (openedComps.size() > 1)) { 318 320 JTabbedPane tab = getTabbedPane(); 321 if (!c.equals(tab.getSelectedComponent())) { 322 tab.setSelectedComponent(c); 324 setActivatedNodes(((TopComponent) c).getActivatedNodes()); 325 } 326 } 330 333 } 334 }); 335 } 336 337 338 void requestFocus (final Component c) { 339 Mutex.EVENT.readAccess(new Runnable () { 340 public void run() { 341 OutputView.this.requestActive(false); 343 if (isOpenedInOV(c)) { 344 if (openedComps.size() > 1) { 345 JTabbedPane tab = getTabbedPane(); 346 if (!c.equals(tab.getSelectedComponent())) { 347 tab.setSelectedComponent(c); 348 setActivatedNodes(((TopComponent) c).getActivatedNodes()); 349 } 350 } 351 c.requestFocusInWindow(); 352 } 353 } 354 }); 355 } 356 357 360 Component getSelectedComponent () { 361 if (openedComps.size() > 1) { 362 return getTabbedPane().getSelectedComponent(); 363 } else if (openedComps.size() == 1) { 364 return ((Component []) openedComps.toArray(new Component[1]))[0]; 365 } else { 366 return null; 367 } 368 } 369 370 371 375 376 private static OutputSettings outputSettings () { 377 return (OutputSettings)OutputSettings.findObject (OutputSettings.class, true); 378 } 379 380 388 public String toString () { 389 return ""; 390 } 391 392 static synchronized Factory getFactory () { 393 if (factory == null) { 394 factory = new Factory(); 395 } 396 return factory; 397 } 398 399 private static synchronized void initialize () { 400 if (standard == null) { 401 String name = NbBundle.getBundle(OutputView.class).getString("CTL_OutputWindow_OutputTab"); 403 standard = new OutputTabInner(name); 404 standard.putClientProperty("PersistenceType", null); } 407 } 408 409 public static class Factory { Factory () { 411 } 413 414 417 public OutputWriter getStdOut() { 418 initialize(); 421 return standard.getOut(); 422 } 423 424 428 public InputOutput getIO(String name, boolean newIO) { 429 initialize(); 432 if (newIO) { 433 436 return new OutputTabInner(name); 437 } else { 438 InputOutput ino; 439 synchronized(ioCache) { 440 ino = (InputOutput)ioCache.get(name); 441 } 442 if (ino == null) { 443 446 ino = new OutputTabInner(name); 447 } 448 else { 449 452 } 453 return ino; 454 } 455 } 456 457 458 public TopComponent getStdOutputTab() { 459 initialize(); 462 return standard; 463 } 464 465 } 466 467 472 473 static class Replace implements java.io.Serializable { 474 475 private static final long serialVersionUID =-3237844916624172415L; 476 477 public Replace () { 478 } 479 480 481 public Object readResolve() throws java.io.ObjectStreamException { 482 return OutputView.getDefault(); 483 } 484 } 485 486 492 500 501 public boolean isOpenedInOV (Component c) { 502 return openedComps.contains(c); 503 } 504 505 507 public boolean isClosedInOV (Component c) { 508 return closedComps.contains(c); 509 } 510 511 512 public void openInOV (final Component c) { 513 517 Mutex.EVENT.readAccess(new Runnable () { 519 public void run() { 520 524 if (!isOpened()) { 526 open(); 527 } 528 if (isOpenedInOV(c)) { 529 532 return; 533 } 534 538 if (openedComps.size() == 0) { 539 add(c); 541 revalidate(); 542 setActivatedNodes(((TopComponent) c).getActivatedNodes()); 543 setName(baseName + " - " + c.getName()); 544 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( 545 KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK), 546 "discard"); getActionMap().put("discard", new DiscardAction()); 548 } else if (openedComps.size() == 1) { 549 Component old = getComponents()[0]; 550 remove(old); 551 JTabbedPane tab = getTabbedPane(); 552 add(tab); 553 tab.addTab(old.getName(),old); 554 tab.addTab(c.getName(),c); 555 setActivatedNodes(((TopComponent) c).getActivatedNodes()); 556 setName(baseName); 557 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove( 558 KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK)); 559 getTabbedPane().addTab(c.getName(),c); 560 setActivatedNodes(((TopComponent) c).getActivatedNodes()); 561 } 562 if (closedComps.contains(c)) { 563 closedComps.remove(c); 564 } 565 openedComps.add(c); 566 if (openedComps.size() > 1) { 567 JTabbedPane tab = getTabbedPane(); 568 if (tab.getTabCount() != openedComps.size()) { 569 tab.add (c.getName(), c); 570 } 571 } 572 574 } 575 }); 576 579 } 580 581 583 protected JPopupMenu createPopupMenu () { 584 JPopupMenu popup = new JPopupMenu (); 585 JMenuItem menuItem = new JMenuItem 586 (NbBundle.getBundle(OutputView.class).getString("LBL_Discard")); 587 menuItem.setActionCommand("Discard"); 588 menuItem.addActionListener(this); 589 popup.add(menuItem); 590 591 menuItem = new JMenuItem 592 (NbBundle.getBundle(OutputView.class).getString("LBL_DiscardAll")); 593 menuItem.setActionCommand("DiscardAll"); 594 menuItem.addActionListener(this); 595 popup.add(menuItem); 596 597 return popup; 598 } 599 600 602 protected void showPopupMenu (JPopupMenu popup, Point p, Component comp) { 603 SwingUtilities.convertPointToScreen (p, comp); 604 Dimension popupSize = popup.getPreferredSize (); 605 Rectangle screenBounds = Utilities.getUsableScreenBounds(getGraphicsConfiguration()); 606 607 if (p.x + popupSize.width > screenBounds.x + screenBounds.width) { 608 p.x = screenBounds.x + screenBounds.width - popupSize.width; 609 } 610 if (p.y + popupSize.height > screenBounds.y + screenBounds.height) { 611 p.y = screenBounds.y + screenBounds.height - popupSize.height; 612 } 613 614 SwingUtilities.convertPointFromScreen (p, comp); 615 popup.show(comp, p.x, p.y); 616 } 617 618 622 static String getOutDisplayName() { 623 return NbBundle.getBundle(OutputView.class).getString("CTL_OutputWindow"); 624 } 625 626 630 632 public void open (Workspace workspace) { 633 if (!isShowing()) { 635 Workspace realWorkspace = (workspace == null) 636 ? WindowManager.getDefault().getCurrentWorkspace() 637 : workspace; 638 Mode mode = realWorkspace.findMode("output"); if (mode == null) { 641 mode = realWorkspace.createMode("output", getOutDisplayName(), OutputView.class.getResource(ICON_RESOURCE)); 643 } 644 Mode tcMode = realWorkspace.findMode(this); 645 if (tcMode == null) { 646 mode.dockInto(this); 647 } 648 super.open(workspace); 650 } else { 651 requestActive(); 652 } 653 } 654 655 659 public void propertyChange(PropertyChangeEvent evt) { 661 } 662 663 public void actionPerformed(ActionEvent e) { 664 if ("Discard".equals(e.getActionCommand())) { 665 discardTab(); 666 } else if ("DiscardAll".equals(e.getActionCommand())) { 667 discardAllTabs(); 668 } 669 } 670 671 672 void discardTab () { 673 Mutex.EVENT.readAccess(new Runnable () { 674 public void run() { 675 Component c = getSelectedComponent(); 676 if (c == null) { 677 return; 678 } 679 discardTab(c); 680 } 681 }); 682 } 683 684 686 void discardTab (Component c) { 687 if (openedComps.size() > 2) { 688 getTabbedPane().remove(c); 689 setActivatedNodes(((TopComponent) getSelectedComponent()).getActivatedNodes()); 690 } else if (openedComps.size() == 2) { 691 JTabbedPane tab = getTabbedPane(); 692 remove(tab); 693 tab.remove(c); 694 Component old = tab.getComponentAt(0); 695 tab.remove(old); 696 add(old); 697 setActivatedNodes(((TopComponent) old).getActivatedNodes()); 698 setName(baseName + " - " + old.getName()); 699 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( 700 KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK), 701 "discard"); getActionMap().put("discard", new DiscardAction()); 703 } else if (openedComps.size() == 1) { 704 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove( 705 KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_DOWN_MASK)); 706 remove(c); 707 setActivatedNodes(new Node[0]); 708 setName(baseName); 709 } 710 revalidate(); 711 repaint(); 712 openedComps.remove(c); 713 closedComps.add(c); 714 } 715 716 717 void discardAllTabs () { 718 Mutex.EVENT.readAccess(new Runnable () { 719 public void run() { 720 if (openedComps.size() > 1) { 721 JTabbedPane tab = getTabbedPane(); 722 tab.removeAll(); 723 remove(tab); 724 } else if (openedComps.size() == 1) { 725 remove(((Component []) openedComps.toArray(new Component[1]))[0]); 726 setName(baseName); 727 } 728 setActivatedNodes(new Node[0]); 729 revalidate(); 730 repaint(); 731 closedComps.addAll(openedComps); 732 openedComps.clear(); 733 } 734 }); 735 } 736 737 744 745 753 } 754 | Popular Tags |