TriStateCheckBox component added

This commit is contained in:
Karl Tauber
2019-10-24 12:36:40 +02:00
parent 1b0c2687c8
commit 7f43b3003c
10 changed files with 330 additions and 3 deletions

View File

@@ -1,6 +1,13 @@
FlatLaf Change Log
==================
## Unreleased
- CheckBox: Support painting a third state (set client property
"JButton.selectedState" to "indeterminate").
- `TriStateCheckBox` component added (see [FlatLaf Extras](flatlaf-extras)).
## 0.16
- Made some fixes for right-to-left support in ComboBox, Slider and ToolTip.

View File

@@ -27,6 +27,9 @@ public interface FlatClientProperties
String BUTTON_TYPE = "JButton.buttonType";
String BUTTON_TYPE_HELP = "help";
String SELECTED_STATE = "JButton.selectedState";
String SELECTED_STATE_INDETERMINATE = "indeterminate";
/**
* Checks whether a client property of a component has the given value.
*/

View File

@@ -16,12 +16,15 @@
package com.formdev.flatlaf.icons;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
@@ -84,7 +87,9 @@ public class FlatCheckBoxIcon
@Override
protected void paintIcon( Component c, Graphics2D g2 ) {
boolean selected = (c instanceof AbstractButton) ? ((AbstractButton)c).isSelected() : false;
boolean indeterminate = c instanceof JComponent && clientPropertyEquals( (JComponent) c, SELECTED_STATE, SELECTED_STATE_INDETERMINATE );
boolean selected = indeterminate || (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
System.out.println( "icon "+indeterminate+" "+selected );
// paint focused border
if( c.hasFocus() && focusWidth > 0 ) {
@@ -111,8 +116,11 @@ public class FlatCheckBoxIcon
paintBackground( g2 );
// paint checkmark
if( selected ) {
if( selected || indeterminate ) {
g2.setColor( c.isEnabled() ? checkmarkColor : disabledCheckmarkColor );
if( indeterminate )
paintIndeterminate( g2 );
else
paintCheckmark( g2 );
}
}
@@ -140,4 +148,8 @@ public class FlatCheckBoxIcon
g2.setStroke( new BasicStroke( 1.9f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
g2.draw( path );
}
protected void paintIndeterminate( Graphics2D g2 ) {
g2.fill( new RoundRectangle2D.Float( 3.75f, 5.75f, 8.5f, 2.5f, 2f, 2f ) );
}
}

13
flatlaf-extras/README.md Normal file
View File

@@ -0,0 +1,13 @@
FlatLaf Extras
==============
This sub-project provides some additional components and classes:
- [TriStateCheckBox](flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/TriStateCheckBox.java):
A tri-state check box.
Download
--------
Not yet available.

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
version = rootProject.version
plugins {
`java-library`
}
dependencies {
implementation( project( ":flatlaf-core" ) )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.extras;
import java.awt.event.ItemEvent;
import javax.swing.JCheckBox;
/**
* A tri-state check box.
*
* To display the third state, this component requires an LaF that supports painting
* the indeterminate state if client property {@code "JButton.selectedState"} has the
* value {@code "indeterminate"}.
*
* FlatLaf and Mac Aqua LaF support the third state.
*
* @author Karl Tauber
*/
public class TriStateCheckBox
extends JCheckBox
{
public enum State { INDETERMINATE, SELECTED, UNSELECTED }
private State state;
private boolean thirdStateEnabled = true;
public TriStateCheckBox() {
this( null );
}
public TriStateCheckBox( String text ) {
this( text, State.INDETERMINATE );
}
public TriStateCheckBox( String text, State initialState ) {
super( text );
setModel( new ToggleButtonModel() {
@Override
public boolean isSelected() {
return state != State.UNSELECTED;
}
@Override
public void setSelected( boolean b ) {
switch( state ) {
case INDETERMINATE: setState( State.SELECTED ); break;
case SELECTED: setState( State.UNSELECTED ); break;
case UNSELECTED: setState( thirdStateEnabled ? State.INDETERMINATE : State.SELECTED ); break;
}
fireStateChanged();
fireItemStateChanged( new ItemEvent( this, ItemEvent.ITEM_STATE_CHANGED, this,
isSelected() ? ItemEvent.SELECTED : ItemEvent.DESELECTED ) );
}
} );
setState( initialState );
}
public State getState() {
return state;
}
public void setState( State state ) {
if( this.state == state )
return;
State oldState = this.state;
this.state = state;
putClientProperty( "JButton.selectedState", state == State.INDETERMINATE ? "indeterminate" : null );
firePropertyChange( "state", oldState, state );
repaint();
}
public boolean isThirdStateEnabled() {
return thirdStateEnabled;
}
public void setThirdStateEnabled( boolean thirdStateEnabled ) {
this.thirdStateEnabled = thirdStateEnabled;
if( state == State.INDETERMINATE )
setState( State.UNSELECTED );
}
@Override
public void setSelected( boolean b ) {
setState( b ? State.SELECTED : State.UNSELECTED );
}
}

View File

@@ -22,6 +22,7 @@ plugins {
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( project( ":flatlaf-extras" ) )
implementation( project( ":flatlaf-swingx" ) )
implementation( "com.miglayout:miglayout-swing:5.2" )

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.testing.extras;
import javax.swing.*;
import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.testing.*;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatExtrasTest
extends FlatTestPanel
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatExtrasTest" );
frame.showFrame( new FlatExtrasTest() );
} );
}
public FlatExtrasTest() {
initComponents();
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
triStateLabel2.setText( triStateCheckBox2.getState().toString() );
}
private void triStateCheckBox1Changed() {
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
}
private void triStateCheckBox2Changed() {
triStateLabel2.setText( triStateCheckBox2.getState().toString() );
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel();
triStateCheckBox1 = new TriStateCheckBox();
triStateLabel1 = new JLabel();
triStateCheckBox2 = new TriStateCheckBox();
triStateLabel2 = new JLabel();
//======== this ========
setLayout(new MigLayout(
"hidemode 3,ltr",
// columns
"[]" +
"[]" +
"[left]",
// rows
"[]" +
"[]"));
//---- label1 ----
label1.setText("TriStateCheckBox:");
add(label1, "cell 0 0");
//---- triStateCheckBox1 ----
triStateCheckBox1.setText("three states");
triStateCheckBox1.addActionListener(e -> triStateCheckBox1Changed());
add(triStateCheckBox1, "cell 1 0");
//---- triStateLabel1 ----
triStateLabel1.setText("text");
add(triStateLabel1, "cell 2 0");
//---- triStateCheckBox2 ----
triStateCheckBox2.setText("third state disabled");
triStateCheckBox2.setThirdStateEnabled(false);
triStateCheckBox2.addActionListener(e -> triStateCheckBox2Changed());
add(triStateCheckBox2, "cell 1 1");
//---- triStateLabel2 ----
triStateLabel2.setText("text");
add(triStateLabel2, "cell 2 1");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JLabel label1;
private TriStateCheckBox triStateCheckBox1;
private JLabel triStateLabel1;
private TriStateCheckBox triStateCheckBox2;
private JLabel triStateLabel2;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,50 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3,ltr"
"$columnConstraints": "[][][left]"
"$rowConstraints": "[][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "TriStateCheckBox:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "triStateCheckBox1"
"text": "three states"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "triStateCheckBox1Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "triStateLabel1"
"text": "text"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "triStateCheckBox2"
"text": "third state disabled"
"thirdStateEnabled": false
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "triStateCheckBox2Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "triStateLabel2"
"text": "text"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 400, 300 )
} )
}
}

View File

@@ -17,6 +17,7 @@
rootProject.name = "FlatLaf"
include( "flatlaf-core" )
include( "flatlaf-extras" )
include( "flatlaf-swingx" )
include( "flatlaf-demo" )
include( "flatlaf-testing" )