1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76:
77:
85: public class MetalRootPaneUI
86: extends BasicRootPaneUI
87: {
88:
89:
95: private static class MetalFrameBorder
96: extends AbstractBorder
97: {
98:
107: public Insets getBorderInsets(Component c, Insets newInsets)
108: {
109: if (newInsets == null)
110: newInsets = new Insets(5, 5, 5, 5);
111: else
112: {
113: newInsets.top = 5;
114: newInsets.left = 5;
115: newInsets.bottom = 5;
116: newInsets.right = 5;
117: }
118: return newInsets;
119: }
120:
121:
128: public Insets getBorderInsets(Component c)
129: {
130: return getBorderInsets(c, null);
131: }
132:
133:
143: public void paintBorder(Component c, Graphics g, int x, int y, int w,
144: int h)
145: {
146: JRootPane f = (JRootPane) c;
147: Window frame = SwingUtilities.getWindowAncestor(f);
148: if (frame.isActive())
149: g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
150: else
151: g.setColor(MetalLookAndFeel.getControlDarkShadow());
152:
153:
154: g.fillRect(x, y, w, 5);
155: g.fillRect(x, y, 5, h);
156: g.fillRect(x + w - 5, y, 5, h);
157: g.fillRect(x, y + h - 5, w, 5);
158:
159:
160: g.setColor(MetalLookAndFeel.getControl());
161: g.fillRect(x, y, 1, 1);
162: g.fillRect(x + w - 1, y, 1, 1);
163: g.fillRect(x + w - 1, y + h - 1, 1, 1);
164: g.fillRect(x, y + h - 1, 1, 1);
165:
166:
167: g.setColor(MetalLookAndFeel.getBlack());
168: g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
169: g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
170: g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
171: g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
172:
173:
174: if (frame.isActive())
175: g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
176: else
177: g.setColor(MetalLookAndFeel.getControlShadow());
178: g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
179: g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
180: g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
181: g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
182: }
183: }
184:
185:
193: private static class MetalTitlePane extends JComponent
194: {
195:
196:
199: private class MouseHandler
200: extends MouseInputAdapter
201: {
202:
205: Point lastDragLocation;
206:
207:
213: public void mousePressed(MouseEvent ev)
214: {
215: lastDragLocation = ev.getPoint();
216: }
217:
218:
224: public void mouseDragged(MouseEvent ev)
225: {
226: Point dragLocation = ev.getPoint();
227: int deltaX = dragLocation.x - lastDragLocation.x;
228: int deltaY = dragLocation.y - lastDragLocation.y;
229: Window window = SwingUtilities.getWindowAncestor(rootPane);
230: Point loc = window.getLocation();
231: window.setLocation(loc.x + deltaX, loc.y + deltaY);
232:
233:
234:
235:
236: }
237: }
238:
239:
242: private class CloseAction extends AbstractAction
243: {
244:
247: public CloseAction()
248: {
249: super("Close");
250: }
251:
252:
257: public void actionPerformed(ActionEvent e)
258: {
259: Window frame = SwingUtilities.getWindowAncestor(rootPane);
260: if (frame instanceof JFrame)
261: {
262: JFrame jframe = (JFrame) frame;
263: switch (jframe.getDefaultCloseOperation())
264: {
265: case JFrame.EXIT_ON_CLOSE:
266: jframe.setVisible(false);
267: jframe.dispose();
268: System.exit(0);
269: break;
270: case JFrame.DISPOSE_ON_CLOSE:
271: jframe.setVisible(false);
272: jframe.dispose();
273: break;
274: case JFrame.HIDE_ON_CLOSE:
275: jframe.setVisible(false);
276: break;
277: case JFrame.DO_NOTHING_ON_CLOSE:
278: default:
279: break;
280: }
281: }
282: else if (frame instanceof JDialog)
283: {
284: JDialog jdialog = (JDialog) frame;
285: switch (jdialog.getDefaultCloseOperation())
286: {
287: case JFrame.DISPOSE_ON_CLOSE:
288: jdialog.setVisible(false);
289: jdialog.dispose();
290: break;
291: case JFrame.HIDE_ON_CLOSE:
292: jdialog.setVisible(false);
293: break;
294: case JFrame.DO_NOTHING_ON_CLOSE:
295: default:
296: break;
297: }
298: }
299: }
300: }
301:
302:
305: private class IconifyAction
306: extends AbstractAction
307: {
308:
309: public void actionPerformed(ActionEvent event)
310: {
311: Window w = SwingUtilities.getWindowAncestor(rootPane);
312: if (w instanceof Frame)
313: {
314: Frame f = (Frame) w;
315: int state = f.getExtendedState();
316: f.setExtendedState(Frame.ICONIFIED);
317: }
318: }
319:
320: }
321:
322:
325: private class MaximizeAction
326: extends AbstractAction
327: {
328:
329: public void actionPerformed(ActionEvent event)
330: {
331: Window w = SwingUtilities.getWindowAncestor(rootPane);
332: if (w instanceof Frame)
333: {
334: Frame f = (Frame) w;
335: int state = f.getExtendedState();
336: f.setExtendedState(Frame.MAXIMIZED_BOTH);
337: }
338: }
339: }
340:
341:
346: private class PaneButton extends JButton
347: {
348:
353: public PaneButton(Action a)
354: {
355: super(a);
356: setMargin(new Insets(0, 0, 0, 0));
357: }
358:
359:
364: public boolean isFocusable()
365: {
366:
367: return false;
368: }
369:
370: }
371:
372:
379: private class MetalTitlePaneLayout implements LayoutManager
380: {
381:
384: public MetalTitlePaneLayout()
385: {
386:
387: }
388:
389:
395: public void addLayoutComponent(String name, Component c)
396: {
397:
398: }
399:
400:
405: public void layoutContainer(Container c)
406: {
407:
408: Dimension size = c.getSize();
409: Insets insets = c.getInsets();
410: int width = size.width - insets.left - insets.right;
411: int height = size.height - insets.top - insets.bottom;
412:
413: int loc = width - insets.right - 1;
414: int top = insets.top + 2;
415: int buttonHeight = height - 4;
416: if (closeButton.isVisible())
417: {
418: int buttonWidth = closeIcon.getIconWidth();
419: loc -= buttonWidth + 2;
420: closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
421: loc -= 6;
422: }
423:
424: if (maxButton.isVisible())
425: {
426: int buttonWidth = maxIcon.getIconWidth();
427: loc -= buttonWidth + 4;
428: maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
429: }
430:
431: if (iconButton.isVisible())
432: {
433: int buttonWidth = minIcon.getIconWidth();
434: loc -= buttonWidth + 4;
435: iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
436: loc -= 2;
437: }
438:
439: Dimension titlePreferredSize = title.getPreferredSize();
440: title.setBounds(insets.left + 5, insets.top,
441: Math.min(titlePreferredSize.width, loc - insets.left - 10),
442: height);
443:
444: }
445:
446:
454: public Dimension minimumLayoutSize(Container c)
455: {
456: return preferredLayoutSize(c);
457: }
458:
459:
467: public Dimension preferredLayoutSize(Container c)
468: {
469: return new Dimension(22, 22);
470: }
471:
472:
477: public void removeLayoutComponent(Component c)
478: {
479:
480: }
481: }
482:
483: JRootPane rootPane;
484:
485:
486: JButton closeButton;
487:
488:
489: JButton iconButton;
490:
491:
492: JButton maxButton;
493:
494: Icon minIcon;
495:
496:
497: Icon maxIcon;
498:
499:
500: private Icon iconIcon;
501:
502:
503: Icon closeIcon;
504:
505:
509: private Color notSelectedTitleColor;
510:
511:
515: private Color selectedTitleColor;
516:
517:
521: JLabel title;
522:
523:
524: private Action closeAction;
525:
526:
527: private Action iconifyAction;
528:
529:
530: private Action maximizeAction;
531:
532:
533: private JMenuBar menuBar;
534:
535:
536: protected JMenu windowMenu;
537:
538: MetalTitlePane(JRootPane rp)
539: {
540: rootPane = rp;
541: setLayout(createLayout());
542: title = new JLabel();
543: title.setHorizontalAlignment(SwingConstants.LEFT);
544: title.setHorizontalTextPosition(SwingConstants.LEFT);
545: title.setOpaque(false);
546: installTitlePane();
547: }
548:
549: protected LayoutManager createLayout()
550: {
551: return new MetalTitlePaneLayout();
552: }
553:
554:
559: protected void installTitlePane()
560: {
561: installDefaults();
562: installListeners();
563: createActions();
564: assembleSystemMenu();
565: createButtons();
566: setButtonIcons();
567: addSubComponents();
568: enableActions();
569: }
570:
571: private void enableActions()
572: {
573:
574: }
575:
576: private void addSubComponents()
577: {
578: add(menuBar);
579: add(closeButton);
580: add(iconButton);
581: add(maxButton);
582: }
583:
584: private void installListeners()
585: {
586: MouseInputAdapter mouseHandler = new MouseHandler();
587: addMouseListener(mouseHandler);
588: addMouseMotionListener(mouseHandler);
589: }
590:
591: private void createActions()
592: {
593: closeAction = new CloseAction();
594: iconifyAction = new IconifyAction();
595: maximizeAction = new MaximizeAction();
596: }
597:
598: private void assembleSystemMenu()
599: {
600: menuBar = createSystemMenuBar();
601: windowMenu = createSystemMenu();
602: menuBar.add(windowMenu);
603: addSystemMenuItems(windowMenu);
604: enableActions();
605: }
606:
607: protected JMenuBar createSystemMenuBar()
608: {
609: if (menuBar == null)
610: menuBar = new JMenuBar();
611: menuBar.removeAll();
612: return menuBar;
613: }
614:
615: protected JMenu createSystemMenu()
616: {
617: if (windowMenu == null)
618: windowMenu = new JMenu();
619: windowMenu.removeAll();
620: return windowMenu;
621: }
622:
623: private void addSystemMenuItems(JMenu menu)
624: {
625:
626: }
627:
628: protected void createButtons()
629: {
630: closeButton = new PaneButton(closeAction);
631: closeButton.setText(null);
632: iconButton = new PaneButton(iconifyAction);
633: iconButton.setText(null);
634: maxButton = new PaneButton(maximizeAction);
635: maxButton.setText(null);
636: closeButton.setBorderPainted(false);
637: closeButton.setContentAreaFilled(false);
638: iconButton.setBorderPainted(false);
639: iconButton.setContentAreaFilled(false);
640: maxButton.setBorderPainted(false);
641: maxButton.setContentAreaFilled(false);
642: }
643:
644: protected void setButtonIcons()
645: {
646: if (closeIcon != null && closeButton != null)
647: closeButton.setIcon(closeIcon);
648: if (iconIcon != null && iconButton != null)
649: iconButton.setIcon(iconIcon);
650: if (maxIcon != null && maxButton != null)
651: maxButton.setIcon(maxIcon);
652: }
653:
654:
659: public void paintComponent(Graphics g)
660: {
661: Window frame = SwingUtilities.getWindowAncestor(rootPane);
662: Color savedColor = g.getColor();
663: paintTitleBackground(g);
664: paintChildren(g);
665: Dimension d = getSize();
666: if (frame.isActive())
667: g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
668: else
669: g.setColor(MetalLookAndFeel.getControlDarkShadow());
670:
671:
672: g.drawLine(0, 0, 0, 0);
673: g.drawLine(d.width - 1, 0, d.width - 1, 0);
674:
675: g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
676:
677:
678: if (UIManager.get("InternalFrame.activeTitleGradient") != null
679: && frame.isActive())
680: {
681: MetalUtils.paintGradient(g, 0, 0, getWidth(), getHeight(),
682: SwingConstants.VERTICAL,
683: "InternalFrame.activeTitleGradient");
684: }
685:
686: Rectangle b = title.getBounds();
687: int startX = b.x + b.width + 5;
688: int endX = startX;
689: if (iconButton.isVisible())
690: endX = Math.max(iconButton.getX(), endX);
691: else if (maxButton.isVisible())
692: endX = Math.max(maxButton.getX(), endX);
693: else if (closeButton.isVisible())
694: endX = Math.max(closeButton.getX(), endX);
695: endX -= 7;
696: if (endX > startX)
697: MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray);
698: g.setColor(savedColor);
699: }
700:
701:
706: protected void paintTitleBackground(Graphics g)
707: {
708: Window frame = SwingUtilities.getWindowAncestor(rootPane);
709:
710: if (!isOpaque())
711: return;
712:
713: Color saved = g.getColor();
714: Dimension dims = getSize();
715:
716: Color bg = getBackground();
717: if (frame.isActive())
718: bg = selectedTitleColor;
719: else
720: bg = notSelectedTitleColor;
721: g.setColor(bg);
722: g.fillRect(0, 0, dims.width, dims.height);
723: g.setColor(saved);
724: }
725:
726:
729: private void installDefaults()
730: {
731: title.setFont(UIManager.getFont("InternalFrame.titleFont"));
732: selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground");
733: notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground");
734: closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
735: iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
736: maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
737: minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16);
738: Frame frame = (Frame) SwingUtilities.getWindowAncestor(rootPane);
739: title = new JLabel(frame.getTitle(),
740: MetalIconFactory.getInternalFrameDefaultMenuIcon(),
741: SwingConstants.LEFT);
742: }
743: }
744:
745: private static class MetalRootLayout
746: implements LayoutManager2
747: {
748:
749:
752: private Rectangle glassPaneBounds;
753:
754:
757: private Rectangle layeredPaneBounds;
758:
759:
762: private Rectangle contentPaneBounds;
763:
764:
767: private Rectangle menuBarBounds;
768:
769:
772: private Rectangle titlePaneBounds;
773:
774:
777: private Dimension prefSize;
778:
779:
782: private MetalTitlePane titlePane;
783:
784:
789: MetalRootLayout(MetalTitlePane tp)
790: {
791: titlePane = tp;
792: }
793:
794: public void addLayoutComponent(Component component, Object constraints)
795: {
796:
797: }
798:
799: public Dimension maximumLayoutSize(Container target)
800: {
801: return preferredLayoutSize(target);
802: }
803:
804: public float getLayoutAlignmentX(Container target)
805: {
806: return 0.0F;
807: }
808:
809: public float getLayoutAlignmentY(Container target)
810: {
811: return 0.0F;
812: }
813:
814: public void invalidateLayout(Container target)
815: {
816: synchronized (this)
817: {
818: glassPaneBounds = null;
819: layeredPaneBounds = null;
820: contentPaneBounds = null;
821: menuBarBounds = null;
822: titlePaneBounds = null;
823: prefSize = null;
824: }
825: }
826:
827: public void addLayoutComponent(String name, Component component)
828: {
829:
830: }
831:
832: public void removeLayoutComponent(Component component)
833: {
834:
835:
836: }
837:
838: public Dimension preferredLayoutSize(Container parent)
839: {
840: JRootPane rp = (JRootPane) parent;
841: JLayeredPane layeredPane = rp.getLayeredPane();
842: Component contentPane = rp.getContentPane();
843: Component menuBar = rp.getJMenuBar();
844:
845:
846:
847: synchronized (this)
848: {
849: if (prefSize == null)
850: {
851: Insets i = parent.getInsets();
852: prefSize = new Dimension(i.left + i.right, i.top + i.bottom);
853: Dimension contentPrefSize = contentPane.getPreferredSize();
854: prefSize.width += contentPrefSize.width;
855: prefSize.height += contentPrefSize.height
856: + titlePane.getPreferredSize().height;
857: if (menuBar != null)
858: {
859: Dimension menuBarSize = menuBar.getPreferredSize();
860: if (menuBarSize.width > contentPrefSize.width)
861: prefSize.width += menuBarSize.width - contentPrefSize.width;
862: prefSize.height += menuBarSize.height;
863: }
864: }
865:
866:
867: return new Dimension(prefSize);
868: }
869: }
870:
871: public Dimension minimumLayoutSize(Container parent)
872: {
873: return preferredLayoutSize(parent);
874: }
875:
876: public void layoutContainer(Container parent)
877: {
878: JRootPane rp = (JRootPane) parent;
879: JLayeredPane layeredPane = rp.getLayeredPane();
880: Component contentPane = rp.getContentPane();
881: Component menuBar = rp.getJMenuBar();
882: Component glassPane = rp.getGlassPane();
883:
884: if (glassPaneBounds == null || layeredPaneBounds == null
885: || contentPaneBounds == null || menuBarBounds == null)
886: {
887: Insets i = rp.getInsets();
888: int containerWidth = parent.getBounds().width - i.left - i.right;
889: int containerHeight = parent.getBounds().height - i.top - i.bottom;
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915: if (titlePaneBounds == null)
916: titlePaneBounds = new Rectangle();
917: titlePaneBounds.width = containerWidth;
918: titlePaneBounds.height = titlePane.getPreferredSize().height;
919:
920:
921: if (menuBarBounds == null)
922: menuBarBounds = new Rectangle();
923: menuBarBounds.setBounds(0,
924: titlePaneBounds.y + titlePaneBounds.height,
925: containerWidth, 0);
926: if (menuBar != null)
927: {
928: Dimension menuBarSize = menuBar.getPreferredSize();
929: if (menuBarSize.height > containerHeight)
930: menuBarBounds.height = containerHeight;
931: else
932: menuBarBounds.height = menuBarSize.height;
933: }
934:
935:
936: if (contentPaneBounds == null)
937: contentPaneBounds = new Rectangle();
938: contentPaneBounds.setBounds(0,
939: menuBarBounds.y + menuBarBounds.height,
940: containerWidth,
941: containerHeight - menuBarBounds.y
942: - menuBarBounds.height);
943: glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
944: layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
945: }
946:
947:
948: glassPane.setBounds(glassPaneBounds);
949: layeredPane.setBounds(layeredPaneBounds);
950: if (menuBar != null)
951: menuBar.setBounds(menuBarBounds);
952: contentPane.setBounds(contentPaneBounds);
953: titlePane.setBounds(titlePaneBounds);
954: }
955:
956: }
957:
958:
961: private static MetalRootPaneUI instance;
962:
963:
966: public MetalRootPaneUI()
967: {
968: super();
969: }
970:
971:
978: public static ComponentUI createUI(JComponent component)
979: {
980: if (instance == null)
981: instance = new MetalRootPaneUI();
982: return instance;
983: }
984:
985:
992: public void installUI(JComponent c)
993: {
994: super.installUI(c);
995: JRootPane rp = (JRootPane) c;
996: if (rp.getWindowDecorationStyle() != JRootPane.NONE)
997: installWindowDecorations(rp);
998: }
999:
1000:
1007: public void uninstallUI(JComponent c)
1008: {
1009: JRootPane rp = (JRootPane) c;
1010: if (rp.getWindowDecorationStyle() != JRootPane.NONE)
1011: uninstallWindowDecorations(rp);
1012: super.uninstallUI(c);
1013: }
1014:
1015:
1022: public void propertyChange(PropertyChangeEvent ev)
1023: {
1024: super.propertyChange(ev);
1025: String propertyName = ev.getPropertyName();
1026: if (propertyName.equals("windowDecorationStyle"))
1027: {
1028: JRootPane rp = (JRootPane) ev.getSource();
1029: if (rp.getWindowDecorationStyle() != JRootPane.NONE)
1030: installWindowDecorations(rp);
1031: else
1032: uninstallWindowDecorations(rp);
1033: }
1034: }
1035:
1036:
1043: private void installWindowDecorations(JRootPane rp)
1044: {
1045: rp.setBorder(new MetalFrameBorder());
1046: MetalTitlePane titlePane = new MetalTitlePane(rp);
1047: rp.setLayout(new MetalRootLayout(titlePane));
1048:
1049: assert rp.getLayeredPane().getComponentCount() > 0
1050: : "We should have a contentPane already";
1051:
1052: rp.getLayeredPane().add(titlePane,
1053: JLayeredPane.FRAME_CONTENT_LAYER, 1);
1054: }
1055:
1056:
1062: private void uninstallWindowDecorations(JRootPane rp)
1063: {
1064: rp.setBorder(null);
1065: JLayeredPane lp = rp.getLayeredPane();
1066: for (int i = lp.getComponentCount() - 1; i >= 0; --i)
1067: {
1068: if (lp.getComponent(i) instanceof MetalTitlePane)
1069: {
1070: lp.remove(i);
1071: break;
1072: }
1073: }
1074: }
1075: }