titlepane.java

来自「用于java swing的皮肤软件」· Java 代码 · 共 1,126 行 · 第 1/2 页

JAVA
1,126 行
字号
package com.digitprop.tonic;


import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import java.util.Locale;


/**	Manages the Look and Feel of a window title bar.
 * 
 * 	@author	Markus Fischer
 *
 *  	<p>This software is under the <a href="http://www.gnu.org/copyleft/lesser.html" target="_blank">GNU Lesser General Public License</a>
 */

/*
 * ------------------------------------------------------------------------
 * Copyright (C) 2004 Markus Fischer
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free 
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 * MA 02111-1307  USA
 * 
 * You can contact the author at:
 *    Markus Fischer
 *    www.digitprop.com
 *    info@digitprop.com
 * ------------------------------------------------------------------------
 */
class TitlePane extends JComponent
{
	private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0);
	
	private static final int IMAGE_HEIGHT = 16;
	
	private static final int IMAGE_WIDTH = 16;
	

	/** 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;

	/** 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;

	/** Icon used for toggleButton when window is normal size. */
	private Icon maximizeIcon;

	/** Icon used for toggleButton when window is maximized. */
	private Icon minimizeIcon;

	/** Listens for changes in the state of the Window listener to 
	 *  update the state of the widgets.
	 */
	private WindowListener windowListener;

	/** Window we're currently in. */
	private Window window;

	/** JRootPane rendering for. */
	private JRootPane rootPane;

	/** Room remaining in title for bumps. */
	private int buttonsWidth;

	/** Buffered Frame.state property. As state isn't bound, this is 
	 *  kept to determine when to avoid updating widgets.
	 */
	private int state;

	/** The RootPaneUI instance that created us. */
	private RootPaneUI rootPaneUI;

	// Colors
	private Color inactiveBackground=UIManager.getColor("inactiveCaption");
	private Color inactiveForeground=UIManager.getColor("inactiveCaptionText");
	private Color inactiveShadow = UIManager.getColor("inactiveCaptionBorder");
	private Color activeBumpsHighlight=TonicLookAndFeel.getPrimaryControlHighlight();
	private Color activeBumpsShadow=TonicLookAndFeel.getPrimaryControlDarkShadow();
	private Color activeBackground=null;
	private Color activeForeground=null;
	private Color activeShadow=null;


	public TitlePane(JRootPane root, RootPaneUI ui)
	{
		this.rootPane = root;
		rootPaneUI = ui;

		state = -1;

		installSubcomponents();
		determineColors();
		installDefaults();

		setLayout(createLayout());
	}

	/**
	 * Uninstalls the necessary state.
	 */
	private void uninstall()
	{
		uninstallListeners();
		window = null;
		removeAll();
	}

	/**
	 * Installs the necessary listeners.
	 */
	private void installListeners()
	{
		if (window != null)
		{
			windowListener = createWindowListener();
			window.addWindowListener(windowListener);
			propertyChangeListener = createWindowPropertyChangeListener();
			window.addPropertyChangeListener(propertyChangeListener);
		}
	}

	/**
	 * Uninstalls the necessary listeners.
	 */
	private void uninstallListeners()
	{
		if (window != null)
		{
			window.removeWindowListener(windowListener);
			window.removePropertyChangeListener(propertyChangeListener);
		}
	}

	/**
	 * 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;
	}

	/**
	 * 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>MetalTitlePane</code>.
	 */
	private void installSubcomponents()
	{
		if (getWindowDecorationStyle() == JRootPane.FRAME)
		{
			createActions();
			menuBar = createMenuBar();
			add(menuBar);
			createButtons();
			add(iconifyButton);
			add(toggleButton);
			add(closeButton);
		}
	}

	/**
	 * Determines the Colors to draw with.
	 */
	private void determineColors()
	{
		switch (getWindowDecorationStyle())
		{
			case JRootPane.FRAME :
				activeBackground = UIManager.getColor("activeCaption");
				activeForeground = UIManager.getColor("activeCaptionText");
				activeShadow = UIManager.getColor("activeCaptionBorder");
				break;
				
			case JRootPane.ERROR_DIALOG :
				activeBackground =
					UIManager.getColor(
						"OptionPane.errorDialog.titlePane.background");
				activeForeground =
					UIManager.getColor(
						"OptionPane.errorDialog.titlePane.foreground");
				activeShadow =
					UIManager.getColor(
						"OptionPane.errorDialog.titlePane.shadow");
				break;
				
			case JRootPane.QUESTION_DIALOG :
			case JRootPane.COLOR_CHOOSER_DIALOG :
			case JRootPane.FILE_CHOOSER_DIALOG :
				activeBackground =
					UIManager.getColor(
						"OptionPane.questionDialog.titlePane.background");
				activeForeground =
					UIManager.getColor(
						"OptionPane.questionDialog.titlePane.foreground");
				activeShadow =
					UIManager.getColor(
						"OptionPane.questionDialog.titlePane.shadow");
				break;
				
			case JRootPane.WARNING_DIALOG :
				activeBackground =
					UIManager.getColor(
						"OptionPane.warningDialog.titlePane.background");
				activeForeground =
					UIManager.getColor(
						"OptionPane.warningDialog.titlePane.foreground");
				activeShadow =
					UIManager.getColor(
						"OptionPane.warningDialog.titlePane.shadow");
				break;
				
			case JRootPane.PLAIN_DIALOG :
			case JRootPane.INFORMATION_DIALOG :
			default :
				activeBackground = UIManager.getColor("activeCaption");
				activeForeground = UIManager.getColor("activeCaptionText");
				activeShadow = UIManager.getColor("activeCaptionBorder");
				break;
		}
	}

	/**
	 * Installs the fonts and necessary properties on the MetalTitlePane.
	 */
	private void installDefaults()
	{
		setFont(UIManager.getFont("InternalFrame.titleFont", getLocale()));
	}

	/**
	 * Uninstalls any previously installed UI values.
	 */
	private void uninstallDefaults()
	{
	}

	/**
	 * Returns the <code>JMenuBar</code> displaying the appropriate system
	 * menu items.
	 */
	protected JMenuBar createMenuBar()
	{
		menuBar = new SystemMenuBar();
		menuBar.setOpaque(false);
		menuBar.setFocusable(false);
		menuBar.setBorderPainted(true);
		menuBar.add(createMenu());
		return menuBar;
	}

	/**
	 * Closes the Window.
	 */
	private void close()
	{
		Window window = getWindow();

		if (window != null)
		{
			window.dispatchEvent(
				new WindowEvent(window, WindowEvent.WINDOW_CLOSING));
		}
	}

	/**
	 * Iconifies the Frame.
	 */
	private void iconify()
	{
		Frame frame = getFrame();
		if (frame != null)
		{
			frame.setExtendedState(state | Frame.ICONIFIED);
		}
	}

	/**
	 * Maximizes the Frame.
	 */
	private void maximize()
	{
		Frame frame = getFrame();
		if (frame != null)
		{
			frame.setExtendedState(state | Frame.MAXIMIZED_BOTH);
		}
	}

	/**
	 * Restores the Frame size.
	 */
	private void restore()
	{
		Frame frame = getFrame();

		if (frame == null)
		{
			return;
		}

		if ((state & Frame.ICONIFIED) != 0)
		{
			frame.setExtendedState(state & ~Frame.ICONIFIED);
		}
		else
		{
			frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
		}
	}

	/**
	 * 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();
	}

	/**
	 * Returns the <code>JMenu</code> displaying the appropriate menu items
	 * for manipulating the Frame.
	 */
	private JMenu createMenu()
	{
		JMenu menu = new JMenu("");
		if (getWindowDecorationStyle() == JRootPane.FRAME)
		{
			addMenuItems(menu);
		}
		return menu;
	}

	/**
	 * Adds the necessary <code>JMenuItem</code> s to the passed in menu.
	 */
	private void addMenuItems(JMenu menu)
	{
		Locale locale = getRootPane().getLocale();
		JMenuItem mi = menu.add(restoreAction);
		int mnemonic = TonicUtils.getInt("MetalTitlePane.restoreMnemonic", -1);

		if (mnemonic != -1)
		{
			mi.setMnemonic(mnemonic);
		}

		mi = menu.add(iconifyAction);
		mnemonic = TonicUtils.getInt("MetalTitlePane.iconifyMnemonic", -1);
		if (mnemonic != -1)
		{
			mi.setMnemonic(mnemonic);
		}

		if (Toolkit
			.getDefaultToolkit()
			.isFrameStateSupported(Frame.MAXIMIZED_BOTH))
		{
			mi = menu.add(maximizeAction);
			mnemonic = TonicUtils.getInt("MetalTitlePane.maximizeMnemonic", -1);
			if (mnemonic != -1)
			{
				mi.setMnemonic(mnemonic);
			}
		}

		menu.add(new JSeparator());

		mi = menu.add(closeAction);
		mnemonic = TonicUtils.getInt("MetalTitlePane.closeMnemonic", -1);
		if (mnemonic != -1)
		{
			mi.setMnemonic(mnemonic);
		}
	}

	/**
	 * Returns a <code>JButton</code> appropriate for placement on the
	 * TitlePane.
	 */
	private JButton createTitleButton()
	{
		JButton button = new JButton();

		button.setFocusPainted(false);
		button.setFocusable(false);
		button.setOpaque(false);
		return button;
	}

	/**
	 * Creates the Buttons that will be placed on the TitlePane.
	 */
	private void createButtons()
	{
		maximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
		minimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon");

		closeButton = createTitleButton();
		closeButton.setAction(closeAction);
		closeButton.setText(null);
		closeButton.putClientProperty("paintActive", Boolean.TRUE);
		closeButton.setBorder(handyEmptyBorder);
		closeButton.getAccessibleContext().setAccessibleName("Close");
		closeButton.setIcon(UIManager.getIcon("InternalFrame.closeIcon"));
		closeButton.setBackground(Color.WHITE);

		iconifyButton = createTitleButton();
		iconifyButton.setAction(iconifyAction);
		iconifyButton.setText(null);
		iconifyButton.putClientProperty("paintActive", Boolean.TRUE);
		iconifyButton.setBorder(handyEmptyBorder);
		iconifyButton.getAccessibleContext().setAccessibleName("Iconify");
		iconifyButton.setIcon(UIManager.getIcon("InternalFrame.iconifyIcon"));
		iconifyButton.setBackground(Color.WHITE);

		toggleButton = createTitleButton();
		toggleButton.setAction(restoreAction);
		toggleButton.putClientProperty("paintActive", Boolean.TRUE);
		toggleButton.setBorder(handyEmptyBorder);
		toggleButton.getAccessibleContext().setAccessibleName("Maximize");
		toggleButton.setIcon(maximizeIcon);
		toggleButton.setBackground(Color.WHITE);
	}

	/**
	 * Returns the <code>LayoutManager</code> that should be installed on the
	 * <code>MetalTitlePane</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);
		}
		// 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)
		{
			if (this.state == state && !updateRegardless)
			{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?