42 |
import java.awt.Component; |
import java.awt.Component; |
43 |
import java.awt.Container; |
import java.awt.Container; |
44 |
import java.awt.Dimension; |
import java.awt.Dimension; |
45 |
|
import java.awt.Font; |
46 |
import java.awt.Graphics; |
import java.awt.Graphics; |
47 |
import java.awt.Insets; |
import java.awt.Insets; |
48 |
import java.awt.LayoutManager; |
import java.awt.LayoutManager; |
70 |
import javax.swing.JComponent; |
import javax.swing.JComponent; |
71 |
import javax.swing.JList; |
import javax.swing.JList; |
72 |
import javax.swing.ListCellRenderer; |
import javax.swing.ListCellRenderer; |
73 |
|
import javax.swing.SwingUtilities; |
74 |
import javax.swing.UIDefaults; |
import javax.swing.UIDefaults; |
75 |
import javax.swing.UIManager; |
import javax.swing.UIManager; |
76 |
import javax.swing.event.ListDataEvent; |
import javax.swing.event.ListDataEvent; |
169 |
*/ |
*/ |
170 |
Dimension displaySize; |
Dimension displaySize; |
171 |
|
|
|
// It seems that JComboBox doesn't have a border set explicitely. So we just |
|
|
// paint the border everytime combo box is displayed. |
|
|
|
|
|
/* border insets for this JComboBox |
|
|
* This is package-private to avoid an accessor method. */ |
|
|
static final Insets borderInsets = new Insets(2, 2, 2, 2); |
|
|
|
|
|
// Width of the arrow button |
|
|
// This is package-private to avoid an accessor method. |
|
|
// FIXME: has wrong name for a constant. |
|
|
static final int arrowButtonWidth = 15; |
|
|
|
|
172 |
// FIXME: This fields aren't used anywhere at this moment. |
// FIXME: This fields aren't used anywhere at this moment. |
173 |
protected Dimension cachedMinimumSize; |
protected Dimension cachedMinimumSize; |
174 |
protected CellRendererPane currentValuePane; |
protected CellRendererPane currentValuePane; |
523 |
*/ |
*/ |
524 |
protected void configureEditor() |
protected void configureEditor() |
525 |
{ |
{ |
526 |
|
editor.setFont(comboBox.getFont()); |
527 |
// FIXME: Need to implement. Set font and add listeners. |
// FIXME: Need to implement. Set font and add listeners. |
528 |
} |
} |
529 |
|
|
605 |
*/ |
*/ |
606 |
public boolean isFocusTraversable(JComboBox c) |
public boolean isFocusTraversable(JComboBox c) |
607 |
{ |
{ |
608 |
if (comboBox.isEditable()) |
if (!comboBox.isEditable()) |
609 |
return true; |
return true; |
610 |
|
|
611 |
return false; |
return false; |
619 |
*/ |
*/ |
620 |
public void paint(Graphics g, JComponent c) |
public void paint(Graphics g, JComponent c) |
621 |
{ |
{ |
622 |
if (c instanceof JComboBox) |
Rectangle rect = rectangleForCurrentValue(); |
623 |
{ |
paintCurrentValueBackground(g, rect, hasFocus); |
624 |
JComboBox cb = (JComboBox) c; |
paintCurrentValue(g, rect, hasFocus); |
|
|
|
|
paintBorder(g, comboBox.getBounds(), hasFocus); |
|
|
|
|
|
Rectangle rect = rectangleForCurrentValue(); |
|
|
paintCurrentValueBackground(g, rect, hasFocus); |
|
|
paintCurrentValue(g, rect, hasFocus); |
|
|
} |
|
|
} |
|
|
|
|
|
private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus) |
|
|
{ |
|
|
int x = 0; |
|
|
int y = 0; |
|
|
int width = bounds.width; |
|
|
int height = bounds.height; |
|
|
|
|
|
Color oldColor = g.getColor(); |
|
|
|
|
|
if (! arrowButton.getModel().isPressed()) |
|
|
BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray, |
|
|
Color.white, Color.gray, Color.white); |
|
|
else |
|
|
{ |
|
|
g.setColor(darkShadow); |
|
|
g.drawRect(x, y, width, height); |
|
|
g.setColor(shadow); |
|
|
g.drawRect(x + 1, y + 1, width - 3, height - 3); |
|
|
} |
|
|
g.setColor(oldColor); |
|
625 |
} |
} |
626 |
|
|
627 |
/** |
/** |
633 |
*/ |
*/ |
634 |
public Dimension getPreferredSize(JComponent c) |
public Dimension getPreferredSize(JComponent c) |
635 |
{ |
{ |
636 |
// return null to indicate that combo box's layout will determin its |
Dimension d = getDisplaySize(); |
637 |
// preferred size |
Dimension arrowDim = arrowButton.getPreferredSize(); |
638 |
return null; |
Dimension result = new Dimension(d.width + arrowDim.width, |
639 |
|
Math.max(d.height, arrowDim.height)); |
640 |
|
return result; |
641 |
} |
} |
642 |
|
|
643 |
/** |
/** |
650 |
*/ |
*/ |
651 |
public Dimension getMinimumSize(JComponent c) |
public Dimension getMinimumSize(JComponent c) |
652 |
{ |
{ |
653 |
return null; |
return getPreferredSize(c); |
654 |
} |
} |
655 |
|
|
656 |
|
/** The value returned by the getMaximumSize() method. */ |
657 |
|
private static final Dimension MAXIMUM_SIZE = new Dimension(32767, 32767); |
658 |
|
|
659 |
/** |
/** |
660 |
* Returns the maximum size for this {@link JComboBox} for this |
* Returns the maximum size for this {@link JComboBox} for this |
661 |
* look and feel. |
* look and feel. |
666 |
*/ |
*/ |
667 |
public Dimension getMaximumSize(JComponent c) |
public Dimension getMaximumSize(JComponent c) |
668 |
{ |
{ |
669 |
return null; |
return MAXIMUM_SIZE; |
670 |
} |
} |
671 |
|
|
672 |
public int getAccessibleChildrenCount(JComponent c) |
public int getAccessibleChildrenCount(JComponent c) |
734 |
*/ |
*/ |
735 |
protected Rectangle rectangleForCurrentValue() |
protected Rectangle rectangleForCurrentValue() |
736 |
{ |
{ |
737 |
Rectangle cbBounds = comboBox.getBounds(); |
Rectangle cbBounds = SwingUtilities.getLocalBounds(comboBox); |
738 |
|
Rectangle abBounds = arrowButton.getBounds(); |
739 |
// Subtract width or the arrow button and border insets |
Rectangle rectForCurrentValue = new Rectangle(cbBounds.x, cbBounds.y, |
740 |
Rectangle rectForCurrentValue = new Rectangle(cbBounds.x |
cbBounds.width - abBounds.width, cbBounds.height); |
|
+ borderInsets.left, |
|
|
cbBounds.y |
|
|
+ borderInsets.top, |
|
|
cbBounds.width |
|
|
- arrowButtonWidth |
|
|
- borderInsets.left |
|
|
- borderInsets.right, |
|
|
cbBounds.height |
|
|
- borderInsets.top |
|
|
- borderInsets.bottom); |
|
|
|
|
741 |
return rectForCurrentValue; |
return rectForCurrentValue; |
742 |
} |
} |
743 |
|
|
771 |
* If there is currently no selected item we will take an empty |
* If there is currently no selected item we will take an empty |
772 |
* String as replacement. |
* String as replacement. |
773 |
*/ |
*/ |
774 |
Component comp = comboBox.getRenderer() |
Component comp = comboBox.getRenderer().getListCellRendererComponent( |
775 |
.getListCellRendererComponent(listBox, |
listBox, (currentValue != null ? currentValue : ""), -1, |
776 |
(currentValue != null ? currentValue : ""), |
isPressed, hasFocus); |
777 |
-1, |
if (! comboBox.isEnabled()) |
778 |
isPressed, |
{ |
779 |
hasFocus); |
comp.setBackground(UIManager.getLookAndFeelDefaults().getColor( |
780 |
if (! comboBox.isEnabled()) |
"ComboBox.disabledBackground")); |
781 |
comp.setEnabled(false); |
comp.setForeground(UIManager.getLookAndFeelDefaults().getColor( |
782 |
|
"ComboBox.disabledForeground")); |
783 |
g.translate(borderInsets.left, borderInsets.top); |
comp.setEnabled(false); |
784 |
comp.setBounds(0, 0, bounds.width, bounds.height); |
} |
785 |
comp.paint(g); |
comp.setBounds(0, 0, bounds.width, bounds.height); |
786 |
g.translate(-borderInsets.left, -borderInsets.top); |
comp.setFont(comboBox.getFont()); |
787 |
|
comp.paint(g); |
788 |
comboBox.revalidate(); |
|
789 |
|
comboBox.revalidate(); |
790 |
} |
} |
791 |
else |
else |
792 |
comboBox.getEditor().setItem(comboBox.getSelectedItem()); |
comboBox.getEditor().setItem(comboBox.getSelectedItem()); |
850 |
// one |
// one |
851 |
for (int i = 0; i < numItems; i++) |
for (int i = 0; i < numItems; i++) |
852 |
{ |
{ |
853 |
Object item = model.getElementAt(i); |
Object item = model.getElementAt(i); |
854 |
String s = item.toString(); |
String s = item.toString(); |
855 |
Component comp = renderer.getListCellRendererComponent(listBox, item, |
Component comp = renderer.getListCellRendererComponent(listBox, item, |
856 |
-1, false, false); |
-1, false, false); |
857 |
|
|
858 |
if (comp.getPreferredSize().getWidth() > size.getWidth()) |
Dimension compSize = comp.getPreferredSize(); |
859 |
size = comp.getPreferredSize(); |
if (compSize.width > size.width) |
860 |
|
size.width = compSize.width; |
861 |
|
if (compSize.height > size.height) |
862 |
|
size.height = compSize.height; |
863 |
|
|
864 |
} |
} |
865 |
|
|
866 |
displaySize = size; |
displaySize = size; |
891 |
* |
* |
892 |
* @see BasicComboBoxUI#createLayoutManager() |
* @see BasicComboBoxUI#createLayoutManager() |
893 |
*/ |
*/ |
894 |
public class ComboBoxLayoutManager extends Object implements LayoutManager |
public class ComboBoxLayoutManager implements LayoutManager |
895 |
{ |
{ |
896 |
/** |
/** |
897 |
* Creates a new ComboBoxLayoutManager object. |
* Creates a new ComboBoxLayoutManager object. |
933 |
*/ |
*/ |
934 |
public Dimension preferredLayoutSize(Container parent) |
public Dimension preferredLayoutSize(Container parent) |
935 |
{ |
{ |
936 |
Dimension d = new Dimension(0, 0); |
return getPreferredSize((JComponent) parent); |
|
|
|
|
if (displaySize == null) |
|
|
displaySize = getDisplaySize(); |
|
|
|
|
|
// add size for the area that will display selected item |
|
|
d.width += displaySize.getWidth(); |
|
|
d.height += displaySize.getHeight(); |
|
|
|
|
|
// add size of the arrow button |
|
|
d.width += arrowButtonWidth; |
|
|
|
|
|
// add width and height of the border |
|
|
d.width += borderInsets.left + borderInsets.right; |
|
|
d.height += borderInsets.left + borderInsets.right; |
|
|
|
|
|
// Add combo box's insets |
|
|
Insets insets = parent.getInsets(); |
|
|
d.width += insets.left + insets.right; |
|
|
d.width += insets.left + insets.right; |
|
|
|
|
|
return d; |
|
937 |
} |
} |
938 |
|
|
939 |
/** |
/** |
945 |
*/ |
*/ |
946 |
public Dimension minimumLayoutSize(Container parent) |
public Dimension minimumLayoutSize(Container parent) |
947 |
{ |
{ |
948 |
Dimension minSize = getDefaultSize(); |
return preferredLayoutSize(parent); |
|
ComboBoxModel model = comboBox.getModel(); |
|
|
int numItems = model.getSize(); |
|
|
|
|
|
if (numItems == 0) |
|
|
return minSize; |
|
|
|
|
|
ListCellRenderer renderer = comboBox.getRenderer(); |
|
|
|
|
|
for (int i = 0; i < numItems; i++) |
|
|
{ |
|
|
Object item = model.getElementAt(i); |
|
|
String s = item.toString(); |
|
|
Component comp = renderer.getListCellRendererComponent(listBox, item, |
|
|
-1, false, false); |
|
|
|
|
|
if (comp.getPreferredSize().width < minSize.width) |
|
|
minSize = comp.getMinimumSize(); |
|
|
} |
|
|
return minSize; |
|
949 |
} |
} |
950 |
|
|
951 |
/** |
/** |
960 |
{ |
{ |
961 |
// Position editor component to the left of arrow button if combo box is |
// Position editor component to the left of arrow button if combo box is |
962 |
// editable |
// editable |
963 |
int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2; |
Dimension arrowPrefSize = arrowButton.getPreferredSize(); |
964 |
|
int editorWidth = comboBox.getBounds().width - arrowPrefSize.width; |
965 |
|
|
966 |
if (comboBox.isEditable()) |
if (comboBox.isEditable()) |
967 |
editor.setBounds(borderInsets.left, borderInsets.top, editorWidth, |
editor.setBounds(0, 0, editorWidth, comboBox.getBounds().height); |
968 |
comboBox.getBounds().height - borderInsets.left |
|
969 |
- borderInsets.top); |
arrowButton.setBounds(editorWidth, 0, arrowPrefSize.width, |
970 |
|
comboBox.getBounds().height); |
|
arrowButton.setBounds(editorWidth, 2, arrowButtonWidth, |
|
|
comboBox.getBounds().height - 4); |
|
971 |
comboBox.revalidate(); |
comboBox.revalidate(); |
972 |
} |
} |
973 |
} |
} |
1166 |
if ((ComboBoxModel) e.getNewValue() != null) |
if ((ComboBoxModel) e.getNewValue() != null) |
1167 |
comboBox.getModel().addListDataListener(listDataListener); |
comboBox.getModel().addListDataListener(listDataListener); |
1168 |
} |
} |
1169 |
|
else if (e.getPropertyName().equals("font")) |
1170 |
|
{ |
1171 |
|
Font font = (Font) e.getNewValue(); |
1172 |
|
editor.setFont(font); |
1173 |
|
listBox.setFont(font); |
1174 |
|
comboBox.revalidate(); |
1175 |
|
comboBox.repaint(); |
1176 |
|
} |
1177 |
|
|
1178 |
// FIXME: Need to handle changes in other bound properties. |
// FIXME: Need to handle changes in other bound properties. |
1179 |
} |
} |