macOS themes: fix horizontal centering of combobox arrows (issue #497; PR #533)

This commit is contained in:
Karl Tauber
2022-12-03 19:17:10 +01:00
parent 9fef2f9d05
commit 4e44e25d30
3 changed files with 71 additions and 20 deletions

View File

@@ -766,12 +766,6 @@ public class FlatComboBoxUI
protected FlatComboBoxButton() { protected FlatComboBoxButton() {
this( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor, this( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor,
buttonHoverArrowColor, null, buttonPressedArrowColor, null ); buttonHoverArrowColor, null, buttonPressedArrowColor, null );
if( isMacStyle() ) {
setArrowWidth( 7 );
setArrowThickness( 1.5f );
setRoundBorderAutoXOffset( false );
}
} }
protected FlatComboBoxButton( int direction, String type, Color foreground, Color disabledForeground, protected FlatComboBoxButton( int direction, String type, Color foreground, Color disabledForeground,
@@ -786,6 +780,21 @@ public class FlatComboBoxUI
buttonHoverArrowColor, null, buttonPressedArrowColor, null ); buttonHoverArrowColor, null, buttonPressedArrowColor, null );
} }
@Override
public int getArrowWidth() {
return isMacStyle() ? (getWidth() % 2 == 0 ? 6 : 7) : super.getArrowWidth();
}
@Override
public float getArrowThickness() {
return isMacStyle() ? 1.5f : super.getArrowThickness();
}
@Override
public boolean isRoundBorderAutoXOffset() {
return isMacStyle() ? false : super.isRoundBorderAutoXOffset();
}
@Override @Override
protected boolean isHover() { protected boolean isHover() {
return super.isHover() || (!comboBox.isEditable() ? hover : false); return super.isHover() || (!comboBox.isEditable() ? hover : false);

View File

@@ -23,6 +23,7 @@ import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.beans.Beans;
import java.util.Hashtable; import java.util.Hashtable;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
@@ -91,10 +92,15 @@ public class FlatPaintingArrowsTest
private void pixelsChanged() { private void pixelsChanged() {
boolean paintPixels = pixelsCheckBox.isSelected(); boolean paintPixels = pixelsCheckBox.isSelected();
boolean paintVector = vectorCheckBox.isSelected();
vectorCheckBox.setEnabled( paintPixels );
FlatTestFrame.updateComponentsRecur( panel, (c, type) -> { FlatTestFrame.updateComponentsRecur( panel, (c, type) -> {
if( c instanceof ArrowPainter ) if( c instanceof ArrowPainter ) {
((ArrowPainter)c).paintPixels = paintPixels; ((ArrowPainter)c).paintPixels = paintPixels;
((ArrowPainter)c).paintVector = paintVector;
}
} ); } );
panel.repaint(); panel.repaint();
@@ -189,6 +195,7 @@ public class FlatPaintingArrowsTest
JLabel scaleLabel = new JLabel(); JLabel scaleLabel = new JLabel();
scaleSlider = new JSlider(); scaleSlider = new JSlider();
pixelsCheckBox = new JCheckBox(); pixelsCheckBox = new JCheckBox();
vectorCheckBox = new JCheckBox();
pixelsScaleLabel = new JLabel(); pixelsScaleLabel = new JLabel();
pixelsScaleSlider = new JSlider(); pixelsScaleSlider = new JSlider();
JPanel panel55 = new JPanel(); JPanel panel55 = new JPanel();
@@ -347,10 +354,12 @@ public class FlatPaintingArrowsTest
//======== panel1 ======== //======== panel1 ========
{ {
panel1.setLayout(new MigLayout( panel1.setLayout(new MigLayout(
"hidemode 3", "flowy,hidemode 3",
// columns // columns
"[fill]" + "[fill]" +
"[grow,fill]para" + "[grow,fill]para" +
"[fill]" +
"[fill]" +
"[fill]", "[fill]",
// rows // rows
"[]" + "[]" +
@@ -380,11 +389,18 @@ public class FlatPaintingArrowsTest
pixelsCheckBox.addActionListener(e -> pixelsChanged()); pixelsCheckBox.addActionListener(e -> pixelsChanged());
panel1.add(pixelsCheckBox, "cell 2 0"); panel1.add(pixelsCheckBox, "cell 2 0");
//---- vectorCheckBox ----
vectorCheckBox.setText("vector");
vectorCheckBox.setMnemonic('V');
vectorCheckBox.setSelected(true);
vectorCheckBox.addActionListener(e -> pixelsChanged());
panel1.add(vectorCheckBox, "cell 2 0");
//---- pixelsScaleLabel ---- //---- pixelsScaleLabel ----
pixelsScaleLabel.setText("Scale:"); pixelsScaleLabel.setText("Scale:");
pixelsScaleLabel.setLabelFor(pixelsScaleSlider); pixelsScaleLabel.setLabelFor(pixelsScaleSlider);
pixelsScaleLabel.setDisplayedMnemonic('C'); pixelsScaleLabel.setDisplayedMnemonic('C');
panel1.add(pixelsScaleLabel, "cell 2 0"); panel1.add(pixelsScaleLabel, "cell 3 0");
//---- pixelsScaleSlider ---- //---- pixelsScaleSlider ----
pixelsScaleSlider.setMinimum(100); pixelsScaleSlider.setMinimum(100);
@@ -395,7 +411,7 @@ public class FlatPaintingArrowsTest
pixelsScaleSlider.setPaintTicks(true); pixelsScaleSlider.setPaintTicks(true);
pixelsScaleSlider.setPaintLabels(true); pixelsScaleSlider.setPaintLabels(true);
pixelsScaleSlider.addChangeListener(e -> pixelsScaleChanged()); pixelsScaleSlider.addChangeListener(e -> pixelsScaleChanged());
panel1.add(pixelsScaleSlider, "cell 2 0"); panel1.add(pixelsScaleSlider, "cell 4 0");
//======== panel55 ======== //======== panel55 ========
{ {
@@ -467,7 +483,7 @@ public class FlatPaintingArrowsTest
buttonCheckBox.addActionListener(e -> arrowButtonChanged()); buttonCheckBox.addActionListener(e -> arrowButtonChanged());
panel55.add(buttonCheckBox, "cell 10 0,alignx left,growx 0"); panel55.add(buttonCheckBox, "cell 10 0,alignx left,growx 0");
} }
panel1.add(panel55, "cell 0 1 3 1"); panel1.add(panel55, "cell 0 1 5 1");
} }
add(panel1, BorderLayout.NORTH); add(panel1, BorderLayout.NORTH);
// JFormDesigner - End of component initialization //GEN-END:initComponents // JFormDesigner - End of component initialization //GEN-END:initComponents
@@ -486,6 +502,7 @@ public class FlatPaintingArrowsTest
private FlatPaintingArrowsTest.ArrowPainter arrowPainter16; private FlatPaintingArrowsTest.ArrowPainter arrowPainter16;
private JSlider scaleSlider; private JSlider scaleSlider;
private JCheckBox pixelsCheckBox; private JCheckBox pixelsCheckBox;
private JCheckBox vectorCheckBox;
private JLabel pixelsScaleLabel; private JLabel pixelsScaleLabel;
private JSlider pixelsScaleSlider; private JSlider pixelsScaleSlider;
private JSpinner arrowWidthSpinner; private JSpinner arrowWidthSpinner;
@@ -515,6 +532,7 @@ public class FlatPaintingArrowsTest
float arrowThickness = 1; float arrowThickness = 1;
int scale = 4; int scale = 4;
boolean paintPixels; boolean paintPixels;
boolean paintVector;
float paintPixelsScale = 1; float paintPixelsScale = 1;
public ArrowPainter() { public ArrowPainter() {
@@ -619,18 +637,27 @@ public class FlatPaintingArrowsTest
// paint icon to buffered image // paint icon to buffered image
BufferedImage bi = new BufferedImage( bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_ARGB ); BufferedImage bi = new BufferedImage( bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_ARGB );
Graphics bg = bi.createGraphics(); Graphics2D bg = bi.createGraphics();
try { try {
FlatUIUtils.setRenderingHints( bg ); FlatUIUtils.setRenderingHints( bg );
bg.scale( paintPixelsScale, paintPixelsScale );
bg.setColor( Color.blue ); bg.setColor( Color.blue );
paintArrow( (Graphics2D) bg, bitmapWidth, bitmapHeight ); paintArrow( bg, width, height );
} finally { } finally {
bg.dispose(); bg.dispose();
} }
// draw scaled-up image // draw scaled-up image
g2.drawImage( bi, 0, 0, getWidth(), getHeight(), null ); g2.drawImage( bi, 0, 0, getWidth(), getHeight(), null );
if( paintVector ) {
AffineTransform oldTransform = g2.getTransform();
g2.scale( scale, scale );
g.setColor( new Color( (Color.red.getRGB() & 0xffffff) | (0xa0 << 24), true ) );
paintArrow( g2, width, height );
g2.setTransform( oldTransform );
}
} }
// paint border and grid // paint border and grid
@@ -660,8 +687,11 @@ public class FlatPaintingArrowsTest
} }
private void paintArrow( Graphics2D g, int width, int height ) { private void paintArrow( Graphics2D g, int width, int height ) {
FlatUIUtils.paintArrow( g, 0, 0, width, height, // do not paint in JFormDesigner because it may use a different FlatLaf version
direction, chevron, arrowSize, arrowThickness, xOffset, yOffset ); if( !Beans.isDesignTime() ) {
FlatUIUtils.paintArrow( g, 0, 0, width, height,
direction, chevron, arrowSize, arrowThickness, xOffset, yOffset );
}
if( button ) { if( button ) {
FlatArrowButton arrowButton = new FlatArrowButton( direction, FlatArrowButton arrowButton = new FlatArrowButton( direction,

View File

@@ -184,8 +184,8 @@ new FormModel {
"value": "Center" "value": "Center"
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3" "$layoutConstraints": "flowy,hidemode 3"
"$columnConstraints": "[fill][grow,fill]para[fill]" "$columnConstraints": "[fill][grow,fill]para[fill][fill][fill]"
"$rowConstraints": "[][]" "$rowConstraints": "[][]"
} ) { } ) {
name: "panel1" name: "panel1"
@@ -225,6 +225,18 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0" "value": "cell 2 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "vectorCheckBox"
"text": "vector"
"mnemonic": 86
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "pixelsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "pixelsScaleLabel" name: "pixelsScaleLabel"
"text": "Scale:" "text": "Scale:"
@@ -234,7 +246,7 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0" "value": "cell 3 0"
} ) } )
add( new FormComponent( "javax.swing.JSlider" ) { add( new FormComponent( "javax.swing.JSlider" ) {
name: "pixelsScaleSlider" name: "pixelsScaleSlider"
@@ -250,7 +262,7 @@ new FormModel {
} }
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "pixelsScaleChanged", false ) ) addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "pixelsScaleChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0" "value": "cell 4 0"
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3" "$layoutConstraints": "hidemode 3"
@@ -366,7 +378,7 @@ new FormModel {
"value": "cell 10 0,alignx left,growx 0" "value": "cell 10 0,alignx left,growx 0"
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1 3 1" "value": "cell 0 1 5 1"
} ) } )
}, new FormLayoutConstraints( class java.lang.String ) { }, new FormLayoutConstraints( class java.lang.String ) {
"value": "North" "value": "North"