From f20803ae5774a6b027025606620c7bf136a709df Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 16 Dec 2019 00:10:20 +0100 Subject: [PATCH] ProgressBar: If progress text is visible: - use smaller font - reduced height - changed style to rounded rectangle - fixed painting issues on low values Support configure of arc with `ProgressBar.arc` --- CHANGELOG.md | 6 ++ .../java/com/formdev/flatlaf/FlatLaf.java | 3 + .../formdev/flatlaf/ui/FlatProgressBarUI.java | 55 ++++++++++++++++--- .../com/formdev/flatlaf/util/UIScale.java | 8 +++ .../com/formdev/flatlaf/FlatLaf.properties | 1 + .../flatlaf/testing/FlatComponentsTest.java | 24 +++++--- .../flatlaf/testing/FlatComponentsTest.jfd | 14 +++-- 7 files changed, 92 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a826b36d..373edb1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ FlatLaf Change Log ## Unreleased +- ProgressBar: If progress text is visible: + - use smaller font + - reduced height + - changed style to rounded rectangle + - fixed painting issues on low values +- ProgressBar: Support configure of arc with `ProgressBar.arc`. - TabbedPane: Support background color for selected tabs. - CheckBox: changed `CheckBox.arc` from radius to diameter to be consistent with `Button.arc` and `Component.arc` diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 4d59e8e8..92d62dbe 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -283,6 +283,9 @@ public abstract class FlatLaf defaults.put( key, uiFont ); } defaults.put( "MenuItem.acceleratorFont", uiFont ); + + // use smaller font for progress bar + defaults.put( "ProgressBar.font", UIScale.scaleFont( uiFont, 0.85f ) ); } /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java index 034a9146..6fc00936 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java @@ -17,13 +17,16 @@ package com.formdev.flatlaf.ui; import java.awt.Dimension; +import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; +import java.awt.geom.Area; import java.awt.geom.RoundRectangle2D; import javax.swing.JComponent; import javax.swing.JProgressBar; import javax.swing.LookAndFeel; +import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicProgressBarUI; import com.formdev.flatlaf.util.UIScale; @@ -44,11 +47,19 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault ProgressBar.repaintInterval int default is 50 milliseconds * @uiDefault ProgressBar.cycleTime int default is 3000 milliseconds * + * + * + * @uiDefault ProgressBar.arc int + * * @author Karl Tauber */ public class FlatProgressBarUI extends BasicProgressBarUI { + protected int arc; + protected Dimension horizontalSize; + protected Dimension verticalSize; + public static ComponentUI createUI( JComponent c ) { return new FlatProgressBarUI(); } @@ -58,16 +69,37 @@ public class FlatProgressBarUI super.installDefaults(); LookAndFeel.installProperty( progressBar, "opaque", false ); + + arc = UIManager.getInt( "ProgressBar.arc" ); + horizontalSize = UIManager.getDimension( "ProgressBar.horizontalSize" ); + verticalSize = UIManager.getDimension( "ProgressBar.verticalSize" ); + } + + @Override + public Dimension getPreferredSize( JComponent c ) { + Dimension size = super.getPreferredSize( c ); + + if( progressBar.isStringPainted() ) { + // recalculate progress height/width to make it smaller + Insets insets = progressBar.getInsets(); + FontMetrics fm = progressBar.getFontMetrics( progressBar.getFont() ); + if( progressBar.getOrientation() == JProgressBar.HORIZONTAL ) + size.height = Math.max( fm.getHeight() + insets.top + insets.bottom, getPreferredInnerHorizontal().height ); + else + size.width = Math.max( fm.getHeight() + insets.left + insets.right, getPreferredInnerVertical().width ); + } + + return size; } @Override protected Dimension getPreferredInnerHorizontal() { - return UIScale.scale( super.getPreferredInnerHorizontal() ); + return UIScale.scale( horizontalSize ); } @Override protected Dimension getPreferredInnerVertical() { - return UIScale.scale( super.getPreferredInnerVertical() ); + return UIScale.scale( verticalSize ); } @Override @@ -90,13 +122,14 @@ public class FlatProgressBarUI return; boolean horizontal = (progressBar.getOrientation() == JProgressBar.HORIZONTAL); - int arc = horizontal ? height : width; + int arc = Math.min( UIScale.scale( this.arc ), horizontal ? height : width ); FlatUIUtils.setRenderingHints( (Graphics2D) g ); // paint track + RoundRectangle2D.Float trackShape = new RoundRectangle2D.Float( x, y, width, height, arc, arc ); g.setColor( progressBar.getBackground() ); - ((Graphics2D)g).fill( new RoundRectangle2D.Float( x, y, width, height, arc, arc ) ); + ((Graphics2D)g).fill( trackShape ); // paint progress if( progressBar.isIndeterminate() ) { @@ -112,11 +145,19 @@ public class FlatProgressBarUI } else { int amountFull = getAmountFull( insets, width, height ); - g.setColor( progressBar.getForeground() ); - ((Graphics2D)g).fill( horizontal + RoundRectangle2D.Float progressShape = horizontal ? new RoundRectangle2D.Float( c.getComponentOrientation().isLeftToRight() ? x : x + (width - amountFull), y, amountFull, height, arc, arc ) - : new RoundRectangle2D.Float( x, y + (height - amountFull), width, amountFull, arc, arc ) ); + : new RoundRectangle2D.Float( x, y + (height - amountFull), width, amountFull, arc, arc ); + + g.setColor( progressBar.getForeground() ); + if( amountFull < (horizontal ? height : width) ) { + // special painting for low amounts to avoid painting outside of track + Area area = new Area( trackShape ); + area.intersect( new Area( progressShape ) ); + ((Graphics2D)g).fill( area ); + } else + ((Graphics2D)g).fill( progressShape ); if( progressBar.isStringPainted() ) paintString( g, x, y, width, height, amountFull, insets ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java index 44c7db33..2bda2c57 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java @@ -197,6 +197,14 @@ public class UIScale return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize ); } + /** + * Scales the given font. + */ + public static FontUIResource scaleFont( FontUIResource font, float scaleFactor ) { + int newFontSize = Math.round( font.getSize() * scaleFactor ); + return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize ); + } + /** * Similar to sun.java2d.SunGraphicsEnvironment.getScaleFactor(String) */ diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 140a9d77..33fcc443 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -261,6 +261,7 @@ PopupMenuSeparator.stripeIndent=4 #---- ProgressBar ---- ProgressBar.border=com.formdev.flatlaf.ui.FlatEmptyBorder +ProgressBar.arc=6 ProgressBar.horizontalSize=146,6 ProgressBar.verticalSize=6,146 diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java index 557934a4..08a3aba2 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java @@ -38,7 +38,15 @@ public class FlatComponentsTest initComponents(); } - private void indeterminateCheckBoxActionPerformed() { + private void changeProgress() { + int value = slider3.getValue(); + progressBar1.setValue( value ); + progressBar2.setValue( value ); + progressBar3.setValue( value ); + progressBar4.setValue( value ); + } + + private void indeterminateProgress() { boolean indeterminate = indeterminateCheckBox.isSelected(); progressBar1.setIndeterminate( indeterminate ); progressBar2.setIndeterminate( indeterminate ); @@ -166,7 +174,7 @@ public class FlatComponentsTest JLabel sliderLabel = new JLabel(); JSlider slider1 = new JSlider(); JSlider slider6 = new JSlider(); - JSlider slider3 = new JSlider(); + slider3 = new JSlider(); JSlider slider5 = new JSlider(); JLabel progressBarLabel = new JLabel(); progressBar1 = new JProgressBar(); @@ -737,12 +745,12 @@ public class FlatComponentsTest //---- progressBar3 ---- progressBar3.setOrientation(SwingConstants.VERTICAL); - progressBar3.setValue(50); + progressBar3.setValue(60); add(progressBar3, "cell 4 13 1 6,growy"); //---- progressBar4 ---- progressBar4.setOrientation(SwingConstants.VERTICAL); - progressBar4.setValue(55); + progressBar4.setValue(60); progressBar4.setStringPainted(true); add(progressBar4, "cell 4 13 1 6,growy"); @@ -867,6 +875,7 @@ public class FlatComponentsTest slider3.setMajorTickSpacing(50); slider3.setPaintLabels(true); slider3.setValue(30); + slider3.addChangeListener(e -> changeProgress()); add(slider3, "cell 1 20 3 1,aligny top,grow 100 0"); //---- slider5 ---- @@ -883,17 +892,17 @@ public class FlatComponentsTest add(progressBarLabel, "cell 0 21"); //---- progressBar1 ---- - progressBar1.setValue(50); + progressBar1.setValue(60); add(progressBar1, "cell 1 21 3 1,growx"); //---- progressBar2 ---- progressBar2.setStringPainted(true); - progressBar2.setValue(55); + progressBar2.setValue(60); add(progressBar2, "cell 1 21 3 1,growx"); //---- indeterminateCheckBox ---- indeterminateCheckBox.setText("indeterminate"); - indeterminateCheckBox.addActionListener(e -> indeterminateCheckBoxActionPerformed()); + indeterminateCheckBox.addActionListener(e -> indeterminateProgress()); add(indeterminateCheckBox, "cell 4 21"); //---- toolTipLabel ---- @@ -952,6 +961,7 @@ public class FlatComponentsTest // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private JProgressBar progressBar3; private JProgressBar progressBar4; + private JSlider slider3; private JProgressBar progressBar1; private JProgressBar progressBar2; private JCheckBox indeterminateCheckBox; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd index 0039fcae..58ec8211 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd @@ -673,7 +673,7 @@ new FormModel { add( new FormComponent( "javax.swing.JProgressBar" ) { name: "progressBar3" "orientation": 1 - "value": 50 + "value": 60 auxiliary() { "JavaCodeGenerator.variableLocal": false } @@ -683,7 +683,7 @@ new FormModel { add( new FormComponent( "javax.swing.JProgressBar" ) { name: "progressBar4" "orientation": 1 - "value": 55 + "value": 60 "stringPainted": true auxiliary() { "JavaCodeGenerator.variableLocal": false @@ -836,6 +836,10 @@ new FormModel { "majorTickSpacing": 50 "paintLabels": true "value": 30 + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "changeProgress", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 20 3 1,aligny top,grow 100 0" } ) @@ -858,7 +862,7 @@ new FormModel { } ) add( new FormComponent( "javax.swing.JProgressBar" ) { name: "progressBar1" - "value": 50 + "value": 60 auxiliary() { "JavaCodeGenerator.variableLocal": false } @@ -868,7 +872,7 @@ new FormModel { add( new FormComponent( "javax.swing.JProgressBar" ) { name: "progressBar2" "stringPainted": true - "value": 55 + "value": 60 auxiliary() { "JavaCodeGenerator.variableLocal": false } @@ -881,7 +885,7 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateCheckBoxActionPerformed", false ) ) + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateProgress", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 21" } )