mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-07 22:40:53 +03:00
AnimatedIcon added (for future animations) (issue #66)
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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
|
||||||
|
*
|
||||||
|
* https://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.icons;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for animated icons that scales width and height, creates and initializes
|
||||||
|
* a scaled graphics context for icon painting.
|
||||||
|
* <p>
|
||||||
|
* Subclasses do not need to scale icon painting.
|
||||||
|
* <p>
|
||||||
|
* This class does not store any state information (needed for animation) in its instance.
|
||||||
|
* Instead a client property is set on the painted component.
|
||||||
|
* This makes it possible to use a share icon instance for multiple components.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public abstract class FlatAnimatedIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
implements AnimatedIcon
|
||||||
|
{
|
||||||
|
public FlatAnimatedIcon( int width, int height, Color color ) {
|
||||||
|
super( width, height, color );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
|
super.paintIcon( c, g, x, y );
|
||||||
|
AnimatedIcon.AnimationSupport.saveIconLocation( this, c, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
AnimatedIcon.AnimationSupport.paintIcon( this, c, g, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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
|
||||||
|
*
|
||||||
|
* https://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.util;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import javax.swing.Icon;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import com.formdev.flatlaf.util.Animator.Interpolator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon that automatically animates painting on component value changes.
|
||||||
|
* <p>
|
||||||
|
* {@link #getValue(Component)} returns the value of the component.
|
||||||
|
* If the value changes, then {@link #paintIconAnimated(Component, Graphics, int, int, float)}
|
||||||
|
* is invoked multiple times with animated value (from old value to new value).
|
||||||
|
* <p>
|
||||||
|
* Example for an animated icon:
|
||||||
|
* <pre>
|
||||||
|
* private class AnimatedMinimalTestIcon
|
||||||
|
* implements AnimatedIcon
|
||||||
|
* {
|
||||||
|
* @Override public int getIconWidth() { return 100; }
|
||||||
|
* @Override public int getIconHeight() { return 20; }
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||||
|
* int w = getIconWidth();
|
||||||
|
* int h = getIconHeight();
|
||||||
|
*
|
||||||
|
* g.setColor( Color.red );
|
||||||
|
* g.drawRect( x, y, w - 1, h - 1 );
|
||||||
|
* g.fillRect( x, y, Math.round( w * animatedValue ), h );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* public float getValue( Component c ) {
|
||||||
|
* return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // sample usage
|
||||||
|
* JCheckBox checkBox = new JCheckBox( "test" );
|
||||||
|
* checkBox.setIcon( new AnimatedMinimalTestIcon() );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Animation works only if the component passed to {@link #paintIcon(Component, Graphics, int, int)}
|
||||||
|
* is a instance of {@link JComponent}.
|
||||||
|
* A client property is set on the component to store the animation state.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public interface AnimatedIcon
|
||||||
|
extends Icon
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
|
AnimationSupport.paintIcon( this, c, g, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints the icon for the given animated value.
|
||||||
|
*
|
||||||
|
* @param c the component that this icon belongs to
|
||||||
|
* @param g the graphics context
|
||||||
|
* @param x the x coordinate of the icon
|
||||||
|
* @param y the y coordinate of the icon
|
||||||
|
* @param animatedValue the animated value, which is either equal to what {@link #getValue(Component)}
|
||||||
|
* returned, or somewhere between the previous value and the latest value
|
||||||
|
* that {@link #getValue(Component)} returned
|
||||||
|
*/
|
||||||
|
void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the component.
|
||||||
|
* <p>
|
||||||
|
* This can be any value and depends on the component.
|
||||||
|
* If the value changes, then this class animates from the old value to the new one.
|
||||||
|
* <p>
|
||||||
|
* For a toggle button this could be {@code 0} for off and {@code 1} for on.
|
||||||
|
*/
|
||||||
|
float getValue( Component c );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether animation is enabled for this icon (default is {@code true}).
|
||||||
|
*/
|
||||||
|
default boolean isAnimationEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the duration of the animation in milliseconds (default is 150).
|
||||||
|
*/
|
||||||
|
default int getAnimationDuration() {
|
||||||
|
return 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resolution of the animation in milliseconds (default is 10).
|
||||||
|
* Resolution is the amount of time between timing events.
|
||||||
|
*/
|
||||||
|
default int getAnimationResolution() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the interpolator for the animation.
|
||||||
|
* Default is {@link CubicBezierEasing#STANDARD_EASING}.
|
||||||
|
*/
|
||||||
|
default Interpolator getAnimationInterpolator() {
|
||||||
|
return CubicBezierEasing.STANDARD_EASING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the client property key used to store the animation support.
|
||||||
|
*/
|
||||||
|
default Object getClientPropertyKey() {
|
||||||
|
return getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class AnimationSupport ---------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animation support class that stores the animation state and implements the animation.
|
||||||
|
*/
|
||||||
|
class AnimationSupport
|
||||||
|
{
|
||||||
|
private float startValue;
|
||||||
|
private float targetValue;
|
||||||
|
private float animatedValue;
|
||||||
|
private float fraction;
|
||||||
|
|
||||||
|
private Animator animator;
|
||||||
|
|
||||||
|
// last x,y coordinates of the icon needed to repaint while animating
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
|
||||||
|
public static void paintIcon( AnimatedIcon icon, Component c, Graphics g, int x, int y ) {
|
||||||
|
if( !isAnimationEnabled( icon, c ) ) {
|
||||||
|
// paint without animation if animation is disabled or
|
||||||
|
// component is not a JComponent and therefore does not support
|
||||||
|
// client properties, which are required to keep animation state
|
||||||
|
paintIconImpl( icon, c, g, x, y, null );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JComponent jc = (JComponent) c;
|
||||||
|
Object key = icon.getClientPropertyKey();
|
||||||
|
AnimationSupport as = (AnimationSupport) jc.getClientProperty( key );
|
||||||
|
if( as == null ) {
|
||||||
|
// painted first time --> do not animate, but remember current component value
|
||||||
|
as = new AnimationSupport();
|
||||||
|
as.startValue = as.targetValue = as.animatedValue = icon.getValue( c );
|
||||||
|
as.x = x;
|
||||||
|
as.y = y;
|
||||||
|
jc.putClientProperty( key, as );
|
||||||
|
} else {
|
||||||
|
// get component value
|
||||||
|
float value = icon.getValue( c );
|
||||||
|
|
||||||
|
if( value != as.targetValue ) {
|
||||||
|
// value changed --> (re)start animation
|
||||||
|
|
||||||
|
if( as.animator == null ) {
|
||||||
|
// create animator
|
||||||
|
AnimationSupport as2 = as;
|
||||||
|
as.animator = new Animator( icon.getAnimationDuration(), fraction -> {
|
||||||
|
// check whether component was removed while animation is running
|
||||||
|
if( !c.isDisplayable() ) {
|
||||||
|
as2.animator.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute animated value
|
||||||
|
as2.animatedValue = as2.startValue + ((as2.targetValue - as2.startValue) * fraction);
|
||||||
|
as2.fraction = fraction;
|
||||||
|
|
||||||
|
// repaint icon
|
||||||
|
c.repaint( as2.x, as2.y, icon.getIconWidth(), icon.getIconHeight() );
|
||||||
|
}, () -> {
|
||||||
|
as2.startValue = as2.animatedValue = as2.targetValue;
|
||||||
|
as2.animator = null;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( as.animator.isRunning() ) {
|
||||||
|
// if animation is still running, restart it from the current
|
||||||
|
// animated value to the new target value with reduced duration
|
||||||
|
as.animator.cancel();
|
||||||
|
int duration2 = (int) (icon.getAnimationDuration() * as.fraction);
|
||||||
|
if( duration2 > 0 )
|
||||||
|
as.animator.setDuration( duration2 );
|
||||||
|
as.startValue = as.animatedValue;
|
||||||
|
} else {
|
||||||
|
// new animation
|
||||||
|
as.animator.setDuration( icon.getAnimationDuration() );
|
||||||
|
as.animator.setResolution( icon.getAnimationResolution() );
|
||||||
|
as.animator.setInterpolator( icon.getAnimationInterpolator() );
|
||||||
|
|
||||||
|
as.animatedValue = as.startValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
as.targetValue = value;
|
||||||
|
as.animator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
as.x = x;
|
||||||
|
as.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
paintIconImpl( icon, c, g, x, y, as );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void paintIconImpl( AnimatedIcon icon, Component c, Graphics g, int x, int y, AnimationSupport as ) {
|
||||||
|
float value = (as != null) ? as.animatedValue : icon.getValue( c );
|
||||||
|
icon.paintIconAnimated( c, g, x, y, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAnimationEnabled( AnimatedIcon icon, Component c ) {
|
||||||
|
return Animator.useAnimation() && icon.isAnimationEnabled() && c instanceof JComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveIconLocation( AnimatedIcon icon, Component c, int x, int y ) {
|
||||||
|
if( !isAnimationEnabled( icon, c ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
AnimationSupport as = (AnimationSupport) ((JComponent)c).getClientProperty( icon.getClientPropertyKey() );
|
||||||
|
if( as != null ) {
|
||||||
|
as.x = x;
|
||||||
|
as.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,38 @@ public class ColorFunctions
|
|||||||
: value);
|
: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a color that is a mixture of two colors.
|
||||||
|
*
|
||||||
|
* @param color1 first color
|
||||||
|
* @param color2 second color
|
||||||
|
* @param weight the weight (in range 0-1) to mix the two colors.
|
||||||
|
* Larger weight uses more of first color, smaller weight more of second color.
|
||||||
|
* @return mixture of colors
|
||||||
|
*/
|
||||||
|
public static Color mix( Color color1, Color color2, float weight ) {
|
||||||
|
if( weight >= 1 )
|
||||||
|
return color1;
|
||||||
|
if( weight <= 0 )
|
||||||
|
return color2;
|
||||||
|
|
||||||
|
int r1 = color1.getRed();
|
||||||
|
int g1 = color1.getGreen();
|
||||||
|
int b1 = color1.getBlue();
|
||||||
|
int a1 = color1.getAlpha();
|
||||||
|
|
||||||
|
int r2 = color2.getRed();
|
||||||
|
int g2 = color2.getGreen();
|
||||||
|
int b2 = color2.getBlue();
|
||||||
|
int a2 = color2.getAlpha();
|
||||||
|
|
||||||
|
return new Color(
|
||||||
|
Math.round( r2 + ((r1 - r2) * weight) ),
|
||||||
|
Math.round( g2 + ((g1 - g2) * weight) ),
|
||||||
|
Math.round( b2 + ((b1 - b2) * weight) ),
|
||||||
|
Math.round( a2 + ((a1 - a2) * weight) ) );
|
||||||
|
}
|
||||||
|
|
||||||
//---- interface ColorFunction --------------------------------------------
|
//---- interface ColorFunction --------------------------------------------
|
||||||
|
|
||||||
public interface ColorFunction {
|
public interface ColorFunction {
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ package com.formdev.flatlaf.util;
|
|||||||
public class CubicBezierEasing
|
public class CubicBezierEasing
|
||||||
implements Animator.Interpolator
|
implements Animator.Interpolator
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Standard easing as specified in Material design (0.4, 0, 0.2, 1).
|
||||||
|
*
|
||||||
|
* @see <a href="https://material.io/design/motion/speed.html#easing">https://material.io/design/motion/speed.html#easing</a>
|
||||||
|
*/
|
||||||
|
public static final CubicBezierEasing STANDARD_EASING = new CubicBezierEasing( 0.4f, 0f, 0.2f, 1f );
|
||||||
|
|
||||||
// common cubic-bezier easing functions (same as in CSS)
|
// common cubic-bezier easing functions (same as in CSS)
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function
|
||||||
public static final CubicBezierEasing EASE = new CubicBezierEasing( 0.25f, 0.1f, 0.25f, 1f );
|
public static final CubicBezierEasing EASE = new CubicBezierEasing( 0.25f, 0.1f, 0.25f, 1f );
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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
|
||||||
|
*
|
||||||
|
* https://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;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import javax.swing.*;
|
||||||
|
import com.formdev.flatlaf.icons.FlatAnimatedIcon;
|
||||||
|
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatAnimatedIconTest
|
||||||
|
extends FlatTestPanel
|
||||||
|
{
|
||||||
|
public static void main( String[] args ) {
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
FlatTestFrame frame = FlatTestFrame.create( args, "FlatAnimatedIconTest" );
|
||||||
|
frame.showFrame( FlatAnimatedIconTest::new );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatAnimatedIconTest() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
AnimatedRadioButtonIcon radioIcon = new AnimatedRadioButtonIcon();
|
||||||
|
radioButton1.setIcon( radioIcon );
|
||||||
|
radioButton2.setIcon( radioIcon );
|
||||||
|
radioButton3.setIcon( radioIcon );
|
||||||
|
|
||||||
|
checkBox1.setIcon( new AnimatedSwitchIcon() );
|
||||||
|
checkBox2.setIcon( new AnimatedMinimalTestIcon() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
|
radioButton1 = new JRadioButton();
|
||||||
|
radioButton2 = new JRadioButton();
|
||||||
|
radioButton3 = new JRadioButton();
|
||||||
|
checkBox1 = new JCheckBox();
|
||||||
|
checkBox2 = new JCheckBox();
|
||||||
|
durationLabel = new JLabel();
|
||||||
|
durationField = new JSpinner();
|
||||||
|
|
||||||
|
//======== this ========
|
||||||
|
setLayout(new MigLayout(
|
||||||
|
"insets dialog,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[]para" +
|
||||||
|
"[fill]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[grow]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- radioButton1 ----
|
||||||
|
radioButton1.setText("radio 1");
|
||||||
|
radioButton1.setSelected(true);
|
||||||
|
add(radioButton1, "cell 0 0");
|
||||||
|
|
||||||
|
//---- radioButton2 ----
|
||||||
|
radioButton2.setText("radio 2");
|
||||||
|
add(radioButton2, "cell 0 1");
|
||||||
|
|
||||||
|
//---- radioButton3 ----
|
||||||
|
radioButton3.setText("radio 3");
|
||||||
|
add(radioButton3, "cell 0 2");
|
||||||
|
|
||||||
|
//---- checkBox1 ----
|
||||||
|
checkBox1.setText("switch");
|
||||||
|
add(checkBox1, "cell 0 3");
|
||||||
|
|
||||||
|
//---- checkBox2 ----
|
||||||
|
checkBox2.setText("minimal");
|
||||||
|
add(checkBox2, "cell 0 4");
|
||||||
|
|
||||||
|
//---- durationLabel ----
|
||||||
|
durationLabel.setText("Duration:");
|
||||||
|
add(durationLabel, "cell 0 6 2 1");
|
||||||
|
|
||||||
|
//---- durationField ----
|
||||||
|
durationField.setModel(new SpinnerNumberModel(200, 100, null, 50));
|
||||||
|
add(durationField, "cell 0 6 2 1");
|
||||||
|
|
||||||
|
//---- buttonGroup1 ----
|
||||||
|
ButtonGroup buttonGroup1 = new ButtonGroup();
|
||||||
|
buttonGroup1.add(radioButton1);
|
||||||
|
buttonGroup1.add(radioButton2);
|
||||||
|
buttonGroup1.add(radioButton3);
|
||||||
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
|
private JRadioButton radioButton1;
|
||||||
|
private JRadioButton radioButton2;
|
||||||
|
private JRadioButton radioButton3;
|
||||||
|
private JCheckBox checkBox1;
|
||||||
|
private JCheckBox checkBox2;
|
||||||
|
private JLabel durationLabel;
|
||||||
|
private JSpinner durationField;
|
||||||
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
|
||||||
|
//---- class AnimatedRadioButtonIcon --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experimental radio button icon that:
|
||||||
|
* - fades icon color from off to on color
|
||||||
|
* - animates size of center dot from zero to full size
|
||||||
|
*/
|
||||||
|
private class AnimatedRadioButtonIcon
|
||||||
|
extends FlatAnimatedIcon
|
||||||
|
{
|
||||||
|
private static final int SIZE = 16;
|
||||||
|
private static final int BORDER_SIZE = 2;
|
||||||
|
private static final int DOT_SIZE = 8;
|
||||||
|
|
||||||
|
private final Color offColor = Color.lightGray;
|
||||||
|
private final Color onColor = Color.red;
|
||||||
|
|
||||||
|
public AnimatedRadioButtonIcon() {
|
||||||
|
super( SIZE, SIZE, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||||
|
Color color = ColorFunctions.mix( onColor, offColor, animatedValue );;
|
||||||
|
|
||||||
|
// border
|
||||||
|
g.setColor( color );
|
||||||
|
g.fillOval( 0, 0, SIZE, SIZE );
|
||||||
|
|
||||||
|
// background
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
int bwh = SIZE - (BORDER_SIZE * 2);
|
||||||
|
g.fillOval( BORDER_SIZE, BORDER_SIZE, bwh, bwh );
|
||||||
|
|
||||||
|
// dot
|
||||||
|
float dotDiameter = DOT_SIZE * animatedValue;
|
||||||
|
float xy = (SIZE - dotDiameter) / 2f;
|
||||||
|
g.setColor( color );
|
||||||
|
((Graphics2D)g).fill( new Ellipse2D.Float( xy, xy, dotDiameter, dotDiameter ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getValue( Component c ) {
|
||||||
|
return ((JRadioButton)c).isSelected() ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAnimationDuration() {
|
||||||
|
return (Integer) durationField.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class AnimatedSwitchIcon -------------------------------------------
|
||||||
|
|
||||||
|
public class AnimatedSwitchIcon
|
||||||
|
extends FlatAnimatedIcon
|
||||||
|
{
|
||||||
|
private final Color offColor = Color.lightGray;
|
||||||
|
private final Color onColor = Color.red;
|
||||||
|
|
||||||
|
public AnimatedSwitchIcon() {
|
||||||
|
super( 28, 16, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||||
|
Color color = ColorFunctions.mix( onColor, offColor, animatedValue );;
|
||||||
|
|
||||||
|
g.setColor( color );
|
||||||
|
g.fillRoundRect( x, y, width, height, height, height );
|
||||||
|
|
||||||
|
int thumbSize = height - 4;
|
||||||
|
int thumbX = x + 2 + Math.round( (width - 4 - thumbSize) * animatedValue );
|
||||||
|
int thumbY = y + 2;
|
||||||
|
g.setColor( Color.white );
|
||||||
|
g.fillOval( thumbX, thumbY, thumbSize, thumbSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getValue( Component c ) {
|
||||||
|
return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAnimationDuration() {
|
||||||
|
return (Integer) durationField.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class AnimatedMinimalTestIcon --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal example for an animated icon.
|
||||||
|
*/
|
||||||
|
private class AnimatedMinimalTestIcon
|
||||||
|
implements AnimatedIcon
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||||
|
int w = getIconWidth();
|
||||||
|
int h = getIconHeight();
|
||||||
|
|
||||||
|
g.setColor( Color.red );
|
||||||
|
g.drawRect( x, y, w - 1, h - 1 );
|
||||||
|
g.fillRect( x, y, Math.round( w * animatedValue ), h );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getValue( Component c ) {
|
||||||
|
return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAnimationDuration() {
|
||||||
|
return (Integer) durationField.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" 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": "insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[]para[fill]"
|
||||||
|
"$rowConstraints": "[][][]para[][][grow][]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "radioButton1"
|
||||||
|
"text": "radio 1"
|
||||||
|
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||||
|
"selected": true
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "radioButton2"
|
||||||
|
"text": "radio 2"
|
||||||
|
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "radioButton3"
|
||||||
|
"text": "radio 3"
|
||||||
|
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "checkBox1"
|
||||||
|
"text": "switch"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "checkBox2"
|
||||||
|
"text": "minimal"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "durationLabel"
|
||||||
|
"text": "Duration:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6 2 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSpinner" ) {
|
||||||
|
name: "durationField"
|
||||||
|
"model": new javax.swing.SpinnerNumberModel {
|
||||||
|
minimum: 100
|
||||||
|
stepSize: 50
|
||||||
|
value: 200
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6 2 1"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 415, 350 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "buttonGroup1"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 360 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user