Slider: snap to ticks is now done while dragging the thumb

This commit is contained in:
Karl Tauber
2020-12-20 17:32:01 +01:00
parent 4fdd44858f
commit 53854a4d13
4 changed files with 254 additions and 185 deletions

View File

@@ -6,7 +6,12 @@ FlatLaf Change Log
#### New features and improvements
- Slider: Clicking on track now immediately moves the thumb to mouse location
and starts dragging the thumb.
and starts dragging the thumb. Use `UIManager.put(
"Slider.scrollOnTrackClick", true )` to enable old behavior that scrolls the
thumb when clicking on track.
- Slider: Snap to ticks is now done while dragging the thumb. Use
`UIManager.put( "Slider.snapToTicksOnReleased", true )` to enable old behavior
that snaps to ticks on mouse released.
- Extras: Added standard component extension classes that provides easy access
to FlatLaf specific client properties (see package
`com.formdev.flatlaf.extras.components`).

View File

@@ -543,8 +543,8 @@ debug*/
// move the mouse event coordinates back to current mouse location
e.translatePoint( -tx, -ty );
// invoke super mouseDragged() to update thumb location
super.mouseDragged( e );
// invoke mouseDragged() to update thumb location
mouseDragged( e );
setThumbPressed( true );
}
@@ -555,6 +555,20 @@ debug*/
super.mouseReleased( e );
}
@Override
public void mouseDragged( MouseEvent e ) {
super.mouseDragged( e );
if( isDragging() &&
slider.getSnapToTicks() &&
slider.isEnabled() &&
!UIManager.getBoolean( "Slider.snapToTicksOnReleased" ) )
{
calculateThumbLocation();
slider.repaint();
}
}
protected void setThumbHover( boolean hover ) {
if( hover != thumbHover ) {
thumbHover = hover;

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.testing;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.ChangeListener;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.extras.components.*;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
@@ -49,6 +50,15 @@ public class FlatComponentsTest
allSliders = new JSlider[] { slider1, slider2, slider3, slider4, slider5, slider6 };
roundSliders = new JSlider[] { slider1, slider2, slider6 };
directionalSliders = new JSlider[] { slider3, slider4, slider5 };
ChangeListener sliderChanged = e -> {
JSlider slider = (JSlider) e.getSource();
String text = slider.getValue() + " " + slider.getValueIsAdjusting();
sliderValueLabel.setText( text );
// System.out.println( text );
};
for( JSlider slider : allSliders )
slider.addChangeListener( sliderChanged );
}
private void changeProgress() {
@@ -375,6 +385,7 @@ public class FlatComponentsTest
JLabel sliderLabel = new JLabel();
slider1 = new JSlider();
slider6 = new JSlider();
JPanel panel8 = new JPanel();
JPanel panel6 = new JPanel();
sliderPaintTrackCheckBox = new JCheckBox();
sliderPaintTicksCheckBox = new FlatTriStateCheckBox();
@@ -383,16 +394,17 @@ public class FlatComponentsTest
sliderSnapToTicksCheckBox = new JCheckBox();
majorTickSpacingSpinner = new JSpinner();
minorTickSpacingSpinner = new JSpinner();
sliderValueLabel = new JLabel();
JPanel panel7 = new JPanel();
indeterminateCheckBox = new JCheckBox();
squareCheckBox = new JCheckBox();
largeHeightCheckBox = new JCheckBox();
JLabel sliderLabel2 = new JLabel();
slider3 = 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();
@@ -1302,55 +1314,103 @@ public class FlatComponentsTest
slider6.setValue(30);
add(slider6, "cell 1 19 3 1");
//======== panel6 ========
//======== panel8 ========
{
panel6.setBorder(new TitledBorder("JSlider Control"));
panel6.setLayout(new MigLayout(
panel8.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");
//======== panel6 ========
{
panel6.setBorder(new TitledBorder("JSlider Control"));
panel6.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]",
// rows
"[]0" +
"[]0" +
"[]0" +
"[]"));
//---- sliderPaintTicksCheckBox ----
sliderPaintTicksCheckBox.setText("ticks");
sliderPaintTicksCheckBox.addActionListener(e -> sliderPaintTicksChanged());
panel6.add(sliderPaintTicksCheckBox, "cell 0 0");
//---- sliderPaintTrackCheckBox ----
sliderPaintTrackCheckBox.setText("track");
sliderPaintTrackCheckBox.setSelected(true);
sliderPaintTrackCheckBox.addActionListener(e -> sliderPaintTrackChanged());
panel6.add(sliderPaintTrackCheckBox, "cell 0 0");
//---- sliderPaintLabelsCheckBox ----
sliderPaintLabelsCheckBox.setText("labels");
sliderPaintLabelsCheckBox.addActionListener(e -> sliderPaintLabelsChanged());
panel6.add(sliderPaintLabelsCheckBox, "cell 0 0");
//---- sliderPaintTicksCheckBox ----
sliderPaintTicksCheckBox.setText("ticks");
sliderPaintTicksCheckBox.addActionListener(e -> sliderPaintTicksChanged());
panel6.add(sliderPaintTicksCheckBox, "cell 0 0");
//---- sliderInvertedCheckBox ----
sliderInvertedCheckBox.setText("inverted");
sliderInvertedCheckBox.addActionListener(e -> sliderInvertedChanged());
panel6.add(sliderInvertedCheckBox, "cell 0 1");
//---- sliderPaintLabelsCheckBox ----
sliderPaintLabelsCheckBox.setText("labels");
sliderPaintLabelsCheckBox.addActionListener(e -> sliderPaintLabelsChanged());
panel6.add(sliderPaintLabelsCheckBox, "cell 0 0");
//---- sliderSnapToTicksCheckBox ----
sliderSnapToTicksCheckBox.setText("snap to ticks");
sliderSnapToTicksCheckBox.addActionListener(e -> sliderSnapToTicksChanged());
panel6.add(sliderSnapToTicksCheckBox, "cell 0 1");
//---- sliderInvertedCheckBox ----
sliderInvertedCheckBox.setText("inverted");
sliderInvertedCheckBox.addActionListener(e -> sliderInvertedChanged());
panel6.add(sliderInvertedCheckBox, "cell 0 1");
//---- majorTickSpacingSpinner ----
majorTickSpacingSpinner.setModel(new SpinnerNumberModel(50, 0, 100, 5));
majorTickSpacingSpinner.addChangeListener(e -> majorThickSpacingChanged());
panel6.add(majorTickSpacingSpinner, "cell 0 2");
//---- sliderSnapToTicksCheckBox ----
sliderSnapToTicksCheckBox.setText("snap to ticks");
sliderSnapToTicksCheckBox.addActionListener(e -> sliderSnapToTicksChanged());
panel6.add(sliderSnapToTicksCheckBox, "cell 0 1");
//---- minorTickSpacingSpinner ----
minorTickSpacingSpinner.setModel(new SpinnerNumberModel(10, 0, 100, 5));
minorTickSpacingSpinner.addChangeListener(e -> minorThickSpacingChanged());
panel6.add(minorTickSpacingSpinner, "cell 0 2");
//---- 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");
//---- sliderValueLabel ----
sliderValueLabel.setText("slider value");
panel6.add(sliderValueLabel, "cell 0 3");
}
panel8.add(panel6, "cell 0 0 1 2,grow");
//======== panel7 ========
{
panel7.setBorder(new TitledBorder("JProgressBar Control"));
panel7.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]" +
"[fill]",
// rows
"[]0" +
"[]"));
//---- 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");
}
panel8.add(panel7, "cell 0 2 1 2,grow");
}
add(panel6, "cell 4 19 1 2,grow");
add(panel8, "cell 4 19 1 4");
//---- sliderLabel2 ----
sliderLabel2.setText("baseline");
@@ -1387,35 +1447,6 @@ public class FlatComponentsTest
progressBar2.setValue(60);
add(progressBar2, "cell 1 21 3 1,growx");
//======== panel7 ========
{
panel7.setBorder(new TitledBorder("JProgressBar Control"));
panel7.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]" +
"[fill]",
// rows
"[]0" +
"[]"));
//---- 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:");
add(toolTipLabel, "cell 0 22");
@@ -1579,13 +1610,14 @@ public class FlatComponentsTest
private JCheckBox sliderSnapToTicksCheckBox;
private JSpinner majorTickSpacingSpinner;
private JSpinner minorTickSpacingSpinner;
private JLabel sliderValueLabel;
private JCheckBox indeterminateCheckBox;
private JCheckBox squareCheckBox;
private JCheckBox largeHeightCheckBox;
private JSlider slider3;
private JSlider slider5;
private FlatProgressBar progressBar1;
private FlatProgressBar progressBar2;
private JCheckBox indeterminateCheckBox;
private JCheckBox squareCheckBox;
private JCheckBox largeHeightCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class TestDefaultButton --------------------------------------------

View File

@@ -1158,84 +1158,142 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[]0[]0[]"
"$rowConstraints": "[][][][]"
"$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 ) )
name: "panel8"
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[]0[]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"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "sliderValueLabel"
"text": "slider value"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
"value": "cell 0 0 1 2,grow"
} )
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 ) )
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 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"
"value": "cell 0 2 1 2,grow"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 19 1 2,grow"
"value": "cell 4 19 1 4"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "sliderLabel2"
@@ -1296,46 +1354,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 21 3 1,growx"
} )
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 1 2,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolTipLabel"
"text": "JToolTip:"