Slider: clicking on track now immediately moves the thumb to mouse location and starts dragging the thumb

This commit is contained in:
Karl Tauber
2020-12-20 13:32:10 +01:00
parent 3c58879ce5
commit 4fdd44858f
4 changed files with 351 additions and 48 deletions

View File

@@ -5,6 +5,8 @@ FlatLaf Change Log
#### New features and improvements
- Slider: Clicking on track now immediately moves the thumb to mouse location
and starts dragging the thumb.
- Extras: Added standard component extension classes that provides easy access
to FlatLaf specific client properties (see package
`com.formdev.flatlaf.extras.components`).

View File

@@ -226,6 +226,10 @@ public class FlatSliderUI
g.drawRect( trackRect.x, trackRect.y, trackRect.width - 1, trackRect.height - 1 );
g.setColor( Color.red );
g.drawRect( thumbRect.x, thumbRect.y, thumbRect.width - 1, thumbRect.height - 1 );
g.setColor( Color.green );
g.drawRect( tickRect.x, tickRect.y, tickRect.width - 1, tickRect.height - 1 );
g.setColor( Color.red );
g.drawRect( labelRect.x, labelRect.y, labelRect.width - 1, labelRect.height - 1 );
debug*/
super.paint( g, c );
@@ -502,7 +506,47 @@ debug*/
@Override
public void mousePressed( MouseEvent e ) {
setThumbPressed( isOverThumb( e ) );
if( !slider.isEnabled() )
return;
// use "old" behavior when clicking on track
if( UIManager.getBoolean( "Slider.scrollOnTrackClick" ) ) {
super.mousePressed( e );
return;
}
// "new" behavior set thumb to mouse location when clicking on track
int x = e.getX();
int y = e.getY();
// clicked on thumb --> let super class do the work
calculateGeometry();
if( thumbRect.contains( x, y ) ) {
super.mousePressed( e );
return;
}
if( UIManager.getBoolean( "Slider.onlyLeftMouseButtonDrag" ) &&
!SwingUtilities.isLeftMouseButton( e ) )
return;
// move the mouse event coordinates to the center of the thumb
int tx = thumbRect.x + (thumbRect.width / 2) - x;
int ty = thumbRect.y + (thumbRect.height / 2) - y;
e.translatePoint( tx, ty );
// invoke super mousePressed() to start dragging thumb
super.mousePressed( e );
// move the mouse event coordinates back to current mouse location
e.translatePoint( -tx, -ty );
// invoke super mouseDragged() to update thumb location
super.mouseDragged( e );
setThumbPressed( true );
}
@Override

View File

@@ -37,10 +37,18 @@ public class FlatComponentsTest
} );
}
private final JSlider[] allSliders;
private final JSlider[] roundSliders;
private final JSlider[] directionalSliders;
FlatComponentsTest() {
initComponents();
buttonTypeComboBox.init( ButtonType.class, true );
allSliders = new JSlider[] { slider1, slider2, slider3, slider4, slider5, slider6 };
roundSliders = new JSlider[] { slider1, slider2, slider6 };
directionalSliders = new JSlider[] { slider3, slider4, slider5 };
}
private void changeProgress() {
@@ -152,6 +160,64 @@ public class FlatComponentsTest
textField1.requestFocusInWindow();
}
private void sliderPaintTrackChanged() {
boolean paintTrack = sliderPaintTrackCheckBox.isSelected();
for( JSlider slider : allSliders )
slider.setPaintTrack( paintTrack );
}
private void sliderPaintTicksChanged() {
Boolean paintTicks = sliderPaintTicksCheckBox.getChecked();
if( paintTicks != null ) {
for( JSlider slider : allSliders )
slider.setPaintTicks( paintTicks );
} else {
for( JSlider slider : roundSliders )
slider.setPaintTicks( false );
for( JSlider slider : directionalSliders )
slider.setPaintTicks( true );
}
}
private void sliderPaintLabelsChanged() {
Boolean paintLabels = sliderPaintLabelsCheckBox.getChecked();
if( paintLabels != null ) {
for( JSlider slider : allSliders )
slider.setPaintLabels( paintLabels );
} else {
for( JSlider slider : roundSliders )
slider.setPaintLabels( false );
for( JSlider slider : directionalSliders )
slider.setPaintLabels( true );
}
}
private void sliderInvertedChanged() {
boolean inverted = sliderInvertedCheckBox.isSelected();
for( JSlider slider : allSliders )
slider.setInverted( inverted );
}
private void sliderSnapToTicksChanged() {
boolean snapToTicks = sliderSnapToTicksCheckBox.isSelected();
for( JSlider slider : allSliders )
slider.setSnapToTicks( snapToTicks );
}
private void majorThickSpacingChanged() {
int majorTickSpacing = (Integer) majorTickSpacingSpinner.getValue();
for( JSlider slider : directionalSliders ) {
slider.setLabelTable( null );
slider.setMajorTickSpacing( majorTickSpacing );
}
}
private void minorThickSpacingChanged() {
int minorTickSpacing = (Integer) minorTickSpacingSpinner.getValue();
for( JSlider slider : directionalSliders )
slider.setMinorTickSpacing( minorTickSpacing );
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel labelLabel = new JLabel();
@@ -273,8 +339,8 @@ public class FlatComponentsTest
FlatScrollBar scrollBar7 = new FlatScrollBar();
FlatScrollBar scrollBar8 = new FlatScrollBar();
JSeparator separator2 = new JSeparator();
JSlider slider2 = new JSlider();
JSlider slider4 = new JSlider();
slider2 = new JSlider();
slider4 = new JSlider();
JScrollPane scrollPane14 = new JScrollPane();
progressBar3 = new FlatProgressBar();
progressBar4 = new FlatProgressBar();
@@ -307,20 +373,29 @@ public class FlatComponentsTest
JSeparator separator1 = new JSeparator();
JPanel panel2 = new JPanel();
JLabel sliderLabel = new JLabel();
JSlider slider1 = new JSlider();
JSlider slider6 = new JSlider();
slider1 = new JSlider();
slider6 = new JSlider();
JPanel panel6 = new JPanel();
sliderPaintTrackCheckBox = new JCheckBox();
sliderPaintTicksCheckBox = new FlatTriStateCheckBox();
sliderPaintLabelsCheckBox = new FlatTriStateCheckBox();
sliderInvertedCheckBox = new JCheckBox();
sliderSnapToTicksCheckBox = new JCheckBox();
majorTickSpacingSpinner = new JSpinner();
minorTickSpacingSpinner = new JSpinner();
JLabel sliderLabel2 = new JLabel();
slider3 = new JSlider();
JSlider slider5 = new JSlider();
slider5 = new JSlider();
JLabel progressBarLabel = new JLabel();
progressBar1 = new FlatProgressBar();
progressBar2 = new FlatProgressBar();
JPanel panel7 = new JPanel();
indeterminateCheckBox = new JCheckBox();
squareCheckBox = new JCheckBox();
largeHeightCheckBox = new JCheckBox();
JLabel toolTipLabel = new JLabel();
JToolTip toolTip1 = new JToolTip();
JToolTip toolTip2 = new JToolTip();
largeHeightCheckBox = new JCheckBox();
JLabel toolBarLabel = new JLabel();
JToolBar toolBar1 = new JToolBar();
JButton button4 = new JButton();
@@ -1227,6 +1302,56 @@ public class FlatComponentsTest
slider6.setValue(30);
add(slider6, "cell 1 19 3 1");
//======== panel6 ========
{
panel6.setBorder(new TitledBorder("JSlider Control"));
panel6.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]",
// rows
"[]0" +
"[]0" +
"[]"));
//---- sliderPaintTrackCheckBox ----
sliderPaintTrackCheckBox.setText("track");
sliderPaintTrackCheckBox.setSelected(true);
sliderPaintTrackCheckBox.addActionListener(e -> sliderPaintTrackChanged());
panel6.add(sliderPaintTrackCheckBox, "cell 0 0");
//---- sliderPaintTicksCheckBox ----
sliderPaintTicksCheckBox.setText("ticks");
sliderPaintTicksCheckBox.addActionListener(e -> sliderPaintTicksChanged());
panel6.add(sliderPaintTicksCheckBox, "cell 0 0");
//---- sliderPaintLabelsCheckBox ----
sliderPaintLabelsCheckBox.setText("labels");
sliderPaintLabelsCheckBox.addActionListener(e -> sliderPaintLabelsChanged());
panel6.add(sliderPaintLabelsCheckBox, "cell 0 0");
//---- sliderInvertedCheckBox ----
sliderInvertedCheckBox.setText("inverted");
sliderInvertedCheckBox.addActionListener(e -> sliderInvertedChanged());
panel6.add(sliderInvertedCheckBox, "cell 0 1");
//---- sliderSnapToTicksCheckBox ----
sliderSnapToTicksCheckBox.setText("snap to ticks");
sliderSnapToTicksCheckBox.addActionListener(e -> sliderSnapToTicksChanged());
panel6.add(sliderSnapToTicksCheckBox, "cell 0 1");
//---- majorTickSpacingSpinner ----
majorTickSpacingSpinner.setModel(new SpinnerNumberModel(50, 0, 100, 5));
majorTickSpacingSpinner.addChangeListener(e -> majorThickSpacingChanged());
panel6.add(majorTickSpacingSpinner, "cell 0 2");
//---- minorTickSpacingSpinner ----
minorTickSpacingSpinner.setModel(new SpinnerNumberModel(10, 0, 100, 5));
minorTickSpacingSpinner.addChangeListener(e -> minorThickSpacingChanged());
panel6.add(minorTickSpacingSpinner, "cell 0 2");
}
add(panel6, "cell 4 19 1 2,grow");
//---- sliderLabel2 ----
sliderLabel2.setText("baseline");
add(sliderLabel2, "cell 0 20,alignx right,growx 0");
@@ -1262,15 +1387,34 @@ public class FlatComponentsTest
progressBar2.setValue(60);
add(progressBar2, "cell 1 21 3 1,growx");
//---- indeterminateCheckBox ----
indeterminateCheckBox.setText("indeterminate");
indeterminateCheckBox.addActionListener(e -> indeterminateProgress());
add(indeterminateCheckBox, "cell 4 21");
//======== panel7 ========
{
panel7.setBorder(new TitledBorder("JProgressBar Control"));
panel7.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]" +
"[fill]",
// rows
"[]0" +
"[]"));
//---- squareCheckBox ----
squareCheckBox.setText("square");
squareCheckBox.addActionListener(e -> squareChanged());
add(squareCheckBox, "cell 4 21");
//---- indeterminateCheckBox ----
indeterminateCheckBox.setText("indeterminate");
indeterminateCheckBox.addActionListener(e -> indeterminateProgress());
panel7.add(indeterminateCheckBox, "cell 0 0");
//---- squareCheckBox ----
squareCheckBox.setText("square");
squareCheckBox.addActionListener(e -> squareChanged());
panel7.add(squareCheckBox, "cell 1 0");
//---- largeHeightCheckBox ----
largeHeightCheckBox.setText("large height");
largeHeightCheckBox.addActionListener(e -> largeHeightChanged());
panel7.add(largeHeightCheckBox, "cell 0 1,aligny top,growy 0");
}
add(panel7, "cell 4 21 1 2,grow");
//---- toolTipLabel ----
toolTipLabel.setText("JToolTip:");
@@ -1284,11 +1428,6 @@ public class FlatComponentsTest
toolTip2.setTipText("Tool tip with\nmultiple\nlines.");
add(toolTip2, "cell 1 22 3 1");
//---- largeHeightCheckBox ----
largeHeightCheckBox.setText("large height");
largeHeightCheckBox.addActionListener(e -> largeHeightChanged());
add(largeHeightCheckBox, "cell 4 22,aligny top,growy 0");
//---- toolBarLabel ----
toolBarLabel.setText("JToolBar:");
add(toolBarLabel, "cell 0 23");
@@ -1417,6 +1556,8 @@ public class FlatComponentsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JTextField textField1;
private JSlider slider2;
private JSlider slider4;
private FlatProgressBar progressBar3;
private FlatProgressBar progressBar4;
private FlatTestEnumComboBox<ButtonType> buttonTypeComboBox;
@@ -1429,7 +1570,17 @@ public class FlatComponentsTest
private JRadioButton magentaOutlineRadioButton;
private JRadioButton magentaCyanOutlineRadioButton;
private JCheckBox focusPaintedCheckBox;
private JSlider slider1;
private JSlider slider6;
private JCheckBox sliderPaintTrackCheckBox;
private FlatTriStateCheckBox sliderPaintTicksCheckBox;
private FlatTriStateCheckBox sliderPaintLabelsCheckBox;
private JCheckBox sliderInvertedCheckBox;
private JCheckBox sliderSnapToTicksCheckBox;
private JSpinner majorTickSpacingSpinner;
private JSpinner minorTickSpacingSpinner;
private JSlider slider3;
private JSlider slider5;
private FlatProgressBar progressBar1;
private FlatProgressBar progressBar2;
private JCheckBox indeterminateCheckBox;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.3.0.337" Java: "15" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -874,6 +874,9 @@ new FormModel {
name: "slider2"
"orientation": 1
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 6,growy"
} )
@@ -885,6 +888,9 @@ new FormModel {
"paintLabels": true
"orientation": 1
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 6,growy"
} )
@@ -1134,6 +1140,9 @@ new FormModel {
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider1"
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 19 3 1,growx"
} )
@@ -1141,9 +1150,93 @@ new FormModel {
name: "slider6"
"enabled": false
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 19 3 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[]0[]0[]"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel6"
"border": new javax.swing.border.TitledBorder( "JSlider Control" )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "sliderPaintTrackCheckBox"
"text": "track"
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "sliderPaintTrackChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
name: "sliderPaintTicksCheckBox"
"text": "ticks"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "sliderPaintTicksChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
name: "sliderPaintLabelsCheckBox"
"text": "labels"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "sliderPaintLabelsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "sliderInvertedCheckBox"
"text": "inverted"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "sliderInvertedChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "sliderSnapToTicksCheckBox"
"text": "snap to ticks"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "sliderSnapToTicksChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "majorTickSpacingSpinner"
"model": new javax.swing.SpinnerNumberModel( 50, 0, 100, 5 )
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "majorThickSpacingChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "minorTickSpacingSpinner"
"model": new javax.swing.SpinnerNumberModel( 10, 0, 100, 5 )
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "minorThickSpacingChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 19 1 2,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "sliderLabel2"
"text": "baseline"
@@ -1172,6 +1265,9 @@ new FormModel {
"paintLabels": true
"enabled": false
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 20 3 1"
} )
@@ -1200,25 +1296,45 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 21 3 1,growx"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "indeterminateCheckBox"
"text": "indeterminate"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateProgress", false ) )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[][fill]"
"$rowConstraints": "[]0[]"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel7"
"border": new javax.swing.border.TitledBorder( "JProgressBar Control" )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "indeterminateCheckBox"
"text": "indeterminate"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateProgress", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "squareCheckBox"
"text": "square"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "squareChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "largeHeightCheckBox"
"text": "large height"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "largeHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,aligny top,growy 0"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 21"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "squareCheckBox"
"text": "square"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "squareChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 21"
"value": "cell 4 21 1 2,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolTipLabel"
@@ -1238,16 +1354,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 22 3 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "largeHeightCheckBox"
"text": "large height"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "largeHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 22,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolBarLabel"
"text": "JToolBar:"