0N/A/*
2362N/A * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.swing.plaf.metal;
0N/A
0N/Aimport sun.swing.SwingUtilities2;
0N/Aimport java.awt.*;
0N/Aimport java.awt.event.*;
0N/Aimport javax.swing.*;
0N/Aimport javax.swing.border.*;
0N/Aimport javax.swing.event.InternalFrameEvent;
0N/Aimport java.util.EventListener;
0N/Aimport java.beans.PropertyChangeListener;
0N/Aimport java.beans.PropertyChangeEvent;
0N/Aimport javax.swing.plaf.basic.BasicInternalFrameTitlePane;
0N/A
0N/A
0N/A/**
0N/A * Class that manages a JLF title bar
0N/A * @author Steve Wilson
0N/A * @author Brian Beck
0N/A * @since 1.3
0N/A */
0N/A
0N/Apublic class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane {
0N/A
0N/A protected boolean isPalette = false;
0N/A protected Icon paletteCloseIcon;
0N/A protected int paletteTitleHeight;
0N/A
0N/A private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
0N/A
0N/A /**
0N/A * Key used to lookup Color from UIManager. If this is null,
0N/A * <code>getWindowTitleBackground</code> is used.
0N/A */
0N/A private String selectedBackgroundKey;
0N/A /**
0N/A * Key used to lookup Color from UIManager. If this is null,
0N/A * <code>getWindowTitleForeground</code> is used.
0N/A */
0N/A private String selectedForegroundKey;
0N/A /**
0N/A * Key used to lookup shadow color from UIManager. If this is null,
0N/A * <code>getPrimaryControlDarkShadow</code> is used.
0N/A */
0N/A private String selectedShadowKey;
0N/A /**
0N/A * Boolean indicating the state of the <code>JInternalFrame</code>s
0N/A * closable property at <code>updateUI</code> time.
0N/A */
0N/A private boolean wasClosable;
0N/A
0N/A int buttonsWidth = 0;
0N/A
0N/A MetalBumps activeBumps
0N/A = new MetalBumps( 0, 0,
0N/A MetalLookAndFeel.getPrimaryControlHighlight(),
0N/A MetalLookAndFeel.getPrimaryControlDarkShadow(),
0N/A (UIManager.get("InternalFrame.activeTitleGradient") != null) ? null :
0N/A MetalLookAndFeel.getPrimaryControl() );
0N/A MetalBumps inactiveBumps
0N/A = new MetalBumps( 0, 0,
0N/A MetalLookAndFeel.getControlHighlight(),
0N/A MetalLookAndFeel.getControlDarkShadow(),
0N/A (UIManager.get("InternalFrame.inactiveTitleGradient") != null) ? null :
0N/A MetalLookAndFeel.getControl() );
0N/A MetalBumps paletteBumps;
0N/A
0N/A private Color activeBumpsHighlight = MetalLookAndFeel.
0N/A getPrimaryControlHighlight();
0N/A private Color activeBumpsShadow = MetalLookAndFeel.
0N/A getPrimaryControlDarkShadow();
0N/A
0N/A public MetalInternalFrameTitlePane(JInternalFrame f) {
0N/A super( f );
0N/A }
0N/A
0N/A public void addNotify() {
0N/A super.addNotify();
0N/A // This is done here instead of in installDefaults as I was worried
0N/A // that the BasicInternalFrameUI might not be fully initialized, and
0N/A // that if this resets the closable state the BasicInternalFrameUI
0N/A // Listeners that get notified might be in an odd/uninitialized state.
0N/A updateOptionPaneState();
0N/A }
0N/A
0N/A protected void installDefaults() {
0N/A super.installDefaults();
0N/A setFont( UIManager.getFont("InternalFrame.titleFont") );
0N/A paletteTitleHeight
0N/A = UIManager.getInt("InternalFrame.paletteTitleHeight");
0N/A paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon");
0N/A wasClosable = frame.isClosable();
0N/A selectedForegroundKey = selectedBackgroundKey = null;
0N/A if (MetalLookAndFeel.usingOcean()) {
0N/A setOpaque(true);
0N/A }
0N/A }
0N/A
0N/A protected void uninstallDefaults() {
0N/A super.uninstallDefaults();
0N/A if (wasClosable != frame.isClosable()) {
0N/A frame.setClosable(wasClosable);
0N/A }
0N/A }
0N/A
0N/A protected void createButtons() {
0N/A super.createButtons();
0N/A
0N/A Boolean paintActive = frame.isSelected() ? Boolean.TRUE:Boolean.FALSE;
0N/A iconButton.putClientProperty("paintActive", paintActive);
0N/A iconButton.setBorder(handyEmptyBorder);
0N/A
0N/A maxButton.putClientProperty("paintActive", paintActive);
0N/A maxButton.setBorder(handyEmptyBorder);
0N/A
0N/A closeButton.putClientProperty("paintActive", paintActive);
0N/A closeButton.setBorder(handyEmptyBorder);
0N/A
0N/A // The palette close icon isn't opaque while the regular close icon is.
0N/A // This makes sure palette close buttons have the right background.
0N/A closeButton.setBackground(MetalLookAndFeel.getPrimaryControlShadow());
0N/A
0N/A if (MetalLookAndFeel.usingOcean()) {
0N/A iconButton.setContentAreaFilled(false);
0N/A maxButton.setContentAreaFilled(false);
0N/A closeButton.setContentAreaFilled(false);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Override the parent's method to do nothing. Metal frames do not
0N/A * have system menus.
0N/A */
0N/A protected void assembleSystemMenu() {}
0N/A
0N/A /**
0N/A * Override the parent's method to do nothing. Metal frames do not
0N/A * have system menus.
0N/A */
0N/A protected void addSystemMenuItems(JMenu systemMenu) {}
0N/A
0N/A /**
0N/A * Override the parent's method to do nothing. Metal frames do not
0N/A * have system menus.
0N/A */
0N/A protected void showSystemMenu() {}
0N/A
0N/A /**
0N/A * Override the parent's method avoid creating a menu bar. Metal frames
0N/A * do not have system menus.
0N/A */
0N/A protected void addSubComponents() {
0N/A add(iconButton);
0N/A add(maxButton);
0N/A add(closeButton);
0N/A }
0N/A
0N/A protected PropertyChangeListener createPropertyChangeListener() {
0N/A return new MetalPropertyChangeHandler();
0N/A }
0N/A
0N/A protected LayoutManager createLayout() {
0N/A return new MetalTitlePaneLayout();
0N/A }
0N/A
0N/A class MetalPropertyChangeHandler
0N/A extends BasicInternalFrameTitlePane.PropertyChangeHandler
0N/A {
0N/A public void propertyChange(PropertyChangeEvent evt) {
614N/A String prop = evt.getPropertyName();
0N/A if( prop.equals(JInternalFrame.IS_SELECTED_PROPERTY) ) {
0N/A Boolean b = (Boolean)evt.getNewValue();
0N/A iconButton.putClientProperty("paintActive", b);
0N/A closeButton.putClientProperty("paintActive", b);
0N/A maxButton.putClientProperty("paintActive", b);
0N/A }
0N/A else if ("JInternalFrame.messageType".equals(prop)) {
0N/A updateOptionPaneState();
0N/A frame.repaint();
0N/A }
0N/A super.propertyChange(evt);
0N/A }
0N/A }
0N/A
0N/A class MetalTitlePaneLayout extends TitlePaneLayout {
0N/A public void addLayoutComponent(String name, Component c) {}
0N/A public void removeLayoutComponent(Component c) {}
0N/A public Dimension preferredLayoutSize(Container c) {
0N/A return minimumLayoutSize(c);
0N/A }
0N/A
0N/A public Dimension minimumLayoutSize(Container c) {
0N/A // Compute width.
0N/A int width = 30;
0N/A if (frame.isClosable()) {
0N/A width += 21;
0N/A }
0N/A if (frame.isMaximizable()) {
0N/A width += 16 + (frame.isClosable() ? 10 : 4);
0N/A }
0N/A if (frame.isIconifiable()) {
0N/A width += 16 + (frame.isMaximizable() ? 2 :
0N/A (frame.isClosable() ? 10 : 4));
0N/A }
0N/A FontMetrics fm = frame.getFontMetrics(getFont());
0N/A String frameTitle = frame.getTitle();
0N/A int title_w = frameTitle != null ? SwingUtilities2.stringWidth(
0N/A frame, fm, frameTitle) : 0;
0N/A int title_length = frameTitle != null ? frameTitle.length() : 0;
0N/A
0N/A if (title_length > 2) {
0N/A int subtitle_w = SwingUtilities2.stringWidth(frame, fm,
0N/A frame.getTitle().substring(0, 2) + "...");
0N/A width += (title_w < subtitle_w) ? title_w : subtitle_w;
0N/A }
0N/A else {
0N/A width += title_w;
0N/A }
0N/A
0N/A // Compute height.
614N/A int height;
0N/A if (isPalette) {
0N/A height = paletteTitleHeight;
0N/A } else {
0N/A int fontHeight = fm.getHeight();
0N/A fontHeight += 7;
0N/A Icon icon = frame.getFrameIcon();
0N/A int iconHeight = 0;
0N/A if (icon != null) {
0N/A // SystemMenuBar forces the icon to be 16x16 or less.
0N/A iconHeight = Math.min(icon.getIconHeight(), 16);
0N/A }
0N/A iconHeight += 5;
0N/A height = Math.max(fontHeight, iconHeight);
0N/A }
0N/A
0N/A return new Dimension(width, height);
0N/A }
0N/A
0N/A public void layoutContainer(Container c) {
0N/A boolean leftToRight = MetalUtils.isLeftToRight(frame);
0N/A
0N/A int w = getWidth();
0N/A int x = leftToRight ? w : 0;
0N/A int y = 2;
0N/A int spacing;
0N/A
0N/A // assumes all buttons have the same dimensions
0N/A // these dimensions include the borders
0N/A int buttonHeight = closeButton.getIcon().getIconHeight();
0N/A int buttonWidth = closeButton.getIcon().getIconWidth();
0N/A
0N/A if(frame.isClosable()) {
0N/A if (isPalette) {
0N/A spacing = 3;
0N/A x += leftToRight ? -spacing -(buttonWidth+2) : spacing;
0N/A closeButton.setBounds(x, y, buttonWidth+2, getHeight()-4);
0N/A if( !leftToRight ) x += (buttonWidth+2);
0N/A } else {
0N/A spacing = 4;
0N/A x += leftToRight ? -spacing -buttonWidth : spacing;
0N/A closeButton.setBounds(x, y, buttonWidth, buttonHeight);
0N/A if( !leftToRight ) x += buttonWidth;
0N/A }
0N/A }
0N/A
0N/A if(frame.isMaximizable() && !isPalette ) {
0N/A spacing = frame.isClosable() ? 10 : 4;
0N/A x += leftToRight ? -spacing -buttonWidth : spacing;
0N/A maxButton.setBounds(x, y, buttonWidth, buttonHeight);
0N/A if( !leftToRight ) x += buttonWidth;
0N/A }
0N/A
0N/A if(frame.isIconifiable() && !isPalette ) {
0N/A spacing = frame.isMaximizable() ? 2
0N/A : (frame.isClosable() ? 10 : 4);
0N/A x += leftToRight ? -spacing -buttonWidth : spacing;
0N/A iconButton.setBounds(x, y, buttonWidth, buttonHeight);
0N/A if( !leftToRight ) x += buttonWidth;
0N/A }
0N/A
0N/A buttonsWidth = leftToRight ? w - x : x;
0N/A }
0N/A }
0N/A
0N/A public void paintPalette(Graphics g) {
0N/A boolean leftToRight = MetalUtils.isLeftToRight(frame);
0N/A
0N/A int width = getWidth();
0N/A int height = getHeight();
0N/A
0N/A if (paletteBumps == null) {
0N/A paletteBumps
0N/A = new MetalBumps(0, 0,
0N/A MetalLookAndFeel.getPrimaryControlHighlight(),
0N/A MetalLookAndFeel.getPrimaryControlInfo(),
0N/A MetalLookAndFeel.getPrimaryControlShadow() );
0N/A }
0N/A
0N/A Color background = MetalLookAndFeel.getPrimaryControlShadow();
0N/A Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
0N/A
0N/A g.setColor(background);
0N/A g.fillRect(0, 0, width, height);
0N/A
0N/A g.setColor( darkShadow );
0N/A g.drawLine ( 0, height - 1, width, height -1);
0N/A
0N/A int xOffset = leftToRight ? 4 : buttonsWidth + 4;
0N/A int bumpLength = width - buttonsWidth -2*4;
0N/A int bumpHeight = getHeight() - 4;
0N/A paletteBumps.setBumpArea( bumpLength, bumpHeight );
0N/A paletteBumps.paintIcon( this, g, xOffset, 2);
0N/A }
0N/A
0N/A public void paintComponent(Graphics g) {
0N/A if(isPalette) {
0N/A paintPalette(g);
0N/A return;
0N/A }
0N/A
0N/A boolean leftToRight = MetalUtils.isLeftToRight(frame);
0N/A boolean isSelected = frame.isSelected();
0N/A
0N/A int width = getWidth();
0N/A int height = getHeight();
0N/A
0N/A Color background = null;
0N/A Color foreground = null;
0N/A Color shadow = null;
0N/A
0N/A MetalBumps bumps;
0N/A String gradientKey;
0N/A
0N/A if (isSelected) {
0N/A if (!MetalLookAndFeel.usingOcean()) {
0N/A closeButton.setContentAreaFilled(true);
0N/A maxButton.setContentAreaFilled(true);
0N/A iconButton.setContentAreaFilled(true);
0N/A }
0N/A if (selectedBackgroundKey != null) {
0N/A background = UIManager.getColor(selectedBackgroundKey);
0N/A }
0N/A if (background == null) {
0N/A background = MetalLookAndFeel.getWindowTitleBackground();
0N/A }
0N/A if (selectedForegroundKey != null) {
0N/A foreground = UIManager.getColor(selectedForegroundKey);
0N/A }
0N/A if (selectedShadowKey != null) {
0N/A shadow = UIManager.getColor(selectedShadowKey);
0N/A }
0N/A if (shadow == null) {
0N/A shadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
0N/A }
0N/A if (foreground == null) {
0N/A foreground = MetalLookAndFeel.getWindowTitleForeground();
0N/A }
0N/A activeBumps.setBumpColors(activeBumpsHighlight, activeBumpsShadow,
0N/A UIManager.get("InternalFrame.activeTitleGradient") !=
0N/A null ? null : background);
0N/A bumps = activeBumps;
0N/A gradientKey = "InternalFrame.activeTitleGradient";
0N/A } else {
0N/A if (!MetalLookAndFeel.usingOcean()) {
0N/A closeButton.setContentAreaFilled(false);
0N/A maxButton.setContentAreaFilled(false);
0N/A iconButton.setContentAreaFilled(false);
0N/A }
0N/A background = MetalLookAndFeel.getWindowTitleInactiveBackground();
0N/A foreground = MetalLookAndFeel.getWindowTitleInactiveForeground();
0N/A shadow = MetalLookAndFeel.getControlDarkShadow();
0N/A bumps = inactiveBumps;
0N/A gradientKey = "InternalFrame.inactiveTitleGradient";
0N/A }
0N/A
0N/A if (!MetalUtils.drawGradient(this, g, gradientKey, 0, 0, width,
0N/A height, true)) {
0N/A g.setColor(background);
0N/A g.fillRect(0, 0, width, height);
0N/A }
0N/A
0N/A g.setColor( shadow );
0N/A g.drawLine ( 0, height - 1, width, height -1);
0N/A g.drawLine ( 0, 0, 0 ,0);
0N/A g.drawLine ( width - 1, 0 , width -1, 0);
0N/A
0N/A
614N/A int titleLength;
0N/A int xOffset = leftToRight ? 5 : width - 5;
0N/A String frameTitle = frame.getTitle();
0N/A
0N/A Icon icon = frame.getFrameIcon();
0N/A if ( icon != null ) {
0N/A if( !leftToRight )
0N/A xOffset -= icon.getIconWidth();
0N/A int iconY = ((height / 2) - (icon.getIconHeight() /2));
0N/A icon.paintIcon(frame, g, xOffset, iconY);
0N/A xOffset += leftToRight ? icon.getIconWidth() + 5 : -5;
0N/A }
0N/A
0N/A if(frameTitle != null) {
0N/A Font f = getFont();
0N/A g.setFont(f);
0N/A FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g, f);
0N/A int fHeight = fm.getHeight();
0N/A
0N/A g.setColor(foreground);
0N/A
0N/A int yOffset = ( (height - fm.getHeight() ) / 2 ) + fm.getAscent();
0N/A
0N/A Rectangle rect = new Rectangle(0, 0, 0, 0);
0N/A if (frame.isIconifiable()) { rect = iconButton.getBounds(); }
0N/A else if (frame.isMaximizable()) { rect = maxButton.getBounds(); }
0N/A else if (frame.isClosable()) { rect = closeButton.getBounds(); }
0N/A int titleW;
0N/A
0N/A if( leftToRight ) {
0N/A if (rect.x == 0) {
0N/A rect.x = frame.getWidth()-frame.getInsets().right-2;
0N/A }
0N/A titleW = rect.x - xOffset - 4;
0N/A frameTitle = getTitle(frameTitle, fm, titleW);
0N/A } else {
0N/A titleW = xOffset - rect.x - rect.width - 4;
0N/A frameTitle = getTitle(frameTitle, fm, titleW);
0N/A xOffset -= SwingUtilities2.stringWidth(frame, fm, frameTitle);
0N/A }
0N/A
0N/A titleLength = SwingUtilities2.stringWidth(frame, fm, frameTitle);
0N/A SwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset);
0N/A xOffset += leftToRight ? titleLength + 5 : -5;
0N/A }
0N/A
0N/A int bumpXOffset;
0N/A int bumpLength;
0N/A if( leftToRight ) {
0N/A bumpLength = width - buttonsWidth - xOffset - 5;
0N/A bumpXOffset = xOffset;
0N/A } else {
0N/A bumpLength = xOffset - buttonsWidth - 5;
0N/A bumpXOffset = buttonsWidth + 5;
0N/A }
0N/A int bumpYOffset = 3;
0N/A int bumpHeight = getHeight() - (2 * bumpYOffset);
0N/A bumps.setBumpArea( bumpLength, bumpHeight );
0N/A bumps.paintIcon(this, g, bumpXOffset, bumpYOffset);
0N/A }
0N/A
0N/A public void setPalette(boolean b) {
0N/A isPalette = b;
0N/A
0N/A if (isPalette) {
0N/A closeButton.setIcon(paletteCloseIcon);
0N/A if( frame.isMaximizable() )
0N/A remove(maxButton);
0N/A if( frame.isIconifiable() )
0N/A remove(iconButton);
0N/A } else {
0N/A closeButton.setIcon(closeIcon);
0N/A if( frame.isMaximizable() )
0N/A add(maxButton);
0N/A if( frame.isIconifiable() )
0N/A add(iconButton);
0N/A }
0N/A revalidate();
0N/A repaint();
0N/A }
0N/A
0N/A /**
0N/A * Updates any state dependant upon the JInternalFrame being shown in
0N/A * a <code>JOptionPane</code>.
0N/A */
0N/A private void updateOptionPaneState() {
0N/A int type = -2;
0N/A boolean closable = wasClosable;
0N/A Object obj = frame.getClientProperty("JInternalFrame.messageType");
0N/A
0N/A if (obj == null) {
0N/A // Don't change the closable state unless in an JOptionPane.
0N/A return;
0N/A }
0N/A if (obj instanceof Integer) {
0N/A type = ((Integer) obj).intValue();
0N/A }
0N/A switch (type) {
0N/A case JOptionPane.ERROR_MESSAGE:
0N/A selectedBackgroundKey =
0N/A "OptionPane.errorDialog.titlePane.background";
0N/A selectedForegroundKey =
0N/A "OptionPane.errorDialog.titlePane.foreground";
0N/A selectedShadowKey = "OptionPane.errorDialog.titlePane.shadow";
0N/A closable = false;
0N/A break;
0N/A case JOptionPane.QUESTION_MESSAGE:
0N/A selectedBackgroundKey =
0N/A "OptionPane.questionDialog.titlePane.background";
0N/A selectedForegroundKey =
0N/A "OptionPane.questionDialog.titlePane.foreground";
0N/A selectedShadowKey =
0N/A "OptionPane.questionDialog.titlePane.shadow";
0N/A closable = false;
0N/A break;
0N/A case JOptionPane.WARNING_MESSAGE:
0N/A selectedBackgroundKey =
0N/A "OptionPane.warningDialog.titlePane.background";
0N/A selectedForegroundKey =
0N/A "OptionPane.warningDialog.titlePane.foreground";
0N/A selectedShadowKey = "OptionPane.warningDialog.titlePane.shadow";
0N/A closable = false;
0N/A break;
0N/A case JOptionPane.INFORMATION_MESSAGE:
0N/A case JOptionPane.PLAIN_MESSAGE:
0N/A selectedBackgroundKey = selectedForegroundKey = selectedShadowKey =
0N/A null;
0N/A closable = false;
0N/A break;
0N/A default:
0N/A selectedBackgroundKey = selectedForegroundKey = selectedShadowKey =
0N/A null;
0N/A break;
0N/A }
0N/A if (closable != frame.isClosable()) {
0N/A frame.setClosable(closable);
0N/A }
0N/A }
0N/A}