489 lines · 17.8 KB · Java
RawDownload
/* * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.synth; import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.plaf.*;import javax.swing.plaf.basic.BasicInternalFrameTitlePane;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;import java.beans.PropertyVetoException;import sun.swing.SwingUtilities2; /** * The class that manages a synth title bar * * @author David Kloba * @author Joshua Outwater * @author Steve Wilson */class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane        implements SynthUI, PropertyChangeListener {     protected JPopupMenu systemPopupMenu;    protected JButton menuButton;     private SynthStyle style;    private int titleSpacing;    private int buttonSpacing;    // Alignment for the title, one of SwingConstants.(LEADING|TRAILING|CENTER)    private int titleAlignment;     public SynthInternalFrameTitlePane(JInternalFrame f) {        super(f);    }     public String getUIClassID() {        return "InternalFrameTitlePaneUI";    }     public SynthContext getContext(JComponent c) {        return getContext(c, getComponentState(c));    }     public SynthContext getContext(JComponent c, int state) {        return SynthContext.getContext(SynthContext.class, c,                    SynthLookAndFeel.getRegion(c), style, state);    }     private Region getRegion(JComponent c) {        return SynthLookAndFeel.getRegion(c);    }     private int getComponentState(JComponent c) {        if (frame != null) {            if (frame.isSelected()) {                return SELECTED;            }        }        return SynthLookAndFeel.getComponentState(c);    }     protected void addSubComponents() {        menuButton.setName("InternalFrameTitlePane.menuButton");        iconButton.setName("InternalFrameTitlePane.iconifyButton");        maxButton.setName("InternalFrameTitlePane.maximizeButton");        closeButton.setName("InternalFrameTitlePane.closeButton");         add(menuButton);        add(iconButton);        add(maxButton);        add(closeButton);    }     protected void installListeners() {        super.installListeners();        frame.addPropertyChangeListener(this);        addPropertyChangeListener(this);    }     protected void uninstallListeners() {        frame.removePropertyChangeListener(this);        removePropertyChangeListener(this);        super.uninstallListeners();    }     private void updateStyle(JComponent c) {        SynthContext context = getContext(this, ENABLED);        SynthStyle oldStyle = style;        style = SynthLookAndFeel.updateStyle(context, this);        if (style != oldStyle) {            maxIcon =                style.getIcon(context,"InternalFrameTitlePane.maximizeIcon");            minIcon =                style.getIcon(context,"InternalFrameTitlePane.minimizeIcon");            iconIcon =                style.getIcon(context,"InternalFrameTitlePane.iconifyIcon");            closeIcon =                style.getIcon(context,"InternalFrameTitlePane.closeIcon");            titleSpacing = style.getInt(context,                              "InternalFrameTitlePane.titleSpacing", 2);            buttonSpacing = style.getInt(context,                              "InternalFrameTitlePane.buttonSpacing", 2);            String alignString = (String)style.get(context,                              "InternalFrameTitlePane.titleAlignment");            titleAlignment = SwingConstants.LEADING;            if (alignString != null) {                alignString = alignString.toUpperCase();                if (alignString.equals("TRAILING")) {                    titleAlignment = SwingConstants.TRAILING;                }                else if (alignString.equals("CENTER")) {                    titleAlignment = SwingConstants.CENTER;                }            }        }        context.dispose();    }     protected void installDefaults() {        super.installDefaults();        updateStyle(this);    }     protected void uninstallDefaults() {        SynthContext context = getContext(this, ENABLED);        style.uninstallDefaults(context);        context.dispose();        style = null;        JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();        if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {            // Release link to systemMenu from the JInternalFrame            di.setComponentPopupMenu(null);        }        super.uninstallDefaults();    }     private static class JPopupMenuUIResource extends JPopupMenu implements        UIResource { }     protected void assembleSystemMenu() {        systemPopupMenu = new JPopupMenuUIResource();        addSystemMenuItems(systemPopupMenu);        enableActions();        menuButton = createNoFocusButton();        updateMenuIcon();        menuButton.addMouseListener(new MouseAdapter() {            public void mousePressed(MouseEvent e) {                try {                    frame.setSelected(true);                } catch(PropertyVetoException pve) {                }                showSystemMenu();            }        });        JPopupMenu p = frame.getComponentPopupMenu();        if (p == null || p instanceof UIResource) {            frame.setComponentPopupMenu(systemPopupMenu);        }        if (frame.getDesktopIcon() != null) {            p = frame.getDesktopIcon().getComponentPopupMenu();            if (p == null || p instanceof UIResource) {                frame.getDesktopIcon().setComponentPopupMenu(systemPopupMenu);            }        }        setInheritsPopupMenu(true);    }     protected void addSystemMenuItems(JPopupMenu menu) {        // PENDING: this should all be localizable!        JMenuItem mi = menu.add(restoreAction);        mi.setMnemonic('R');        mi = menu.add(moveAction);        mi.setMnemonic('M');        mi = menu.add(sizeAction);        mi.setMnemonic('S');        mi = menu.add(iconifyAction);        mi.setMnemonic('n');        mi = menu.add(maximizeAction);        mi.setMnemonic('x');        menu.add(new JSeparator());        mi = menu.add(closeAction);        mi.setMnemonic('C');    }     protected void showSystemMenu() {        Insets insets = frame.getInsets();        if (!frame.isIcon()) {            systemPopupMenu.show(frame, menuButton.getX(), getY() + getHeight());        } else {            systemPopupMenu.show(menuButton,                getX() - insets.left - insets.right,                getY() - systemPopupMenu.getPreferredSize().height -                    insets.bottom - insets.top);        }    }     // SynthInternalFrameTitlePane has no UI, we'll invoke paint on it.    public void paintComponent(Graphics g) {        SynthContext context = getContext(this);        SynthLookAndFeel.update(context, g);        context.getPainter().paintInternalFrameTitlePaneBackground(context,                          g, 0, 0, getWidth(), getHeight());        paint(context, g);        context.dispose();    }     protected void paint(SynthContext context, Graphics g) {        String title = frame.getTitle();         if (title != null) {            SynthStyle style = context.getStyle();             g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));            g.setFont(style.getFont(context));             // Center text vertically.            FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g);            int baseline = (getHeight() + fm.getAscent() - fm.getLeading() -                            fm.getDescent()) / 2;            JButton lastButton = null;            if (frame.isIconifiable()) {                lastButton = iconButton;            }            else if (frame.isMaximizable()) {                lastButton = maxButton;            }            else if (frame.isClosable()) {                lastButton = closeButton;            }            int maxX;            int minX;            boolean ltr = SynthLookAndFeel.isLeftToRight(frame);            int titleAlignment = this.titleAlignment;            if (ltr) {                if (lastButton != null) {                    maxX = lastButton.getX() - titleSpacing;                }                else {                    maxX = frame.getWidth() - frame.getInsets().right -                           titleSpacing;                }                minX = menuButton.getX() + menuButton.getWidth() +                       titleSpacing;            }            else {                if (lastButton != null) {                    minX = lastButton.getX() + lastButton.getWidth() +                           titleSpacing;                }                else {                    minX = frame.getInsets().left + titleSpacing;                }                maxX = menuButton.getX() - titleSpacing;                if (titleAlignment == SwingConstants.LEADING) {                    titleAlignment = SwingConstants.TRAILING;                }                else if (titleAlignment == SwingConstants.TRAILING) {                    titleAlignment = SwingConstants.LEADING;                }            }            String clippedTitle = getTitle(title, fm, maxX - minX);            if (clippedTitle == title) {                // String fit, align as necessary.                if (titleAlignment == SwingConstants.TRAILING) {                    minX = maxX - style.getGraphicsUtils(context).                        computeStringWidth(context, g.getFont(), fm, title);                }                else if (titleAlignment == SwingConstants.CENTER) {                    int width = style.getGraphicsUtils(context).                           computeStringWidth(context, g.getFont(), fm, title);                    minX = Math.max(minX, (getWidth() - width) / 2);                    minX = Math.min(maxX - width, minX);                }            }            style.getGraphicsUtils(context).paintText(                context, g, clippedTitle, minX, baseline - fm.getAscent(), -1);        }    }     public void paintBorder(SynthContext context, Graphics g, int x,                            int y, int w, int h) {        context.getPainter().paintInternalFrameTitlePaneBorder(context,                                                            g, x, y, w, h);    }     protected LayoutManager createLayout() {        SynthContext context = getContext(this);        LayoutManager lm =            (LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");        context.dispose();        return (lm != null) ? lm : new SynthTitlePaneLayout();    }     public void propertyChange(PropertyChangeEvent evt) {        if (evt.getSource() == this) {            if (SynthLookAndFeel.shouldUpdateStyle(evt)) {                updateStyle(this);            }        }        else {            // Changes for the internal frame            if (evt.getPropertyName() == JInternalFrame.FRAME_ICON_PROPERTY) {                updateMenuIcon();            }        }    }     /**     * Resets the menuButton icon to match that of the frame.     */    private void updateMenuIcon() {        Icon frameIcon = frame.getFrameIcon();        SynthContext context = getContext(this);        if (frameIcon != null) {            Dimension maxSize = (Dimension)context.getStyle().get(context,                                "InternalFrameTitlePane.maxFrameIconSize");            int maxWidth = 16;            int maxHeight = 16;            if (maxSize != null) {                maxWidth = maxSize.width;                maxHeight = maxSize.height;            }            if ((frameIcon.getIconWidth() > maxWidth ||                     frameIcon.getIconHeight() > maxHeight) &&                    (frameIcon instanceof ImageIcon)) {                frameIcon = new ImageIcon(((ImageIcon)frameIcon).                             getImage().getScaledInstance(maxWidth, maxHeight,                             Image.SCALE_SMOOTH));            }        }        context.dispose();        menuButton.setIcon(frameIcon);    }      class SynthTitlePaneLayout implements LayoutManager {        public void addLayoutComponent(String name, Component c) {}        public void removeLayoutComponent(Component c) {}        public Dimension preferredLayoutSize(Container c)  {            return minimumLayoutSize(c);        }         public Dimension minimumLayoutSize(Container c) {            SynthContext context = getContext(                             SynthInternalFrameTitlePane.this);            int width = 0;            int height = 0;             int buttonCount = 0;            Dimension pref;             if (frame.isClosable()) {                pref = closeButton.getPreferredSize();                width += pref.width;                height = Math.max(pref.height, height);                buttonCount++;            }            if (frame.isMaximizable()) {                pref = maxButton.getPreferredSize();                width += pref.width;                height = Math.max(pref.height, height);                buttonCount++;            }            if (frame.isIconifiable()) {                pref = iconButton.getPreferredSize();                width += pref.width;                height = Math.max(pref.height, height);                buttonCount++;            }            pref = menuButton.getPreferredSize();            width += pref.width;            height = Math.max(pref.height, height);             width += Math.max(0, (buttonCount - 1) * buttonSpacing);             FontMetrics fm = SynthInternalFrameTitlePane.this.getFontMetrics(                                          getFont());            SynthGraphicsUtils graphicsUtils = context.getStyle().                                       getGraphicsUtils(context);            String frameTitle = frame.getTitle();            int title_w = frameTitle != null ? graphicsUtils.                               computeStringWidth(context, fm.getFont(),                               fm, frameTitle) : 0;            int title_length = frameTitle != null ? frameTitle.length() : 0;             // Leave room for three characters in the title.            if (title_length > 3) {                int subtitle_w = graphicsUtils.computeStringWidth(context,                    fm.getFont(), fm, frameTitle.substring(0, 3) + "...");                width += (title_w < subtitle_w) ? title_w : subtitle_w;            } else {                width += title_w;            }             height = Math.max(fm.getHeight() + 2, height);             width += titleSpacing + titleSpacing;             Insets insets = getInsets();            height += insets.top + insets.bottom;            width += insets.left + insets.right;            context.dispose();            return new Dimension(width, height);        }         private int center(Component c, Insets insets, int x,                           boolean trailing) {            Dimension pref = c.getPreferredSize();            if (trailing) {                x -= pref.width;            }            c.setBounds(x, insets.top +                        (getHeight() - insets.top - insets.bottom -                         pref.height) / 2, pref.width, pref.height);            if (pref.width > 0) {                if (trailing) {                    return x - buttonSpacing;                }                return x + pref.width + buttonSpacing;            }            return x;        }         public void layoutContainer(Container c) {            Insets insets = c.getInsets();            Dimension pref;             if (SynthLookAndFeel.isLeftToRight(frame)) {                center(menuButton, insets, insets.left, false);                int x = getWidth() - insets.right;                if (frame.isClosable()) {                    x = center(closeButton, insets, x, true);                }                if (frame.isMaximizable()) {                    x = center(maxButton, insets, x, true);                }                if (frame.isIconifiable()) {                    x = center(iconButton, insets, x, true);                }            }            else {                center(menuButton, insets, getWidth() - insets.right,                       true);                int x = insets.left;                if (frame.isClosable()) {                    x = center(closeButton, insets, x, false);                }                if (frame.isMaximizable()) {                    x = center(maxButton, insets, x, false);                }                if (frame.isIconifiable()) {                    x = center(iconButton, insets, x, false);                }            }        }    }     private JButton createNoFocusButton() {        JButton button = new JButton();        button.setFocusable(false);        button.setMargin(new Insets(0,0,0,0));        return button;    }}