⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rootpaneui.java

📁 用于java swing的皮肤软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.digitprop.tonic;


import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import java.awt.*;


/**
 * Slight modification of the UI delegate for root panes.
 * 
 * @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
 * ------------------------------------------------------------------------
 */
public class RootPaneUI extends BasicRootPaneUI
{
	/**
	 * Keys to lookup borders in defaults table.
	 */
	private static final String[]	borderKeys					= new String[]
																			{
				null, "RootPane.frameBorder", "RootPane.plainDialogBorder",
				"RootPane.informationDialogBorder", "RootPane.errorDialogBorder",
				"RootPane.colorChooserDialogBorder", "RootPane.fileChooserDialogBorder",
				"RootPane.questionDialogBorder", "RootPane.warningDialogBorder"
																			};

	/**
	 * The amount of space (in pixels) that the cursor is changed on.
	 */
	private static final int		CORNER_DRAG_WIDTH			= 16;

	/**
	 * Region from edges that dragging is active from.
	 */
	private static final int		BORDER_DRAG_THICKNESS	= 5;

	/**
	 * Window the <code>JRootPane</code> is in.
	 */
	private Window						window;

	/**
	 * <code>JComponent</code> providing window decorations. This will be null
	 * if not providing window decorations.
	 */
	private JComponent				titlePane;

	/**
	 * <code>MouseInputListener</code> that is added to the parent
	 * <code>Window</code> the <code>JRootPane</code> is contained in.
	 */
	private MouseInputListener		mouseInputListener;

	/**
	 * The <code>LayoutManager</code> that is set on the <code>JRootPane</code>.
	 */
	private LayoutManager			layoutManager;

	/**
	 * <code>LayoutManager</code> of the <code>JRootPane</code> before we
	 * replaced it.
	 */
	private LayoutManager			savedOldLayout;

	/**
	 * <code>JRootPane</code> providing the look and feel for.
	 */
	private JRootPane					root;

	/**
	 * <code>Cursor</code> used to track the cursor set by the user. This is
	 * initially <code>Cursor.DEFAULT_CURSOR</code>.
	 */
	private Cursor						lastCursor					= Cursor
																						.getPredefinedCursor(Cursor.DEFAULT_CURSOR);



	/**
	 * Creates a UI for a <code>JRootPane</code>.
	 * 
	 * @param c the JRootPane the RootPaneUI will be created for
	 * @return the RootPaneUI implementation for the passed in JRootPane
	 */
	public static ComponentUI createUI(JComponent c)
	{
		return new RootPaneUI();
	}


	/**
	 * Invokes supers implementation of <code>installUI</code> to install the
	 * necessary state onto the passed in <code>JRootPane</code> to render the
	 * metal look and feel implementation of <code>RootPaneUI</code>. If the
	 * <code>windowDecorationStyle</code> property of the
	 * <code>JRootPane</code> is other than <code>JRootPane.NONE</code>,
	 * this will add a custom <code>Component</code> to render the widgets to
	 * <code>JRootPane</code>, as well as installing a custom
	 * <code>Border</code> and <code>LayoutManager</code> on the
	 * <code>JRootPane</code>.
	 * 
	 * @param c the JRootPane to install state onto
	 */
	public void installUI(JComponent c)
	{
		super.installUI(c);
		root = (JRootPane) c;
		int style = root.getWindowDecorationStyle();
		if (style != JRootPane.NONE)
		{
			installClientDecorations(root);
		}
	}


	/**
	 * Invokes supers implementation to uninstall any of its state. This will
	 * also reset the <code>LayoutManager</code> of the <code>JRootPane</code>.
	 * If a <code>Component</code> has been added to the <code>JRootPane</code>
	 * to render the window decoration style, this method will remove it.
	 * Similarly, this will revert the Border and LayoutManager of the
	 * <code>JRootPane</code> to what it was before <code>installUI</code>
	 * was invoked.
	 * 
	 * @param c the JRootPane to uninstall state from
	 */
	public void uninstallUI(JComponent c)
	{
		super.uninstallUI(c);
		uninstallClientDecorations(root);

		layoutManager = null;
		mouseInputListener = null;
		root = null;
	}


	/**
	 * Installs the appropriate <code>Border</code> onto the
	 * <code>JRootPane</code>.
	 */
	void installBorder(JRootPane root)
	{
		int style = root.getWindowDecorationStyle();

		if (style == JRootPane.NONE)
		{
			LookAndFeel.uninstallBorder(root);
		}
		else
		{
			LookAndFeel.installBorder(root, borderKeys[style]);
		}
	}


	/**
	 * Removes any border that may have been installed.
	 */
	private void uninstallBorder(JRootPane root)
	{
		LookAndFeel.uninstallBorder(root);
	}


	/**
	 * Installs the necessary Listeners on the parent <code>Window</code>, if
	 * there is one.
	 * <p>
	 * This takes the parent so that cleanup can be done from
	 * <code>removeNotify</code>, at which point the parent hasn't been reset
	 * yet.
	 * 
	 * @param parent The parent of the JRootPane
	 */
	private void installWindowListeners(JRootPane root, Component parent)
	{
		if (parent instanceof Window)
		{
			window = (Window) parent;
		}
		else
		{
			window = SwingUtilities.getWindowAncestor(parent);
		}
		if (window != null)
		{
			if (mouseInputListener == null)
			{
				mouseInputListener = createWindowMouseInputListener(root);
			}
			window.addMouseListener(mouseInputListener);
			window.addMouseMotionListener(mouseInputListener);
		}
	}


	/**
	 * Uninstalls the necessary Listeners on the <code>Window</code> the
	 * Listeners were last installed on.
	 */
	private void uninstallWindowListeners(JRootPane root)
	{
		if (window != null)
		{
			window.removeMouseListener(mouseInputListener);
			window.removeMouseMotionListener(mouseInputListener);
		}
	}


	/**
	 * Installs the appropriate LayoutManager on the <code>JRootPane</code> to
	 * render the window decorations.
	 */
	private void installLayout(JRootPane root)
	{
		if (layoutManager == null)
		{
			layoutManager = createLayoutManager();
		}
		savedOldLayout = root.getLayout();
		root.setLayout(layoutManager);
	}


	/**
	 * Uninstalls the previously installed <code>LayoutManager</code>.
	 */
	private void uninstallLayout(JRootPane root)
	{
		if (savedOldLayout != null)
		{
			root.setLayout(savedOldLayout);
			savedOldLayout = null;
		}
	}


	/**
	 * Installs the necessary state onto the JRootPane to render client
	 * decorations. This is ONLY invoked if the <code>JRootPane</code> has a
	 * decoration style other than <code>JRootPane.NONE</code>.
	 */
	private void installClientDecorations(JRootPane root)
	{
		installBorder(root);

		JComponent titlePane = createTitlePane(root);

		setTitlePane(root, titlePane);
		installWindowListeners(root, root.getParent());
		installLayout(root);
		if (window != null)
		{
			root.revalidate();
			root.repaint();
		}
	}


	/**
	 * Uninstalls any state that <code>installClientDecorations</code> has
	 * installed.
	 * <p>
	 * NOTE: This may be called if you haven't installed client decorations yet
	 * (ie before <code>installClientDecorations</code> has been invoked).
	 */
	private void uninstallClientDecorations(JRootPane root)
	{
		uninstallBorder(root);
		uninstallWindowListeners(root);
		setTitlePane(root, null);
		uninstallLayout(root);
		// We have to revalidate/repaint root if the style is JRootPane.NONE
		// only. When we needs to call revalidate/repaint with other styles
		// the installClientDecorations is always called after this method
		// imediatly and it will cause the revalidate/repaint at the proper
		// time.
		int style = root.getWindowDecorationStyle();
		if (style == JRootPane.NONE)
		{
			root.repaint();
			root.revalidate();
		}
		// Reset the cursor, as we may have changed it to a resize cursor
		if (window != null)
		{
			window.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		}
		window = null;
	}


	/**
	 * Returns the <code>JComponent</code> to render the window decoration
	 * style.
	 */
	private JComponent createTitlePane(JRootPane root)
	{
		return new TitlePane(root, this);
	}


	/**
	 * Returns a <code>MouseListener</code> that will be added to the
	 * <code>Window</code> containing the <code>JRootPane</code>.
	 */
	private MouseInputListener createWindowMouseInputListener(JRootPane root)
	{
		return new MouseInputHandler();
	}


	/**
	 * Returns a <code>LayoutManager</code> that will be set on the
	 * <code>JRootPane</code>.
	 */
	private LayoutManager createLayoutManager()
	{
		return new MetalRootLayout();
	}


	/**
	 * Sets the window title pane -- the JComponent used to provide a plaf a way
	 * to override the native operating system's window title pane with one whose
	 * look and feel are controlled by the plaf. The plaf creates and sets this
	 * value; the default is null, implying a native operating system window
	 * title pane.
	 * 
	 * @param content the <code>JComponent</code> to use for the window title
	 *           pane.
	 */
	private void setTitlePane(JRootPane root, JComponent titlePane)
	{
		JLayeredPane layeredPane = root.getLayeredPane();
		JComponent oldTitlePane = getTitlePane();

		if (oldTitlePane != null)
		{
			oldTitlePane.setVisible(false);
			layeredPane.remove(oldTitlePane);
		}
		if (titlePane != null)
		{
			layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER);
			titlePane.setVisible(true);
		}
		this.titlePane = titlePane;
	}


	/**
	 * Returns the <code>JComponent</code> rendering the title pane. If this
	 * returns null, it implies there is no need to render window decorations.
	 * 
	 * @return the current window title pane, or null
	 * @see #setTitlePane
	 */
	private JComponent getTitlePane()
	{
		return titlePane;
	}


	/**
	 * Returns the <code>JRootPane</code> we're providing the look and feel
	 * for.
	 */
	private JRootPane getRootPane()
	{
		return root;
	}


	/**
	 * Invoked when a property changes. <code>MetalRootPaneUI</code> is
	 * primarily interested in events originating from the <code>JRootPane</code>
	 * it has been installed on identifying the property
	 * <code>windowDecorationStyle</code>. If the
	 * <code>windowDecorationStyle</code> has changed to a value other than
	 * <code>JRootPane.NONE</code>, this will add a <code>Component</code>
	 * to the <code>JRootPane</code> to render the window decorations, as well
	 * as installing a <code>Border</code> on the <code>JRootPane</code>. On
	 * the other hand, if the <code>windowDecorationStyle</code> has changed to
	 * <code>JRootPane.NONE</code>, this will remove the
	 * <code>Component</code> that has been added to the <code>JRootPane</code>
	 * as well resetting the Border to what it was before <code>installUI</code>
	 * was invoked.
	 * 
	 * @param e A PropertyChangeEvent object describing the event source and the
	 *           property that has changed.
	 */
	public void propertyChange(PropertyChangeEvent e)
	{
		super.propertyChange(e);

		String propertyName = e.getPropertyName();
		if (propertyName == null)
		{
			return;
		}

		if (propertyName.equals("windowDecorationStyle"))
		{
			JRootPane root = (JRootPane) e.getSource();
			int style = root.getWindowDecorationStyle();

			// This is potentially more than needs to be done,
			// but it rarely happens and makes the install/uninstall process
			// simpler. MetalTitlePane also assumes it will be recreated if
			// the decoration style changes.
			uninstallClientDecorations(root);
			if (style != JRootPane.NONE)
			{
				installClientDecorations(root);
			}
		}
		else if (propertyName.equals("ancestor"))
		{
			uninstallWindowListeners(root);
			if (((JRootPane) e.getSource()).getWindowDecorationStyle() != JRootPane.NONE)
			{
				installWindowListeners(root, root.getParent());
			}
		}
		return;
	}

	/**
	 * A custom layout manager that is responsible for the layout of layeredPane,
	 * glassPane, menuBar and titlePane, if one has been installed.
	 */
	// NOTE: Ideally this would extends JRootPane.RootLayout, but that
	//       would force this to be non-static.
	private static class MetalRootLayout implements LayoutManager2
	{
		/**
		 * Returns the amount of space the layout would like to have.
		 * 
		 * @param the Container for which this layout manager is being used
		 * @return a Dimension object containing the layout's preferred size
		 */
		public Dimension preferredLayoutSize(Container parent)
		{
			Dimension cpd, mbd, tpd;
			int cpWidth = 0;
			int cpHeight = 0;
			int mbWidth = 0;
			int mbHeight = 0;
			int tpWidth = 0;
			int tpHeight = 0;
			Insets i = parent.getInsets();
			JRootPane root = (JRootPane) parent;

			if (root.getContentPane() != null)
			{
				cpd = root.getContentPane().getPreferredSize();
			}
			else
			{
				cpd = root.getSize();
			}
			if (cpd != null)
			{
				cpWidth = cpd.width;
				cpHeight = cpd.height;
			}

			if (root.getMenuBar() != null)
			{
				mbd = root.getMenuBar().getPreferredSize();
				if (mbd != null)
				{
					mbWidth = mbd.width;
					mbHeight = mbd.height;
				}
			}

			if (root.getWindowDecorationStyle() != JRootPane.NONE
						&& (root.getUI() instanceof RootPaneUI))
			{
				JComponent titlePane = ((RootPaneUI) root.getUI()).getTitlePane();
				if (titlePane != null)
				{
					tpd = titlePane.getPreferredSize();
					if (tpd != null)
					{
						tpWidth = tpd.width;
						tpHeight = tpd.height;
					}
				}
			}

			return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right,
						cpHeight + mbHeight + tpWidth + i.top + i.bottom);
		}


		/**
		 * Returns the minimum amount of space the layout needs.
		 * 
		 * @param the Container for which this layout manager is being used
		 * @return a Dimension object containing the layout's minimum size
		 */
		public Dimension minimumLayoutSize(Container parent)
		{
			Dimension cpd, mbd, tpd;
			int cpWidth = 0;
			int cpHeight = 0;
			int mbWidth = 0;
			int mbHeight = 0;
			int tpWidth = 0;
			int tpHeight = 0;
			Insets i = parent.getInsets();
			JRootPane root = (JRootPane) parent;

			if (root.getContentPane() != null)
			{
				cpd = root.getContentPane().getMinimumSize();
			}
			else
			{
				cpd = root.getSize();
			}
			if (cpd != null)
			{
				cpWidth = cpd.width;
				cpHeight = cpd.height;
			}

			if (root.getMenuBar() != null)
			{
				mbd = root.getMenuBar().getMinimumSize();
				if (mbd != null)
				{
					mbWidth = mbd.width;
					mbHeight = mbd.height;

⌨️ 快捷键说明

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