帆软使用的第三方框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

366 lines
11 KiB

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tiny Look and Feel *
* *
* (C) Copyright 2003 - 2007 Hans Bickel *
* *
* For licensing information and credits, please refer to the *
* comment in file de.muntjak.tinylookandfeel.TinyLookAndFeel *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.muntjak.tinylookandfeel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ComboBoxEditor;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.ListCellRenderer;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxIcon;
/**
* TinyComboBoxUI
*
* @version 1.3
* @author Hans Bickel
*/
public class TinyComboBoxUI extends BasicComboBoxUI {
// Flag for calculating the display size
protected boolean isDisplaySizeDirty = true;
// Cached the size that the display needs to render the largest item
protected Dimension cachedDisplaySize = new Dimension(0, 0);
public static ComponentUI createUI(JComponent c) {
return new TinyComboBoxUI();
}
public void paint(Graphics g, JComponent c) {
}
protected ComboBoxEditor createEditor() {
return new TinyComboBoxEditor.UIResource();
}
protected ComboPopup createPopup() {
return new MetalComboPopup(comboBox);
}
protected JButton createArrowButton() {
JButton button = new TinyComboBoxButton(comboBox,
new MetalComboBoxIcon(),
comboBox.isEditable(),
currentValuePane,
listBox);
button.setMargin(new Insets(0, 0, 0, 0));
button.putClientProperty("isComboBoxButton", Boolean.TRUE);
return button;
}
protected void installComponents() {
super.installComponents();
if(arrowButton != null) {
arrowButton.setFocusable(false);
}
}
public PropertyChangeListener createPropertyChangeListener() {
return new TinyPropertyChangeListener();
}
/**
* This inner class is marked "public" due to a compiler bug.
* This class should be treated as a "protected" inner class.
* Instantiate it only within subclasses of <FooUI>.
*/
public class TinyPropertyChangeListener extends BasicComboBoxUI.PropertyChangeHandler {
public void propertyChange(PropertyChangeEvent e) {
super.propertyChange(e);
String propertyName = e.getPropertyName();
if(propertyName.equals("editable")) {
TinyComboBoxButton button = (TinyComboBoxButton)arrowButton;
button.setIconOnly(comboBox.isEditable());
isMinimumSizeDirty = true;
isDisplaySizeDirty = true;
comboBox.revalidate();
}
// else if(propertyName.equals("font")) {
// isMinimumSizeDirty = true;
// isDisplaySizeDirty = true;
// comboBox.revalidate();
// }
else if(propertyName.equals("background")) {
Color color = (Color) e.getNewValue();
listBox.setBackground(color);
}
else if(propertyName.equals("foreground")) {
Color color = (Color) e.getNewValue();
listBox.setForeground(color);
}
}
}
/**
* As of Java 2 platform v1.4 this method is no longer used. Do not call or
* override. All the functionality of this method is in the
* MetalPropertyChangeListener.
*
* @deprecated As of Java 2 platform v1.4.
*/
protected void editablePropertyChanged(PropertyChangeEvent e) {
}
protected LayoutManager createLayoutManager() {
return new TinyComboBoxLayoutManager();
}
/**
* This inner class is marked &quot;public&quot; due to a compiler bug.
* This class should be treated as a &quot;protected&quot; inner class.
* Instantiate it only within subclasses of <FooUI>.
*/
public class TinyComboBoxLayoutManager implements LayoutManager {
public void addLayoutComponent(String name, Component comp) {
}
public void removeLayoutComponent(Component comp) {
}
public Dimension preferredLayoutSize(Container parent) {
JComboBox cb = (JComboBox) parent;
return parent.getPreferredSize();
}
public Dimension minimumLayoutSize(Container parent) {
JComboBox cb = (JComboBox) parent;
return parent.getMinimumSize();
}
public void layoutContainer(Container parent) {
JComboBox cb = (JComboBox) parent;
int width = cb.getWidth();
int height = cb.getHeight();
Rectangle cvb;
if (comboBox.isEditable()) {
if (arrowButton != null) {
arrowButton.setBounds(width -
Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]], 0,
Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]], height);
}
if (editor != null) {
cvb = rectangleForCurrentValue2();
editor.setBounds(cvb);
}
} else {
arrowButton.setBounds(0, 0, width, height);
}
}
}
protected Rectangle rectangleForCurrentValue2() {
int width = comboBox.getWidth();
int height = comboBox.getHeight();
Insets insets = getInsets();
int buttonSize = height - (insets.top + insets.bottom);
if (arrowButton != null) {
buttonSize = Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]];
}
if (comboBox.getComponentOrientation().isLeftToRight()) {
return new Rectangle(insets.left,
insets.top,
width - (insets.left + insets.right + buttonSize),
height - (insets.top + insets.bottom));
} else {
return new Rectangle(
insets.left + buttonSize,
insets.top,
width - (insets.left + insets.right + buttonSize),
height - (insets.top + insets.bottom));
}
}
/**
* As of Java 2 platform v1.4 this method is no
* longer used.
*
* @deprecated As of Java 2 platform v1.4.
*/
protected void removeListeners() {
if (propertyChangeListener != null) {
comboBox.removePropertyChangeListener(propertyChangeListener);
}
}
// These two methods were overloaded and made public. This was probably a
// mistake in the implementation. The functionality that they used to
// provide is no longer necessary and should be removed. However,
// removing them will create an uncompatible API change.
public void configureEditor() {
super.configureEditor();
}
public void unconfigureEditor() {
super.unconfigureEditor();
}
/**
* @param c the combo box
*/
public Dimension getMinimumSize(JComponent c) {
if(!isMinimumSizeDirty) {
isDisplaySizeDirty = true; // 1.3
return new Dimension(cachedMinimumSize);
}
// changed in 1.3
Insets insets = Theme.comboInsets[Theme.style];
Dimension size = getDisplaySize();
size.width += Theme.comboButtonWidth[Theme.derivedStyle[Theme.style]];
size.width += insets.left + insets.right;
size.height += insets.top + insets.bottom;
cachedMinimumSize.setSize(size.width, size.height);
isMinimumSizeDirty = false;
return new Dimension(cachedMinimumSize);
}
/**
* Copied from BasicComboBoxUI, because isDisplaySizeDirty was declared private!?
* Returns the calculated size of the display area. The display area is the
* portion of the combo box in which the selected item is displayed. This
* method will use the prototype display value if it has been set.
* <p>
* For combo boxes with a non trivial number of items, it is recommended to
* use a prototype display value to significantly speed up the display
* size calculation.
*
* @return the size of the display area calculated from the combo box items
* @see javax.swing.JComboBox#setPrototypeDisplayValue
*/
protected Dimension getDisplaySize() {
if(!isDisplaySizeDirty) {
return new Dimension(cachedDisplaySize);
}
Dimension result = new Dimension();
ListCellRenderer renderer = comboBox.getRenderer();
if(renderer == null) {
renderer = new DefaultListCellRenderer();
}
Object prototypeValue = comboBox.getPrototypeDisplayValue();
if(prototypeValue != null) {
// Calculates the dimension based on the prototype value
result = getSizeForComponent(renderer.getListCellRendererComponent(
listBox, prototypeValue, -1, false, false));
}
else {
// Calculate the dimension by iterating over all the elements in the combo
// box list.
ComboBoxModel model = comboBox.getModel();
int modelSize = model.getSize();
Dimension d;
Component cpn;
if(modelSize > 0) {
for (int i = 0; i < modelSize ; i++ ) {
// Calculates the maximum height and width based on the largest
// element
d = getSizeForComponent(renderer.getListCellRendererComponent(
listBox, model.getElementAt(i), -1, false, false));
result.width = Math.max(result.width,d.width);
result.height = Math.max(result.height,d.height);
}
}
else {
result = getDefaultSize();
if(comboBox.isEditable()) {
result.width = 100;
}
}
}
if(comboBox.isEditable()) {
Dimension d = editor.getPreferredSize();
result.width = Math.max(result.width, d.width);
result.height = Math.max(result.height, d.height);
}
// Set the cached value
cachedDisplaySize.setSize(result.width, result.height);
isDisplaySizeDirty = false;
return result;
}
/*
* Copied from BasicComboBoxUI.
*/
protected Dimension getSizeForComponent(Component comp) {
currentValuePane.add(comp);
comp.setFont(comboBox.getFont());
Dimension d = comp.getPreferredSize();
currentValuePane.remove(comp);
return d;
}
/**
* This inner class is marked &quot;public&quot; due to a compiler bug.
* This class should be treated as a &quot;protected&quot; inner class.
* Instantiate it only within subclasses of <FooUI>.
*
* This class is now obsolete and doesn't do anything and
* is only included for backwards API compatibility. Do not call or
* override.
*
* @deprecated As of Java 2 platform v1.4.
*/
public class MetalComboPopup extends BasicComboPopup {
public MetalComboPopup(JComboBox cBox) {
super(cBox);
}
// This method was overloaded and made public. This was probably
// mistake in the implementation. The functionality that they used to
// provide is no longer necessary and should be removed. However,
// removing them will create an uncompatible API change.
public void delegateFocus(MouseEvent e) {
super.delegateFocus(e);
}
}
}