ComboBox: support using as cell renderer (e.g. in JTable)

This commit is contained in:
Karl Tauber
2021-05-04 21:39:08 +02:00
parent 067501cbe7
commit cacf0ea987
4 changed files with 90 additions and 30 deletions

View File

@@ -5,8 +5,13 @@ FlatLaf Change Log
#### New features and improvements
- Renamed `Flat*Laf.install()` methods to `Flat*Laf.setup()` to avoid confusion
with `UIManager.installLookAndFeel(LookAndFeelInfo info)`. The old
`Flat*Laf.install()` methods are still there, but marked as deprecated. They
will be removed in a future version.
- Button and ToggleButton: Support borderless button style (set client property
`JButton.buttonType` to `borderless`). (PR #276)
- ComboBox: Support using as cell renderer (e.g. in `JTable`).
- DesktopPane: Improved layout of iconified internal frames in dock:
- Always placed at bottom-left in desktop pane.
- Newly iconified frames are added to the right side of the dock.
@@ -23,10 +28,6 @@ FlatLaf Change Log
- Use mapper function in color filter to dynamically map colors. (PR #303)
- Color filter supports light and dark themes.
- Getters for icon name, classloader, etc.
- Renamed `Flat*Laf.install()` methods to `Flat*Laf.setup()` to avoid confusion
with `UIManager.installLookAndFeel(LookAndFeelInfo info)`. The old
`Flat*Laf.install()` methods are still there, but marked as deprecated. They
will be removed in a future version.
#### Fixed bugs

View File

@@ -141,6 +141,21 @@ public class FlatArrowButton
return FlatUIUtils.deriveColor( foreground, this.foreground );
}
/**
* Returns the color used to paint the arrow.
*
* @since 1.2
*/
protected Color getArrowColor() {
return isEnabled()
? (pressedForeground != null && isPressed()
? pressedForeground
: (hoverForeground != null && isHover()
? hoverForeground
: foreground))
: disabledForeground;
}
@Override
public Dimension getPreferredSize() {
return scale( super.getPreferredSize() );
@@ -170,13 +185,7 @@ public class FlatArrowButton
}
// paint arrow
g.setColor( deriveForeground( isEnabled()
? (pressedForeground != null && isPressed()
? pressedForeground
: (hoverForeground != null && isHover()
? hoverForeground
: foreground))
: disabledForeground ) );
g.setColor( deriveForeground( getArrowColor() ) );
paintArrow( (Graphics2D) g );
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );

View File

@@ -42,6 +42,7 @@ import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.CellRendererPane;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.InputMap;
@@ -390,6 +391,15 @@ public class FlatComboBoxUI
public void update( Graphics g, JComponent c ) {
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
float arc = FlatUIUtils.getBorderArc( c );
boolean paintBackground = true;
// check whether used as cell renderer
boolean isCellRenderer = c.getParent() instanceof CellRendererPane;
if( isCellRenderer ) {
focusWidth = 0;
arc = 0;
paintBackground = isCellRendererBackgroundChanged();
}
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && (focusWidth > 0 || arc > 0) )
@@ -407,27 +417,29 @@ public class FlatComboBoxUI
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( getBackground( enabled ) );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
g2.setColor( paintButton ? buttonEditableBackground : buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
if( paintBackground || c.isOpaque() ) {
g2.setColor( getBackground( enabled ) );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow button
if( paintButton ) {
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
// paint arrow button background
if( enabled && !isCellRenderer ) {
g2.setColor( paintButton ? buttonEditableBackground : buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow button
if( paintButton ) {
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
}
}
// avoid that the "current value" renderer is invoked with enabled antialiasing
@@ -554,6 +566,16 @@ public class FlatComboBoxUI
}
}
private boolean isCellRenderer() {
return comboBox.getParent() instanceof CellRendererPane;
}
private boolean isCellRendererBackgroundChanged() {
// parent is a CellRendererPane, parentParent is e.g. a JTable
Container parentParent = comboBox.getParent().getParent();
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
}
//---- class FlatComboBoxButton -------------------------------------------
protected class FlatComboBoxButton
@@ -580,6 +602,14 @@ public class FlatComboBoxUI
protected boolean isPressed() {
return super.isPressed() || (!comboBox.isEditable() ? pressed : false);
}
@Override
protected Color getArrowColor() {
if( isCellRenderer() && isCellRendererBackgroundChanged() )
return comboBox.getForeground();
return super.getArrowColor();
}
}
//---- class FlatComboPopup -----------------------------------------------

View File

@@ -134,6 +134,7 @@ public class FlatComponents2Test
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
cm.getColumn(2).setCellRenderer( new TestComboBoxTableCellRenderer() );
cm.getColumn(2).setCellEditor( new DefaultCellEditor( new JComboBox<>( months ) ) );
JComboBox<String> editableComboBox = new JComboBox<>( months );
editableComboBox.setEditable( true );
@@ -1219,4 +1220,23 @@ public class FlatComponents2Test
return this;
}
}
//---- class TestComboBoxTableCellRenderer --------------------------------
private static class TestComboBoxTableCellRenderer
extends JComboBox<String>
implements TableCellRenderer
{
@Override
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column )
{
setModel( new DefaultComboBoxModel<>( new String[] { String.valueOf( value ) } ) );
setBackground( isSelected ? table.getSelectionBackground() : table.getBackground() );
setForeground( isSelected ? table.getSelectionForeground() : table.getForeground() );
setBorder( null );
return this;
}
}
}