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

📄 comboboxui.java

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

import java.awt.*;
import java.awt.event.*;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.accessibility.*;
import javax.swing.plaf.*;
import javax.swing.event.*;

import sun.awt.AppContext;


/**	UI delegate for combo boxes.
 * 
 * 	@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 ComboBoxUI extends javax.swing.plaf.metal.MetalComboBoxUI/*Basic*/
{
	/**	If true, the combo box is used in the JTable DefaultCellEditor */
	private boolean 					isTableCellEditor= false;
	
	/**	Helper string */
	private static final String 	IS_TABLE_CELL_EDITOR="JComboBox.isTableCellEditor";

	/**	The focus listener */
	FocusListener 							editorFocusListener;

	/**	Flag for calculating the display size */
	private boolean 					isDisplaySizeDirty = true;
	
	/**	This is used for knowing when to cache the minimum preferred size.
	 * 	If the data in the list changes, the cached value get marked for recalc.
	 * 	Added to the current JComboBox model.<p>
	 * 
	 * 	Cached the size that the display needs to render the largest item
	 */
	private Dimension 					cachedDisplaySize= new Dimension(0, 0);

	/**	Key used for lookup of the DefaultListCellRenderer in the AppContext. */
	private static final Object 	COMBO_UI_LIST_CELL_RENDERER_KEY=
		new StringBuffer("DefaultListCellRendererKey");

	
	/**	Returns the default ListCellRenderer */
	private static ListCellRenderer getDefaultListCellRenderer()
	{
		ListCellRenderer renderer=
			(ListCellRenderer) AppContext.getAppContext().get(
				COMBO_UI_LIST_CELL_RENDERER_KEY);

		if (renderer == null)
		{
			renderer= new DefaultListCellRenderer();
			AppContext.getAppContext().put(
				COMBO_UI_LIST_CELL_RENDERER_KEY,
				new DefaultListCellRenderer());
		}
		return renderer;
	}
	

	/**	Creates and returns the UI delegate for the specified component */ 
	public static ComponentUI createUI(JComponent c)
	{
		return new ComboBoxUI();
	}
	
	
	/**	Installs an UI delegate for the specified component */
	public void installUI(JComponent c)
	{
		isMinimumSizeDirty= true;

		comboBox= (JComboBox) c;
		installDefaults();
		popup= createPopup();
		listBox= popup.getList();

		// Is this combo box a cell editor?
		Boolean inTable= (Boolean) c.getClientProperty(IS_TABLE_CELL_EDITOR);
		if (inTable != null)
		{
			isTableCellEditor= inTable.equals(Boolean.TRUE) ? true : false;
		}

		if (comboBox.getRenderer() == null
			|| comboBox.getRenderer() instanceof UIResource)
		{
			comboBox.setRenderer(createRenderer());
		}

		if (comboBox.getEditor() == null
			|| comboBox.getEditor() instanceof UIResource)
		{
			comboBox.setEditor(createEditor());
		}

		installListeners();
		installComponents();

		comboBox.setLayout(createLayoutManager());

		comboBox.setRequestFocusEnabled(true);

		installKeyboardActions();

		/* 4353597: XXX - remove this hack but keep it here for some more testing. This block
		 * should be removed before FCS.
			  // An invokeLater() was used here because updateComponentTree() resets
			  // our sub-components after this method is completed.  By delaying, we
			  // can set what we need after updateComponentTree() has set all of the
			  // values to defaults.
			  Runnable initializer = new Runnable() {
					public void run(){
						 // This test for comboBox being null is required because it's possible for the UI
						 // to become uninstalled before this block of code is executed.
						 if ( comboBox != null ) {
							  if ( editor != null ) {
									editor.setFont( comboBox.getFont() );
							  }
							  installKeyboardActions();
						 }
					}
			  };
			  SwingUtilities.invokeLater( initializer ); */
	}


	/**	Uninstalls the UI delegate for the specified component */
	public void uninstallUI(JComponent c)
	{
		setPopupVisible(comboBox, false);
		popup.uninstallingUI();

		uninstallKeyboardActions();

		comboBox.setLayout(null);

		uninstallComponents();
		uninstallListeners();
		uninstallDefaults();

		if (comboBox.getRenderer() == null
			|| comboBox.getRenderer() instanceof UIResource)
		{
			comboBox.setRenderer(null);
		}
		if (comboBox.getEditor() == null
			|| comboBox.getEditor() instanceof UIResource)
		{
			comboBox.setEditor(null);
		}

		keyListener= null;
		focusListener= null;
		listDataListener= null;
		propertyChangeListener= null;
		editorFocusListener= null;
		popup= null;
		listBox= null;
		comboBox= null;
	}

	
	/**	Installs the default colors, default font, default renderer, and default
	 * 	editor into the JComboBox.
	 */
	protected void installDefaults()
	{
		LookAndFeel.installColorsAndFont(
			comboBox,
			"ComboBox.background",
			"ComboBox.foreground",
			"ComboBox.font");
		LookAndFeel.installBorder(comboBox, "ComboBox.border");
	}


	/**	Create and install the listeners for the combo box and its model.
	 * 	This method is called when the UI is installed.
	 */
	protected void installListeners()
	{
		if ((itemListener= createItemListener()) != null)
		{
			comboBox.addItemListener(itemListener);
		}
		if ((propertyChangeListener= createPropertyChangeListener()) != null)
		{
			comboBox.addPropertyChangeListener(propertyChangeListener);
		}
		if ((keyListener= createKeyListener()) != null)
		{
			comboBox.addKeyListener(keyListener);
		}
		if ((focusListener= createFocusListener()) != null)
		{
			comboBox.addFocusListener(focusListener);
		}
		if ((popupMouseListener= popup.getMouseListener()) != null)
		{
			comboBox.addMouseListener(popupMouseListener);
		}
		if ((popupMouseMotionListener= popup.getMouseMotionListener()) != null)
		{
			comboBox.addMouseMotionListener(popupMouseMotionListener);
		}
		if ((popupKeyListener= popup.getKeyListener()) != null)
		{
			comboBox.addKeyListener(popupKeyListener);
		}

		if (comboBox.getModel() != null)
		{
			if ((listDataListener= createListDataListener()) != null)
			{
				comboBox.getModel().addListDataListener(listDataListener);
			}
		}
	}


	/**	Uninstalls the default colors, default font, default renderer, and 
	 * 	default editor into the JComboBox.
	 */
	protected void uninstallDefaults()
	{
		LookAndFeel.installColorsAndFont(
			comboBox,
			"ComboBox.background",
			"ComboBox.foreground",
			"ComboBox.font");
		LookAndFeel.uninstallBorder(comboBox);
	}


	/**	Remove the installed listeners from the combo box and its model.
	 * 	The number and types of listeners removed and in this method should be
	 * 	the same that was added in <code>installListeners</code>
	 */
	protected void uninstallListeners()
	{
		if (keyListener != null)
		{
			comboBox.removeKeyListener(keyListener);
		}
		if (itemListener != null)
		{
			comboBox.removeItemListener(itemListener);
		}
		if (propertyChangeListener != null)
		{
			comboBox.removePropertyChangeListener(propertyChangeListener);
		}
		if (focusListener != null)
		{
			comboBox.removeFocusListener(focusListener);
		}
		if (popupMouseListener != null)
		{
			comboBox.removeMouseListener(popupMouseListener);
		}
		if (popupMouseMotionListener != null)
		{
			comboBox.removeMouseMotionListener(popupMouseMotionListener);
		}
		if (popupKeyListener != null)
		{
			comboBox.removeKeyListener(popupKeyListener);
		}
		if (comboBox.getModel() != null)
		{
			if (listDataListener != null)
			{
				comboBox.getModel().removeListDataListener(listDataListener);
			}
		}
	}


	/**	Creates the popup portion of the combo box.
	 *	
	 *		@return an instance of <code>ComboPopup</code>
	 *
	 * 	@see ComboPopup
	 */
	protected ComboPopup createPopup()
	{
		BasicComboPopup popup= new BasicComboPopup(comboBox);
		popup.getAccessibleContext().setAccessibleParent(comboBox);
		return popup;
	}

	
	/**	Creates a <code>KeyListener</code> which will be added to the
	 * 	combo box. If this method returns null then it will not be added
	 * 	to the combo box.
	 * 
	 * 	@return an instance <code>KeyListener</code> or null
	 */
	protected KeyListener createKeyListener()
	{
		return new KeyHandler();
	}


	/**	Creates a <code>FocusListener</code> which will be added to the combo box.
	 * 	If this method returns null then it will not be added to the combo box.
	 * 	
	 * 	@return an instance of a <code>FocusListener</code> or null
	 */
	protected FocusListener createFocusListener()
	{
		return new FocusHandler();
	}

	
	/**	Creates a list data listener which will be added to the
	 * 	<code>ComboBoxModel</code>. If this method returns null then
	 * 	it will not be added to the combo box model.
	 * 
	 * 	@return an instance of a <code>ListDataListener</code> or null
	 */
	protected ListDataListener createListDataListener()
	{
		return new ListDataHandler();
	}


	/**
	 * Creates an <code>ItemListener</code> which will be added to the 
	 * combo box. If this method returns null then it will not 
	 * be added to the combo box.
	 * <p>
	 * Subclasses may override this method to return instances of their own
	 * ItemEvent handlers.
	 *
	 * @return an instance of an <code>ItemListener</code> or null
	 */
	protected ItemListener createItemListener()
	{
		return null;
	}

	/**
	 * Creates a <code>PropertyChangeListener</code> which will be added to
	 * the combo box. If this method returns null then it will not
	 * be added to the combo box.
	 * 
	 * @return an instance of a <code>PropertyChangeListener</code> or null
	 */
	public PropertyChangeListener createPropertyChangeListener()
	{
		return new PropertyChangeHandler();
	}

	/**
	 * Creates a layout manager for managing the components which make up the 
	 * combo box.
	 * 
	 * @return an instance of a layout manager
	 */
	protected LayoutManager createLayoutManager()
	{
		return new ComboBoxLayoutManager();
	}

	/**
	 * Creates the default renderer that will be used in a non-editiable combo 
	 * box. A default renderer will used only if a renderer has not been 
	 * explicitly set with <code>setRenderer</code>.
	 * 
	 * @return a <code>ListCellRender</code> used for the combo box
	 * @see javax.swing.JComboBox#setRenderer
	 */
	protected ListCellRenderer createRenderer()
	{
		return new BasicComboBoxRenderer.UIResource();
	}

	/**
	 * Creates the default editor that will be used in editable combo boxes.  
	 * A default editor will be used only if an editor has not been 
	 * explicitly set with <code>setEditor</code>.
	 *
	 * @return a <code>ComboBoxEditor</code> used for the combo box
	 * @see javax.swing.JComboBox#setEditor
	 */
	protected ComboBoxEditor createEditor()
	{
		return new javax.swing.plaf.metal.MetalComboBoxEditor.UIResource();
	}

	//
	// end UI Initialization
	//======================

	//======================
	// begin Inner classes
	//

	/**
	 * This listener checks to see if the key event isn't a navigation key.  If
	 * it finds a key event that wasn't a navigation key it dispatches it to
	 * JComboBox.selectWithKeyChar() so that it can do type-ahead.
	 *
	 * This public inner class should be treated as protected. 
	 * Instantiate it only within subclasses of 
	 * <code>BasicComboBoxUI</code>.
	 */
	public class KeyHandler extends KeyAdapter
	{
		public void keyPressed(KeyEvent e)
		{
			if (comboBox.isEnabled()
				&& !isNavigationKey(e.getKeyCode())
				&& isTypeAheadKey(e))
			{

				if (comboBox.selectWithKeyChar(e.getKeyChar()))
				{
					e.consume();
				}
			}
		}

		boolean isTypeAheadKey(KeyEvent e)
		{
			return !e.isAltDown() && !e.isControlDown() && !e.isMetaDown();
		}
	}


	/**
	 * This listener watches for changes in the 
	 * <code>ComboBoxModel</code>.
	 * <p>
	 * This public inner class should be treated as protected. 
	 * Instantiate it only within subclasses of 
	 * <code>BasicComboBoxUI</code>.
	 */
	public class ListDataHandler implements ListDataListener
	{
		public void contentsChanged(ListDataEvent e)
		{
			if (!(e.getIndex0() == -1 && e.getIndex1() == -1))
			{
				isMinimumSizeDirty= true;
				comboBox.revalidate();
			}

			// set the editor with the selected item since this
			// is the event handler for a selected item change.
			if (comboBox.isEditable() && editor != null)
			{
				comboBox.configureEditor(
					comboBox.getEditor(),
					comboBox.getSelectedItem());
			}

			comboBox.repaint();
		}

		public void intervalAdded(ListDataEvent e)
		{
			isDisplaySizeDirty= true;
			contentsChanged(e);
		}

		public void intervalRemoved(ListDataEvent e)
		{
			isDisplaySizeDirty= true;
			contentsChanged(e);
		}
	}

	/**
	 * This listener watches for changes to the selection in the 
	 * combo box.
	 * <p>
	 * This public inner class should be treated as protected. 
	 * Instantiate it only within subclasses of 
	 * <code>BasicComboBoxUI</code>.
	 */
	public class ItemHandler implements ItemListener
	{
		// This class used to implement behavior which is now redundant.
		public void itemStateChanged(ItemEvent e)
		{
		}
	}

	/**
	 * This listener watches for bound properties that have changed in the
	 * combo box. 
	 * <p>
	 * Subclasses which wish to listen to combo box property changes should
	 * call the superclass methods to ensure that the combo box ui correctly 
	 * handles property changes.
	 * <p>
	 * This public inner class should be treated as protected. 
	 * Instantiate it only within subclasses of 
	 * <code>BasicComboBoxUI</code>.
	 */
	public class PropertyChangeHandler implements PropertyChangeListener
	{
		public void propertyChange(PropertyChangeEvent e)
		{
			String propertyName= e.getPropertyName();
			JComboBox comboBox= (JComboBox) e.getSource();

			if (propertyName.equals("model"))
			{
				ComboBoxModel newModel= (ComboBoxModel) e.getNewValue();
				ComboBoxModel oldModel= (ComboBoxModel) e.getOldValue();

				if (oldModel != null && listDataListener != null)
				{
					oldModel.removeListDataListener(listDataListener);
				}

				if (newModel != null && listDataListener != null)
				{
					newModel.addListDataListener(listDataListener);
				}

				if (editor != null)
				{
					comboBox.configureEditor(
						comboBox.getEditor(),
						comboBox.getSelectedItem());
				}
				isMinimumSizeDirty= true;
				isDisplaySizeDirty= true;
				comboBox.revalidate();
				comboBox.repaint();
			}
			else if (propertyName.equals("editor") && comboBox.isEditable())
			{
				addEditor();
				comboBox.revalidate();
			}
			else if (propertyName.equals("editable"))
			{
				if (comboBox.isEditable())
				{
					comboBox.setRequestFocusEnabled(false);
					addEditor();

⌨️ 快捷键说明

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