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
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 "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 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 "public" due to a compiler bug. |
|
* This class should be treated as a "protected" 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); |
|
} |
|
} |
|
}
|
|
|