1 22 23 package org.gjt.sp.jedit.gui; 24 25 import javax.swing.border.*; 27 import javax.swing.plaf.metal.*; 28 import javax.swing.*; 29 import java.awt.event.*; 30 import java.awt.font.*; 31 import java.awt.geom.AffineTransform ; 32 import java.awt.*; 33 import java.util.*; 34 import java.util.List ; 35 36 import org.gjt.sp.jedit.*; 37 import org.gjt.sp.util.StandardUtilities; 38 40 47 public class PanelWindowContainer implements DockableWindowContainer 48 { 49 public PanelWindowContainer(DockableWindowManager wm, String position, 51 int dimension) 52 { 53 this.wm = wm; 54 this.position = position; 55 56 buttonPanel = new JPanel(new ButtonLayout()); 58 buttonPanel.setBorder(new EmptyBorder(1,1,1,1)); 59 60 closeBox = new JButton(GUIUtilities.loadIcon("closebox.gif")); 61 closeBox.setRequestFocusEnabled(false); 62 closeBox.setToolTipText(jEdit.getProperty("view.docking.close-tooltip")); 63 if(OperatingSystem.isMacOSLF()) 64 closeBox.putClientProperty("JButton.buttonType","toolbar"); 65 66 closeBox.setMargin(new Insets(0,0,0,0)); 67 68 closeBox.addActionListener(new ActionHandler()); 69 70 menuBtn = new JButton(GUIUtilities.loadIcon("ToolbarMenu.gif")); 71 menuBtn.setRequestFocusEnabled(false); 72 menuBtn.setToolTipText(jEdit.getProperty("view.docking.menu-tooltip")); 73 if(OperatingSystem.isMacOSLF()) 74 menuBtn.putClientProperty("JButton.buttonType","toolbar"); 75 76 menuBtn.setMargin(new Insets(0,0,0,0)); 77 78 menuBtn.addMouseListener(new MenuMouseHandler()); 79 80 buttonGroup = new ButtonGroup(); 81 buttonGroup.add(nullButton = new JToggleButton()); 83 85 dockables = new ArrayList(); 86 buttons = new ArrayList(); 87 dockablePanel = new DockablePanel(this); 88 89 this.dimension = dimension; 90 } 92 96 public DockableWindowManager getDockableWindowManager() 97 { 98 return wm; 99 } 101 public void register(final DockableWindowManager.Entry entry) 103 { 104 dockables.add(entry); 105 106 int rotation; 108 if(position.equals(DockableWindowManager.TOP) 109 || position.equals(DockableWindowManager.BOTTOM)) 110 rotation = RotatedTextIcon.NONE; 111 else if(position.equals(DockableWindowManager.LEFT)) 112 rotation = RotatedTextIcon.CCW; 113 else if(position.equals(DockableWindowManager.RIGHT)) 114 rotation = RotatedTextIcon.CW; 115 else 116 throw new InternalError ("Invalid position: " + position); 117 118 JToggleButton button = new JToggleButton(); 119 button.setMargin(new Insets(1,1,1,1)); 120 button.setRequestFocusEnabled(false); 121 button.setIcon(new RotatedTextIcon(rotation,button.getFont(), 122 entry.shortTitle())); 123 button.setActionCommand(entry.factory.name); 124 button.addActionListener(new ActionHandler()); 125 button.addMouseListener(new MenuMouseHandler()); 126 if(OperatingSystem.isMacOSLF()) 127 button.putClientProperty("JButton.buttonType","toolbar"); 128 130 buttonGroup.add(button); 131 buttons.add(button); 132 entry.btn = button; 133 134 wm.revalidate(); 135 } 137 public void unregister(DockableWindowManager.Entry entry) 139 { 140 if(entry.factory.name.equals(mostRecent)) 141 mostRecent = null; 142 143 if(entry.btn != null) 144 { 145 buttonPanel.remove(entry.btn); 146 buttons.remove(entry.btn); 147 entry.btn = null; 148 } 149 150 dockables.remove(entry); 151 if(entry.win != null) 152 dockablePanel.remove(entry.win); 153 154 if(current == entry) 155 { 156 current = null; 157 show(null); 158 } 159 else 160 { 161 wm.revalidate(); 162 dockablePanel.repaint(); 163 buttonPanel.repaint(); 164 } 165 } 167 public void remove(final DockableWindowManager.Entry entry) 169 { 170 if(entry.factory.name.equals(mostRecent)) 171 mostRecent = null; 172 173 if(entry.win != null) 174 { 175 dockablePanel.remove(entry.win); 176 entry.win = null; 177 } 178 179 if(current == entry) 180 { 181 current = null; 182 show(null); 183 } 184 else 185 { 186 wm.revalidate(); 187 dockablePanel.repaint(); 188 } 189 } 191 public void showMostRecent() 193 { 194 if(dockables.isEmpty()) 195 { 196 Toolkit.getDefaultToolkit().beep(); 197 return; 198 } 199 200 if(mostRecent == null) 201 { 202 mostRecent = ((DockableWindowManager.Entry) 203 dockables.get(0)).factory.name; 204 } 205 206 wm.showDockableWindow(mostRecent); 207 } 209 public void show(final DockableWindowManager.Entry entry) 211 { 212 if(current == entry) 213 { 214 if(entry != null) 215 { 216 if(entry.win instanceof DefaultFocusComponent) 217 { 218 ((DefaultFocusComponent)entry.win) 219 .focusOnDefaultComponent(); 220 } 221 else 222 { 223 entry.win.requestDefaultFocus(); 224 } 225 } 226 return; 227 } 228 229 if(entry != null) 230 { 231 if(current == null) 232 { 233 dockablePanel.setBorder(new DockBorder(position)); 236 } 237 238 mostRecent = entry.factory.name; 239 this.current = entry; 240 241 if(entry.win.getParent() != dockablePanel) 242 dockablePanel.add(entry.factory.name,entry.win); 243 244 dockablePanel.showDockable(entry.factory.name); 245 246 entry.btn.setSelected(true); 247 248 if(entry.win instanceof DefaultFocusComponent) 249 { 250 ((DefaultFocusComponent)entry.win) 251 .focusOnDefaultComponent(); 252 } 253 else 254 { 255 entry.win.requestDefaultFocus(); 256 } 257 } 258 else 259 { 260 current = null; 261 nullButton.setSelected(true); 262 dockablePanel.setBorder(null); 264 265 wm.getView().getTextArea().requestFocus(); 266 } 267 268 wm.revalidate(); 269 dockablePanel.repaint(); 270 } 272 public boolean isVisible(DockableWindowManager.Entry entry) 274 { 275 return current == entry; 276 } 278 283 public String getCurrent() 284 { 285 if(current == null) 286 return null; 287 else 288 return current.factory.name; 289 } 291 297 public int getDimension() 298 { 299 return dimension; 300 } 302 306 public String getPosition() 307 { 308 return position; 309 } 311 public String [] getDockables() 313 { 314 String [] retVal = new String [dockables.size()]; 315 for(int i = 0; i < dockables.size(); i++) 316 { 317 DockableWindowManager.Entry entry = 318 (DockableWindowManager.Entry) dockables.get(i); 319 retVal[i] = entry.factory.name; 320 } 321 return retVal; 322 } 324 static final int SPLITTER_WIDTH = 10; 326 DockablePanel dockablePanel; 327 JPanel buttonPanel; 328 329 void save() 331 { 332 jEdit.setIntegerProperty("view.dock." + position + ".dimension", 333 dimension); 334 if(current == null) 335 jEdit.unsetProperty("view.dock." + position + ".last"); 336 else 337 { 338 jEdit.setProperty("view.dock." + position + ".last", 339 current.factory.name); 340 } 341 } 343 void setDimension(int dimension) 345 { 346 if(dimension > SPLITTER_WIDTH) 347 this.dimension = dimension - SPLITTER_WIDTH; 348 } 350 void sortDockables() 352 { 353 buttonPanel.removeAll(); 354 buttonPanel.add(closeBox); 355 buttonPanel.add(menuBtn); 356 Collections.sort(buttons,new DockableWindowCompare()); 357 for(int i = 0; i < buttons.size(); i++) 358 { 359 buttonPanel.add((AbstractButton)buttons.get(i)); 360 } 361 } 363 367 int getWrappedDimension(int dimension) 368 { 369 return ((ButtonLayout)buttonPanel.getLayout()) 370 .getWrappedDimension(buttonPanel,dimension); 371 } 373 375 private DockableWindowManager wm; 377 private String position; 378 private JButton closeBox; 379 private JButton menuBtn; 380 private ButtonGroup buttonGroup; 381 private JToggleButton nullButton; 382 private int dimension; 383 private List dockables; 384 private List buttons; 385 private DockableWindowManager.Entry current; 386 private JPopupMenu popup; 387 388 private String mostRecent; 390 392 394 static class DockableWindowCompare implements Comparator 396 { 397 public int compare(Object o1, Object o2) 398 { 399 String name1 = ((AbstractButton)o1).getActionCommand(); 400 String name2 = ((AbstractButton)o2).getActionCommand(); 401 return StandardUtilities.compareStrings( 402 jEdit.getProperty(name1 + ".title",""), 403 jEdit.getProperty(name2 + ".title",""), 404 true); 405 } 406 } 408 class ActionHandler implements ActionListener 410 { 411 public void actionPerformed(ActionEvent evt) 412 { 413 if(popup != null && popup.isVisible()) 414 popup.setVisible(false); 415 416 if(evt.getSource() == closeBox) 417 show(null); 418 else 419 { 420 if(wm.isDockableWindowVisible(evt.getActionCommand())) 421 show(null); 422 else 423 wm.showDockableWindow(evt.getActionCommand()); 424 } 425 } 426 } 428 class MenuMouseHandler extends MouseAdapter 430 { 431 public void mousePressed(MouseEvent evt) 432 { 433 if(popup != null && popup.isVisible()) 434 { 435 popup.setVisible(false); 436 return; 437 } 438 439 Component comp = (Component)evt.getSource(); 440 String dockable; 441 if(comp instanceof JToggleButton) 442 dockable = ((JToggleButton)comp).getActionCommand(); 443 else 444 dockable = getCurrent(); 445 446 if(comp == menuBtn || GUIUtilities.isPopupTrigger(evt)) 447 { 448 if(dockable == null) 449 { 450 popup = wm.createPopupMenu(PanelWindowContainer.this,null,false); 451 } 452 else 453 { 454 popup = wm.createPopupMenu(PanelWindowContainer.this,dockable,false); 455 } 456 457 int x, y; 458 boolean point; 459 if(comp == menuBtn) 460 { 461 x = 0; 462 y = menuBtn.getHeight(); 463 point = false; 464 } 465 else 466 { 467 x = evt.getX(); 468 y = evt.getY(); 469 point = true; 470 } 471 GUIUtilities.showPopupMenu(popup, 472 comp,x,y,point); 473 } 474 } 475 } 477 static class DockBorder implements Border 479 { 480 String position; 481 Insets insets; 482 Color color1; 483 Color color2; 484 Color color3; 485 486 DockBorder(String position) 488 { 489 this.position = position; 490 insets = new Insets( 491 position.equals(DockableWindowManager.BOTTOM) 492 ? SPLITTER_WIDTH : 0, 493 position.equals(DockableWindowManager.RIGHT) 494 ? SPLITTER_WIDTH : 0, 495 position.equals(DockableWindowManager.TOP) 496 ? SPLITTER_WIDTH : 0, 497 position.equals(DockableWindowManager.LEFT) 498 ? SPLITTER_WIDTH : 0); 499 } 501 public void paintBorder(Component c, Graphics g, 503 int x, int y, int width, int height) 504 { 505 updateColors(); 506 507 if(color1 == null || color2 == null || color3 == null) 508 return; 509 510 if(position.equals(DockableWindowManager.BOTTOM)) 511 paintHorizBorder(g,x,y,width); 512 else if(position.equals(DockableWindowManager.RIGHT)) 513 paintVertBorder(g,x,y,height); 514 else if(position.equals(DockableWindowManager.TOP)) 515 { 516 paintHorizBorder(g,x,y + height 517 - SPLITTER_WIDTH,width); 518 } 519 else if(position.equals(DockableWindowManager.LEFT)) 520 { 521 paintVertBorder(g,x + width 522 - SPLITTER_WIDTH,y,height); 523 } 524 } 526 public Insets getBorderInsets(Component c) 528 { 529 return insets; 530 } 532 public boolean isBorderOpaque() 534 { 535 return false; 536 } 538 private void paintHorizBorder(Graphics g, int x, int y, int width) 540 { 541 g.setColor(color3); 542 g.fillRect(x,y,width,SPLITTER_WIDTH); 543 544 for(int i = 0; i < width / 4 - 1; i++) 545 { 546 g.setColor(color1); 547 g.drawLine(x + i * 4 + 2,y + 3, 548 x + i * 4 + 2,y + 3); 549 g.setColor(color2); 550 g.drawLine(x + i * 4 + 3,y + 4, 551 x + i * 4 + 3,y + 4); 552 g.setColor(color1); 553 g.drawLine(x + i * 4 + 4,y + 5, 554 x + i * 4 + 4,y + 5); 555 g.setColor(color2); 556 g.drawLine(x + i * 4 + 5,y + 6, 557 x + i * 4 + 5,y + 6); 558 } 559 } 561 private void paintVertBorder(Graphics g, int x, int y, int height) 563 { 564 g.setColor(color3); 565 g.fillRect(x,y,SPLITTER_WIDTH,height); 566 567 for(int i = 0; i < height / 4 - 1; i++) 568 { 569 g.setColor(color1); 570 g.drawLine(x + 3,y + i * 4 + 2, 571 x + 3,y + i * 4 + 2); 572 g.setColor(color2); 573 g.drawLine(x + 4,y + i * 4 + 3, 574 x + 4,y + i * 4 + 3); 575 g.setColor(color1); 576 g.drawLine(x + 5,y + i * 4 + 4, 577 x + 5,y + i * 4 + 4); 578 g.setColor(color2); 579 g.drawLine(x + 6,y + i * 4 + 5, 580 x + 6,y + i * 4 + 5); 581 } 582 } 584 private void updateColors() 586 { 587 if(UIManager.getLookAndFeel() instanceof MetalLookAndFeel) 588 { 589 color1 = MetalLookAndFeel.getControlHighlight(); 590 color2 = MetalLookAndFeel.getControlDarkShadow(); 591 color3 = MetalLookAndFeel.getControl(); 592 } 593 else 594 { 595 color1 = color2 = color3 = null; 596 } 597 } } 600 public static class RotatedTextIcon implements Icon 602 { 603 public static final int NONE = 0; 604 public static final int CW = 1; 605 public static final int CCW = 2; 606 607 public RotatedTextIcon(int rotate, Font font, String text) 609 { 610 this.rotate = rotate; 611 this.font = font; 612 613 FontRenderContext fontRenderContext 614 = new FontRenderContext(null,true,true); 615 this.text = text; 616 glyphs = font.createGlyphVector(fontRenderContext,text); 617 width = (int)glyphs.getLogicalBounds().getWidth() + 4; 618 620 LineMetrics lineMetrics = font.getLineMetrics(text,fontRenderContext); 621 ascent = lineMetrics.getAscent(); 622 height = (int)lineMetrics.getHeight(); 623 624 renderHints = new RenderingHints( 625 RenderingHints.KEY_ANTIALIASING, 626 RenderingHints.VALUE_ANTIALIAS_ON); 627 renderHints.put(RenderingHints.KEY_FRACTIONALMETRICS, 628 RenderingHints.VALUE_FRACTIONALMETRICS_ON); 629 renderHints.put(RenderingHints.KEY_RENDERING, 630 RenderingHints.VALUE_RENDER_QUALITY); 631 } 633 public int getIconWidth() 635 { 636 return (int)(rotate == RotatedTextIcon.CW 637 || rotate == RotatedTextIcon.CCW 638 ? height : width); 639 } 641 public int getIconHeight() 643 { 644 return (int)(rotate == RotatedTextIcon.CW 645 || rotate == RotatedTextIcon.CCW 646 ? width : height); 647 } 649 public void paintIcon(Component c, Graphics g, int x, int y) 651 { 652 Graphics2D g2d = (Graphics2D)g; 653 g2d.setFont(font); 654 AffineTransform oldTransform = g2d.getTransform(); 655 RenderingHints oldHints = g2d.getRenderingHints(); 656 657 g2d.setRenderingHints(renderHints); 658 g2d.setColor(c.getForeground()); 659 660 if(rotate == RotatedTextIcon.NONE) 662 { 663 g2d.drawGlyphVector(glyphs,x + 2,y + ascent); 664 } else if(rotate == RotatedTextIcon.CW) 667 { 668 AffineTransform trans = new AffineTransform (); 669 trans.concatenate(oldTransform); 670 trans.translate(x,y + 2); 671 trans.rotate(Math.PI / 2, 672 height / 2, width / 2); 673 g2d.setTransform(trans); 674 g2d.drawGlyphVector(glyphs,(height - width) / 2, 675 (width - height) / 2 676 + ascent); 677 } else if(rotate == RotatedTextIcon.CCW) 680 { 681 AffineTransform trans = new AffineTransform (); 682 trans.concatenate(oldTransform); 683 trans.translate(x,y - 2); 684 trans.rotate(Math.PI * 3 / 2, 685 height / 2, width / 2); 686 g2d.setTransform(trans); 687 g2d.drawGlyphVector(glyphs,(height - width) / 2, 688 (width - height) / 2 689 + ascent); 690 } 692 g2d.setTransform(oldTransform); 693 g2d.setRenderingHints(oldHints); 694 } 696 private int rotate; 698 private Font font; 699 private String text; 700 private GlyphVector glyphs; 701 private float width; 702 private float height; 703 private float ascent; 704 private RenderingHints renderHints; 705 } 708 class ButtonLayout implements LayoutManager 710 { 711 public void addLayoutComponent(String name, Component comp) {} 714 public void removeLayoutComponent(Component comp) {} 717 721 int getWrappedDimension(JComponent parent, int dimension) 722 { 723 Insets insets = parent.getBorder() 724 .getBorderInsets(parent); 725 726 Component[] comp = parent.getComponents(); 727 if(comp.length <= 2) 728 return 0; 729 730 Dimension dim = comp[2].getPreferredSize(); 731 732 if(position.equals(DockableWindowManager.TOP) 733 || position.equals(DockableWindowManager.BOTTOM)) 734 { 735 int width = dimension - insets.right; 736 int rowHeight = Math.max(dim.height,closeBox.getPreferredSize().width); 737 int x = rowHeight * 2 + insets.left; 738 Dimension returnValue = new Dimension(0,rowHeight 739 + insets.top + insets.bottom); 740 741 for(int i = 2; i < comp.length; i++) 742 { 743 int btnWidth = comp[i].getPreferredSize().width; 744 if(btnWidth + x > width) 745 { 746 returnValue.height += rowHeight; 747 x = insets.left; 748 } 749 750 x += btnWidth; 751 } 752 return returnValue.height; 753 } 754 else 755 { 756 int height = dimension - insets.bottom; 757 int colWidth = Math.max(dim.width,closeBox.getPreferredSize().height); 758 int y = colWidth * 2 + insets.top; 759 Dimension returnValue = new Dimension(colWidth 760 + insets.left + insets.right,0); 761 762 for(int i = 2; i < comp.length; i++) 763 { 764 int btnHeight = comp[i].getPreferredSize().height; 765 if(btnHeight + y > height) 766 { 767 returnValue.width += colWidth; 768 y = insets.top; 769 } 770 771 y += btnHeight; 772 } 773 return returnValue.width; 774 } 775 } 777 public Dimension preferredLayoutSize(Container parent) 779 { 780 Insets insets = ((JComponent)parent).getBorder() 781 .getBorderInsets(parent); 782 783 Component[] comp = parent.getComponents(); 784 if(comp.length <= 2) 785 { 786 return new Dimension(0,0); 788 } 789 790 Dimension dim = comp[2].getPreferredSize(); 791 792 if(position.equals(DockableWindowManager.TOP) 793 || position.equals(DockableWindowManager.BOTTOM)) 794 { 795 int width = parent.getWidth() - insets.right; 796 int rowHeight = Math.max(dim.height,closeBox.getPreferredSize().width); 797 int x = rowHeight * 2 + insets.left; 798 Dimension returnValue = new Dimension(0,rowHeight 799 + insets.top + insets.bottom); 800 801 for(int i = 2; i < comp.length; i++) 802 { 803 int btnWidth = comp[i].getPreferredSize().width; 804 if(btnWidth + x > width) 805 { 806 returnValue.height += rowHeight; 807 x = insets.left; 808 } 809 810 x += btnWidth; 811 } 812 return returnValue; 813 } 814 else 815 { 816 int height = parent.getHeight() - insets.bottom; 817 int colWidth = Math.max(dim.width,closeBox.getPreferredSize().height); 818 int y = colWidth * 2 + insets.top; 819 Dimension returnValue = new Dimension(colWidth 820 + insets.left + insets.right,0); 821 822 for(int i = 2; i < comp.length; i++) 823 { 824 int btnHeight = comp[i].getPreferredSize().height; 825 if(btnHeight + y > height) 826 { 827 returnValue.width += colWidth; 828 y = insets.top; 829 } 830 831 y += btnHeight; 832 } 833 return returnValue; 834 } 835 } 837 public Dimension minimumLayoutSize(Container parent) 839 { 840 return preferredLayoutSize(parent); 841 } 843 public void layoutContainer(Container parent) 845 { 846 Insets insets = ((JComponent)parent).getBorder() 847 .getBorderInsets(parent); 848 849 Component[] comp = parent.getComponents(); 850 if(comp.length <= 2) 851 { 852 for(int i = 0; i < comp.length; i++) 853 { 854 comp[i].setVisible(false); 855 } 856 return; 857 } 858 859 comp[0].setVisible(true); 860 comp[1].setVisible(true); 861 862 Dimension dim = comp[2].getPreferredSize(); 863 864 if(position.equals(DockableWindowManager.TOP) 865 || position.equals(DockableWindowManager.BOTTOM)) 866 { 867 int width = parent.getWidth() - insets.right; 868 int rowHeight = Math.max(dim.height,closeBox.getPreferredSize().width); 869 int x = rowHeight * 2 + insets.left; 870 int y = insets.top; 871 closeBox.setBounds(insets.left,insets.top,rowHeight,rowHeight); 872 menuBtn.setBounds(insets.left + rowHeight,insets.top,rowHeight,rowHeight); 873 874 for(int i = 2; i < comp.length; i++) 875 { 876 int btnWidth = comp[i].getPreferredSize().width; 877 if(btnWidth + x > width) 878 { 879 x = insets.left; 880 y += rowHeight; 881 } 882 comp[i].setBounds(x,y,btnWidth,rowHeight); 883 x += btnWidth; 884 } 885 886 893 } 894 else 895 { 896 int height = parent.getHeight() - insets.bottom; 897 int colWidth = Math.max(dim.width,closeBox.getPreferredSize().height); 898 int x = insets.left; 899 int y = colWidth * 2 + insets.top; 900 closeBox.setBounds(insets.left,insets.top,colWidth,colWidth); 901 menuBtn.setBounds(insets.left,insets.top + colWidth,colWidth,colWidth); 902 903 for(int i = 2; i < comp.length; i++) 904 { 905 int btnHeight = comp[i].getPreferredSize().height; 906 if(btnHeight + y > height) 907 { 908 x += colWidth; 909 y = insets.top; 910 } 911 comp[i].setBounds(x,y,colWidth,btnHeight); 912 y += btnHeight; 913 } 914 915 921 } 922 } } 925 } 927 | Popular Tags |