/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Liquid Look and Feel * * * * Author, Miroslav Lazarevic * * * * For licensing information and credits, please refer to the * * comment in file com.birosoft.liquid.LiquidLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package com.birosoft.liquid; import com.birosoft.liquid.util.LiquidUtilities; import java.awt.*; import java.awt.event.*; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.beans.*; import javax.swing.*; import javax.swing.plaf.*; /* * @(#)LiquidTitlePane.java 1.10 01/12/03 * * Copyright 2002 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ /* * Class that manages a JLF awt.Window-descendant class's title bar. * <p> * This class assumes it will be created with a particular window * decoration style, and that if the style changes, a new one will * be created. * * @version 1.10 12/03/01 * @author Terry Kellerman * @since 1.4 */ /** * LiquidTitlePane * * @version 0.1 * @author Miroslav Lazarević */ class LiquidTitlePane extends JComponent { /** * */ private static final long serialVersionUID = -1424746354108457746L; private static final int IMAGE_HEIGHT = 16; private static final int IMAGE_WIDTH = 16; private static LiquidWindowButtonUI iconButtonUI; private static LiquidWindowButtonUI maxButtonUI; private static LiquidWindowButtonUI closeButtonUI; private static LiquidWindowButtonUI menuButtonUI; private boolean prevState = false; private boolean isMenuShowed = false; /** * Color for the title in a normal sized internal frame */ Color normalTitleColor = Color.white; /** * Color for the shadow of the title in a normal sized internal frame */ Color shadowColor = new Color(10, 24, 131); /** * Color for the title in a normal sized internal frame that is not enabled */ Color disabledTitleColor = new Color(216, 228, 244); /** * PropertyChangeListener added to the JRootPane. */ private PropertyChangeListener propertyChangeListener; /** * JMenuBar, typically renders the system menu items. */ private JMenuBar menuBar; /** * Action used to close the Window. */ private Action closeAction; /** * Action used to iconify the Frame. */ private Action iconifyAction; /** * Action to restore the Frame size. */ private Action restoreAction; /** * Action to restore the Frame size. */ private Action maximizeAction; private Action menuAction; /** * Button used to maximize or restore the Frame. */ private JButton toggleButton; /** * Button used to maximize or restore the Frame. */ private JButton iconifyButton; /** * Button used to maximize or restore the Frame. */ private JButton closeButton; private JButton menuButton; /** * Listens for changes in the state of the Window listener to update * the state of the widgets. */ private WindowListener windowListener; private ComponentListener windowMoveListener; /** * Window we're currently in. */ private Window window; /** * JRootPane rendering for. */ private JRootPane rootPane; /** * Buffered Frame.state property. As state isn't bound, this is kept * to determine when to avoid updating widgets. */ private int state; public LiquidTitlePane(JRootPane root, LiquidRootPaneUI ui) { rootPane = root; state = -1; installSubcomponents(); installDefaults(); setLayout(createLayout()); } /** * Installs the necessary listeners. */ private void installListeners() { if (window != null) { windowListener = createWindowListener(); window.addWindowListener(windowListener); propertyChangeListener = createWindowPropertyChangeListener(); window.addPropertyChangeListener(propertyChangeListener); windowMoveListener = new WindowMoveListener(); window.addComponentListener(windowMoveListener); } } /** * Uninstalls the necessary listeners. */ private void uninstallListeners() { if (window != null) { window.removeWindowListener(windowListener); window.removePropertyChangeListener(propertyChangeListener); window.removeComponentListener(windowMoveListener); } } /** * Returns the <code>WindowListener</code> to add to the * <code>Window</code>. */ private WindowListener createWindowListener() { return new WindowHandler(); } /** * Returns the <code>PropertyChangeListener</code> to install on * the <code>Window</code>. */ private PropertyChangeListener createWindowPropertyChangeListener() { return new PropertyChangeHandler(); } /** * Returns the <code>JRootPane</code> this was created for. */ public JRootPane getRootPane() { return rootPane; } public static void resetCachedSkins() { iconButtonUI = null; maxButtonUI = null; closeButtonUI = null; menuButtonUI = null; } /** * Returns the decoration style of the <code>JRootPane</code>. */ private int getWindowDecorationStyle() { return getRootPane().getWindowDecorationStyle(); } public void addNotify() { super.addNotify(); uninstallListeners(); window = SwingUtilities.getWindowAncestor(this); if (window != null) { if (window instanceof Frame) { setState(((Frame) window).getExtendedState()); } else { setState(0); } setActive(window.isActive()); installListeners(); } } public void removeNotify() { super.removeNotify(); uninstallListeners(); window = null; } /** * Adds any sub-Components contained in the <code>LiquidTitlePane</code>. */ private void installSubcomponents() { if (getWindowDecorationStyle() == JRootPane.FRAME) { createActions(); if (!LiquidLookAndFeel.winDecoPanther) { menuBar = createMenuBar(); add(menuBar); } createButtons(); add(iconifyButton); add(toggleButton); add(closeButton); if (LiquidLookAndFeel.winDecoPanther) { add(menuButton); menuButton.putClientProperty("externalFrameButton", Boolean.TRUE); } iconifyButton.putClientProperty("externalFrameButton", Boolean.TRUE); toggleButton.putClientProperty("externalFrameButton", Boolean.TRUE); closeButton.putClientProperty("externalFrameButton", Boolean.TRUE); /*System.out.println(rootPane.getIgnoreRepaint()); rootPane.setIgnoreRepaint(true); System.out.println(rootPane.getContentPane().getIgnoreRepaint()); rootPane.getContentPane().setIgnoreRepaint(true);*/ } else if (getWindowDecorationStyle() != JRootPane.NONE) { createActions(); createButtons(); add(closeButton); closeButton.putClientProperty("externalFrameButton", Boolean.FALSE); if (LiquidLookAndFeel.winDecoPanther) { add(menuButton); menuButton.putClientProperty("externalFrameButton", Boolean.FALSE); } } } /** * Installs the fonts and necessary properties on the LiquidTitlePane. */ private void installDefaults() { // setFont(UIManager.getFont("InternalFrame.titleFont", getLocale())); Font font = LiquidLookAndFeel.winDecoPanther ? UIManager.getFont("InternalFrame.pantherTitleFont") : UIManager.getFont("InternalFrame.titleFont"); setFont(font); } /** * Returns the <code>JMenuBar</code> displaying the appropriate * system menu items. */ protected JMenuBar createMenuBar() { menuBar = new SystemMenuBar(createMenu()); menuBar.setFocusable(false); menuBar.setBorderPainted(true); //menuBar.add(createMenu()); return menuBar; } /** * Closes the Window. */ private void close() { isMenuShowed = false; Window window = getWindow(); if (window != null) { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); } } /** * Iconifies the Frame. */ private void iconify() { isMenuShowed = false; Frame frame = getFrame(); if (frame != null) { frame.setExtendedState(state | Frame.ICONIFIED); } } /** * Maximizes the Frame. */ private void maximize() { isMenuShowed = false; Frame frame = getFrame(); if (frame != null) { setMaximizeBounds(frame); frame.setExtendedState(state | Frame.MAXIMIZED_BOTH); } } private void setMaximizeBounds(Frame frame) { if (frame.getMaximizedBounds() != null) { return; } Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration()); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // spare any Systemmenus or Taskbars or ??... int x = screenInsets.left; int y = screenInsets.top; int w = screenSize.width - x - screenInsets.right; int h = screenSize.height - y - screenInsets.bottom; Rectangle maxBounds = new Rectangle(x, y, w, h); frame.setMaximizedBounds(maxBounds); } /** * Restores the Frame size. */ private void restore() { isMenuShowed = false; Frame frame = getFrame(); if (frame == null) { return; } if ((state & Frame.ICONIFIED) != 0) { frame.setExtendedState(state & ~Frame.ICONIFIED); } else { frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH); } } private void showMenu(JPopupMenu systemMenu) { if (!isMenuShowed) { systemMenu.show(this, LiquidLookAndFeel.winDecoPanther ? (getWidth() - systemMenu.getPreferredSize().width) : 0, 21); isMenuShowed = true; } else { isMenuShowed = false; systemMenu.setVisible(isMenuShowed); } } /** * Create the <code>Action</code>s that get associated with the * buttons and menu items. */ private void createActions() { closeAction = new CloseAction(); iconifyAction = new IconifyAction(); restoreAction = new RestoreAction(); maximizeAction = new MaximizeAction(); menuAction = new MenuAction(); } /** * Returns the <code>JMenu</code> displaying the appropriate menu items * for manipulating the Frame. */ private JPopupMenu createMenu() { JPopupMenu menu = new JPopupMenu(); if ((getWindowDecorationStyle() == JRootPane.FRAME) || (getWindowDecorationStyle() == JRootPane.PLAIN_DIALOG)) { addMenuItems(menu); // we use this property to prevent the Menu from drawing rollovers menu.putClientProperty("isSystemMenu", Boolean.TRUE); } return menu; } /** * Adds the necessary <code>JMenuItem</code>s to the passed in menu. */ private void addMenuItems(JPopupMenu menu) { JMenuItem mi = menu.add(restoreAction); mi.setMnemonic('r'); mi = menu.add(iconifyAction); mi.setMnemonic('e'); if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { mi = menu.add(maximizeAction); mi.setMnemonic('x'); } menu.addSeparator(); mi = menu.add(closeAction); mi.setMnemonic('c'); } /** * Creates the buttons of the title pane and initializes their actions. */ protected void createButtons() { if (iconButtonUI == null) { iconButtonUI = LiquidWindowButtonUI.createButtonUIForType(LiquidWindowButtonUI.MINIMIZE); maxButtonUI = LiquidWindowButtonUI.createButtonUIForType(LiquidWindowButtonUI.MAXIMIZE); closeButtonUI = LiquidWindowButtonUI.createButtonUIForType(LiquidWindowButtonUI.CLOSE); if (LiquidLookAndFeel.winDecoPanther) { menuButtonUI = LiquidWindowButtonUI.createButtonUIForType(LiquidWindowButtonUI.SYSMENU); } } iconifyButton = new SpecialUIButton(iconButtonUI, (Window) getRootPane().getParent()); iconifyButton.setAction(iconifyAction); iconifyButton.setRolloverEnabled(true); toggleButton = new SpecialUIButton(maxButtonUI, (Window) getRootPane().getParent()); toggleButton.setAction(maximizeAction); toggleButton.setRolloverEnabled(true); closeButton = new SpecialUIButton(closeButtonUI, (Window) getRootPane().getParent()); closeButton.setAction(closeAction); closeButton.setRolloverEnabled(true); if (LiquidLookAndFeel.winDecoPanther) { menuButton = new SpecialUIButton(menuButtonUI, (Window) getRootPane().getParent()); menuButton.setAction(menuAction); menuButton.setRolloverEnabled(true); menuButton.getAccessibleContext().setAccessibleName("Menu"); } closeButton.getAccessibleContext().setAccessibleName("Close"); iconifyButton.getAccessibleContext().setAccessibleName("Iconify"); toggleButton.getAccessibleContext().setAccessibleName("Maximize"); } /** * Returns the <code>LayoutManager</code> that should be installed on * the <code>LiquidTitlePane</code>. */ private LayoutManager createLayout() { return new TitlePaneLayout(); } /** * Updates state dependant upon the Window's active state. */ private void setActive(boolean isActive) { if (getWindowDecorationStyle() == JRootPane.FRAME) { Boolean activeB = isActive ? Boolean.TRUE : Boolean.FALSE; iconifyButton.putClientProperty("paintActive", activeB); closeButton.putClientProperty("paintActive", activeB); toggleButton.putClientProperty("paintActive", activeB); iconifyButton.setEnabled(isActive); closeButton.setEnabled(isActive); toggleButton.setEnabled(isActive); if (LiquidLookAndFeel.winDecoPanther) { menuButton.putClientProperty("paintActive", activeB); menuButton.setEnabled(isActive); } } // Repaint the whole thing as the Borders that are used have // different colors for active vs inactive getRootPane().repaint(); } /** * Sets the state of the Window. */ private void setState(int state) { setState(state, false); } /** * Sets the state of the window. If <code>updateRegardless</code> is * true and the state has not changed, this will update anyway. */ private void setState(int state, boolean updateRegardless) { Window w = getWindow(); if ((w != null) && ((getWindowDecorationStyle() == JRootPane.FRAME) || (getWindowDecorationStyle() == JRootPane.PLAIN_DIALOG))) { if ((this.state == state) && !updateRegardless) { return; } Frame frame = getFrame(); if (frame != null) { JRootPane rootPane = getRootPane(); if (((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) && ((rootPane.getBorder() == null) || (rootPane.getBorder() instanceof UIResource)) && frame.isShowing()) { //rootPane.setBorder(null); } else if ((state & Frame.MAXIMIZED_BOTH) != Frame.MAXIMIZED_BOTH) { // This is a croak, if state becomes bound, this can // be nuked. //rootPaneUI.installBorder(rootPane); } if (frame.isResizable()) { if (((state & Frame.MAXIMIZED_VERT) == Frame.MAXIMIZED_VERT) || ((state & Frame.MAXIMIZED_HORIZ) == Frame.MAXIMIZED_HORIZ)) { updateToggleButton(restoreAction); maximizeAction.setEnabled(false); restoreAction.setEnabled(true); } else { updateToggleButton(maximizeAction); maximizeAction.setEnabled(true); restoreAction.setEnabled(false); } if ((toggleButton.getParent() == null) || (iconifyButton.getParent() == null)) { add(toggleButton); add(iconifyButton); revalidate(); repaint(); } toggleButton.setText(null); } else { maximizeAction.setEnabled(false); restoreAction.setEnabled(false); if (toggleButton.getParent() != null) { remove(toggleButton); revalidate(); repaint(); } } } else { // Not contained in a Frame maximizeAction.setEnabled(false); restoreAction.setEnabled(false); iconifyAction.setEnabled(false); remove(toggleButton); remove(iconifyButton); revalidate(); repaint(); } closeAction.setEnabled(true); this.state = state; } } /** * Updates the toggle button to contain the Icon <code>icon</code>, and * Action <code>action</code>. */ private void updateToggleButton(Action action) { toggleButton.setAction(action); toggleButton.setText(null); } /** * Returns the Frame rendering in. This will return null if the * <code>JRootPane</code> is not contained in a <code>Frame</code>. */ private Frame getFrame() { Window window = getWindow(); if (window instanceof Frame) { return (Frame) window; } return null; } /** * Returns the <code>Window</code> the <code>JRootPane</code> is * contained in. This will return null if there is no parent ancestor * of the <code>JRootPane</code>. */ private Window getWindow() { return window; } /** * Returns the String to display as the title. */ private String getTitle() { Window w = getWindow(); if (w instanceof Frame) { return ((Frame) w).getTitle(); } else if (w instanceof Dialog) { return ((Dialog) w).getTitle(); } return null; } public boolean isSelected() { Window window = getWindow(); return (window == null) ? true : window.isActive(); } public boolean isFrameMaximized() { Frame frame = getFrame(); if (frame != null) { return ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH); } return false; } /** * Renders the TitlePane. */ public void paintComponent(Graphics g) { if (getFrame() != null) { setState(getFrame().getExtendedState()); } Window frame = getWindow(); boolean leftToRight = frame.getComponentOrientation().isLeftToRight(); boolean isSelected = isSelected(); if (isSelected) { prevState = true; } if (!prevState && !isSelected) { isSelected = true; } int width = getWidth(); int height = getHeight(); Graphics2D g2 = (Graphics2D) g; Object oldAntiAliasingValue = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, // RenderingHints.VALUE_FRACTIONALMETRICS_ON); if (LiquidLookAndFeel.winDecoPanther) { drawPantherCaption(g, isSelected, width, height); } else { drawLiquidCaption(g, isSelected, width, height); } int titleLength = 0; int xOffset = leftToRight ? 2 : (width - 2); String frameTitle = getTitle(); int xOvalOffset = 8; // Add in the oval offset xOffset += (leftToRight && !LiquidLookAndFeel.winDecoPanther) ? xOvalOffset : 0; if (frameTitle != null) { Font f = getFont(); g.setFont(f); int osFontOffset = f.getFamily().equals(LiquidLookAndFeel.fontName) ? 2 : 0; FontMetrics fm = g.getFontMetrics(); titleLength = fm.stringWidth(frameTitle); int titleW = 0; Rectangle r = new Rectangle(0, 0, 0, 0); if( leftToRight && !LiquidLookAndFeel.winDecoPanther ) { if (iconifyAction.isEnabled()) { r = iconifyButton.getBounds(); } else if (maximizeAction.isEnabled()) { r = toggleButton.getBounds(); } else if (closeAction.isEnabled()) { r = closeButton.getBounds(); } if( r.x == 0 ) { r.x = frame.getWidth()-frame.getInsets().right; } xOffset += menuBar != null ? (menuBar.getX() + menuBar.getWidth() + 2) : 2; titleW = r.x - xOffset - xOvalOffset -2; } else { if (maximizeAction.isEnabled()) { r = toggleButton.getBounds(); } else if (iconifyAction.isEnabled()) { r = iconifyButton.getBounds(); } else if (closeAction.isEnabled()) { r = closeButton.getBounds(); } Rectangle menu = new Rectangle(0, 0, 0, 0); if( menuButton != null ) { menu = menuButton.getBounds(); } if( menu.x == 0 ) { menu.x = frame.getWidth()-frame.getInsets().right; } xOffset = r.x + r.width + 2; titleW = menu.x - xOffset; } int startTitleLength = fm.stringWidth(frameTitle); frameTitle = LiquidUtilities.clipStringIfNecessary(fm, frameTitle, titleW); titleLength = fm.stringWidth(frameTitle); if( titleLength == startTitleLength ) { xOffset += (titleW - titleLength) / 2; } // System.out.println("Title Height = " + height); // // System.out.println("osFontOffset = " + osFontOffset); // System.out.println("Font = " + f); // System.out.println("Font.size = " + f.getSize()); // System.out.println("FontMetrics.getAscent = " + fm.getAscent()); // System.out.println("FontMetrics.getDescent = " + fm.getDescent()); // System.out.println("FontMetrics.getHeight = " + fm.getHeight()); FontRenderContext frc = g2.getFontRenderContext(); LineMetrics lm = f.getLineMetrics(frameTitle, frc); // System.out.println("LineMetrics.getAscent = " + lm.getAscent()); // System.out.println("LineMetrics.getDescent = " + lm.getDescent()); // System.out.println("LineMetrics.getHeight = " + lm.getHeight()); // a shadow effect for the titles in normal sized internal frames // int yOffset = ((height - f.getSize()) / 2) + fm.getAscent() + osFontOffset; int yOffset = ((height - Math.round(lm.getHeight())) / 2) + Math.round(lm.getAscent()) + osFontOffset; int endOffset = 19;//height - (yOffset - 15) - Math.round(lm.getDescent()); // System.out.println("yOffset = " + yOffset); // System.out.println("endOffset = " + endOffset); if (!leftToRight) { xOffset -= titleLength; } if (isSelected) { // for an active window if (!LiquidLookAndFeel.winDecoPanther && titleLength > 0) { GradientPaint grad = new GradientPaint(xOffset + (titleLength / 2), yOffset - 15, new Color(60, 144, 233), xOffset + (titleLength / 2), endOffset, new Color(102, 186, 255)); g2.setPaint(grad); g2.fillRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18); g.setColor(new Color(0, 78, 167)); g2.drawRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18); } if (!LiquidLookAndFeel.winDecoPanther) { g.setColor(shadowColor);//Color.black); g.drawString(frameTitle, xOffset + 1, yOffset); g.setColor(normalTitleColor); } else { g.setColor(Color.black); Frame _frame = null; Dialog _dialog = null; Image image = null; Window w = getWindow(); if (w instanceof Frame) { _frame = (Frame) w; image = _frame.getIconImage(); } else { _dialog = (Dialog) w; if (_dialog.getParent() != null) { if (_dialog.getParent() instanceof Frame) { image = ((Frame) _dialog.getParent()).getIconImage(); } } } if (image != null) { xOffset += 10; g.drawImage(image, xOffset - 20, 3, IMAGE_WIDTH, IMAGE_HEIGHT, null); } else { Icon icon = UIManager.getIcon( "InternalFrame.pantherIcon"); if (icon != null) { xOffset += 10; icon.paintIcon(this, g, xOffset - 20, 3); } } } g.drawString(frameTitle, xOffset, yOffset - 1); xOffset += (leftToRight ? (titleLength + 2) : (-2)); } else { // for an inactive window if (!LiquidLookAndFeel.winDecoPanther && titleLength > 0) { GradientPaint grad = new GradientPaint(xOffset + (titleLength / 2), yOffset - 15, new Color(191, 211, 233), xOffset + (titleLength / 2), endOffset, new Color(233, 253, 255)); g2.setPaint(grad); //g2.fillRoundRect(xOffset-8, yOffset-15, titleLength+15, fm.getHeight()+1, 18, 18); g2.fillRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18); g.setColor(new Color(125, 145, 167)); //g2.drawRoundRect(xOffset-8, yOffset-15, titleLength+15, fm.getHeight()+1, 18, 18); g2.drawRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18); } if (LiquidLookAndFeel.winDecoPanther) { Frame _frame = null; Dialog _dialog = null; Image image = null; Window w = getWindow(); if (w instanceof Frame) { _frame = (Frame) w; image = _frame.getIconImage(); } else { _dialog = (Dialog) w; if (_dialog.getParent() != null) { if (_dialog.getParent() instanceof Frame) { image = ((Frame) _dialog.getParent()).getIconImage(); } } } if (image != null) { xOffset += 10; g.drawImage(image, xOffset - 20, 3, IMAGE_WIDTH, IMAGE_HEIGHT, null); } else { Icon icon = UIManager.getIcon( "InternalFrame.pantherIconInactive"); if (icon != null) { xOffset += 10; icon.paintIcon(this, g, xOffset - 20, 3); } } } g.setColor(LiquidLookAndFeel.winDecoPanther ? new Color(115, 115, 115) : Color.black); g.drawString(frameTitle, xOffset, yOffset - 1); xOffset += (leftToRight ? (titleLength + 2) : (-2)); } } g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntiAliasingValue); // g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, // RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT); } private void drawLiquidCaption(Graphics g, boolean isSelected, int w, int h) { Color c = isSelected ? new Color(62, 145, 235) : new Color(175, 214, 255); g.setColor(c); g.fillRect(0, 0, w, h - 1); c = isSelected ? new Color(94, 172, 255) : new Color(226, 240, 255); g.setColor(c); g.drawLine(0, 0, w, 0); c = isSelected ? new Color(60, 141, 228) : new Color(170, 207, 247); g.setColor(c); g.drawLine(0, 1, w, 1); for (int i = 4; i < (h - 1); i += 4) { c = isSelected ? new Color(59, 138, 223) : new Color(166, 203, 242); g.setColor(c); g.drawLine(0, i, w, i); c = isSelected ? new Color(60, 141, 228) : new Color(170, 207, 247); g.setColor(c); g.drawLine(0, i + 1, w, i + 1); } c = isSelected ? new Color(47, 111, 180) : new Color(135, 164, 196); g.setColor(c); g.drawLine(0, h - 1, w, h - 1); } private void drawPantherCaption(Graphics g, boolean isSelected, int w, int h) { Graphics2D g2 = (Graphics2D) g; GradientPaint grad = isSelected ? new GradientPaint(0, 0, new Color(238, 238, 238), 0, h - 1, new Color(192, 192, 192)) : new GradientPaint(0, 0, new Color(230, 230, 230), 0, h - 1, new Color(202, 202, 202)); g2.setPaint(grad); g2.fillRect(0, 0, w, h - 1); g2.setColor(new Color(198, 198, 198)); g2.drawLine(0, 0, w - 1, 0); g2.setColor(Color.WHITE); g2.drawLine(0, 1, w - 1, 1); g2.setColor(new Color(147, 147, 147)); g2.drawLine(0, h - 1, w, h - 1); } /** * Actions used to <code>close</code> the <code>Window</code>. */ private class CloseAction extends AbstractAction { /** * */ private static final long serialVersionUID = 1650870353459807265L; public CloseAction() { super("Close"); } public void actionPerformed(ActionEvent e) { close(); } } /** * Actions used to <code>iconfiy</code> the <code>Frame</code>. */ private class IconifyAction extends AbstractAction { /** * */ private static final long serialVersionUID = -1568241802569872804L; public IconifyAction() { super("Minimize"); } public void actionPerformed(ActionEvent e) { iconify(); } } /** * Actions used to <code>restore</code> the <code>Frame</code>. */ private class RestoreAction extends AbstractAction { /** * */ private static final long serialVersionUID = -8278229416441409721L; public RestoreAction() { super("Restore"); } public void actionPerformed(ActionEvent e) { restore(); } } /** * Actions used to <code>restore</code> the <code>Frame</code>. */ private class MaximizeAction extends AbstractAction { /** * */ private static final long serialVersionUID = -483155396622664537L; public MaximizeAction() { super("Maximize"); } public void actionPerformed(ActionEvent e) { maximize(); } } private class MenuAction extends AbstractAction { /** * */ private static final long serialVersionUID = -9191861525972000095L; public MenuAction() { super("Menu"); } public void actionPerformed(ActionEvent e) { showMenu(createMenu()); } } /** * Class responsible for drawing the system menu. Looks up the * image to draw from the Frame associated with the * <code>JRootPane</code>. */ private class SystemMenuBar extends JMenuBar implements MouseListener { /** * */ private static final long serialVersionUID = 3248211542099676445L; private JPopupMenu systemMenu; private boolean isShowed = false; public SystemMenuBar(JPopupMenu menu) { super(); systemMenu = menu; addMouseListener(this); } protected void setSystemMenuVisible(boolean b) { isShowed = b; } public void paint(Graphics g) { if (LiquidLookAndFeel.winDecoPanther) { return; } Frame frame = getFrame(); Image image = (frame != null) ? frame.getIconImage() : null; if (image != null) { g.drawImage(image, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); } else { Icon icon = UIManager.getIcon("InternalFrame.icon"); if (icon != null) { icon.paintIcon(this, g, 0, 0); } } } public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getPreferredSize() { Icon icon = UIManager.getIcon("InternalFrame.icon"); if (icon != null) { return new Dimension(icon.getIconWidth(), icon.getIconHeight()); } Dimension size = super.getPreferredSize(); return new Dimension(Math.max(IMAGE_WIDTH, size.width), Math.max(size.height, IMAGE_HEIGHT)); } public void mouseClicked(MouseEvent e) { if (!isShowed) { systemMenu.show(this, 0, 18); isShowed = true; } else { isShowed = false; systemMenu.setVisible(isShowed); } } public void mouseEntered(MouseEvent e) { if (!systemMenu.isVisible()) { isShowed = false; } } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } } /** * This inner class is marked "public" due to a compiler bug. * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of <Foo>. */ private class TitlePaneLayout implements LayoutManager { public void addLayoutComponent(String name, Component c) { } public void removeLayoutComponent(Component c) { } public Dimension preferredLayoutSize(Container c) { int height = computeHeight(); return new Dimension(height, height); } public Dimension minimumLayoutSize(Container c) { return preferredLayoutSize(c); } private int computeHeight() { if (getFrame() instanceof JFrame) { setMaximizeBounds(getFrame()); if (LiquidLookAndFeel.winDecoPanther) { return 22; } return 24; } else { if (LiquidLookAndFeel.winDecoPanther) { return 22; } return 24; } } public void layoutContainer(Container c) { if (getWindowDecorationStyle() == JRootPane.NONE) { return; } boolean leftToRight = (window == null) ? getRootPane().getComponentOrientation().isLeftToRight() : window.getComponentOrientation().isLeftToRight(); if( LiquidLookAndFeel.winDecoPanther ) { leftToRight = !leftToRight; } int w = getWidth(); int x; int spacing; int buttonHeight; int buttonWidth; if (closeButton != null) { buttonHeight = closeButton.getPreferredSize().height; buttonWidth = closeButton.getPreferredSize().width; } else { buttonHeight = IMAGE_HEIGHT; buttonWidth = IMAGE_WIDTH; } int y = ((getHeight() - buttonHeight) / 2) + 1; //if (Theme.derivedStyle[Theme.style] == Theme.WIN_STYLE) { // y += 1; //} // assumes all buttons have the same dimensions // these dimensions include the borders //x = leftToRight ? w : 0; spacing = LiquidLookAndFeel.winDecoPanther ? 7 : 0; x = leftToRight ? spacing : (w - buttonWidth - spacing); if (menuBar != null) { // this is a JFrame menuBar.setBounds(x, y, buttonWidth, buttonHeight); } // bound for buttons x = leftToRight ? w : 0; x += (LiquidLookAndFeel.winDecoPanther ? (leftToRight ? (-spacing - 3 - buttonWidth) : spacing) : (leftToRight ? (-spacing - buttonWidth) : spacing)); int yOffset = LiquidLookAndFeel.winDecoPanther ? 1 : 0; if (closeButton != null) { closeButton.setBounds(x, y - yOffset, buttonWidth, buttonHeight); } if (menuButton != null) { menuButton.setBounds(leftToRight ? 3 : (w - 21 - spacing), y - yOffset + 1, 21, 12); //menuButton.setBounds(3, y - yOffset + 1, 21, 12); } if (!leftToRight) { x += buttonWidth; } if( LiquidLookAndFeel.winDecoPanther ) { if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { x += (leftToRight ? (-spacing - buttonWidth) : spacing); iconifyButton.setBounds(x, y - yOffset, buttonWidth, buttonHeight); if (!leftToRight) { x += buttonWidth; } } } if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { if (toggleButton.getParent() != null) { x += (leftToRight ? (-spacing - buttonWidth) : spacing); toggleButton.setBounds(x, y - yOffset, buttonWidth, buttonHeight); if (!leftToRight) { x += buttonWidth; } } } if( !LiquidLookAndFeel.winDecoPanther ) { if ((iconifyButton != null) && (iconifyButton.getParent() != null)) { x += (leftToRight ? (-spacing - buttonWidth) : spacing); iconifyButton.setBounds(x, y - yOffset, buttonWidth, buttonHeight); if (!leftToRight) { x += buttonWidth; } } } } } /** * PropertyChangeListener installed on the Window. Updates the necessary * state as the state of the Window changes. */ private class PropertyChangeHandler implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent pce) { String name = pce.getPropertyName(); // Frame.state isn't currently bound. if ("resizable".equals(name) || "state".equals(name)) { Frame frame = getFrame(); if (frame != null) { setState(frame.getExtendedState(), true); } if ("resizable".equals(name)) { getRootPane().repaint(); } } else if ("title".equals(name)) { repaint(); } else if ("componentOrientation".equals(name)) { revalidate(); repaint(); } } } /** * WindowListener installed on the Window, updates the state as necessary. */ private class WindowHandler extends WindowAdapter { public void windowActivated(WindowEvent ev) { setActive(true); } public void windowDeactivated(WindowEvent ev) { setActive(false); } } class WindowMoveListener extends ComponentAdapter { /** * @see java.awt.event.ComponentListener#componentMoved(ComponentEvent) */ public void componentMoved(ComponentEvent e) { if (getWindowDecorationStyle() == JRootPane.NONE) { return; } Window w = getWindow(); w.repaint(0, 0, w.getWidth(), 5); } /** * @see java.awt.event.ComponentAdapter#componentResized(ComponentEvent) */ public void componentResized(ComponentEvent e) { if (getWindowDecorationStyle() == JRootPane.NONE) { return; } Window w = getWindow(); w.repaint(0, 0, w.getWidth(), 5); } } }