Compare commits

..

32 Commits
0.20 ... 0.22

Author SHA1 Message Date
Karl Tauber
2399e54a4b release 0.22 2019-12-18 12:28:08 +01:00
Karl Tauber
aea5e8eb16 Demo: bottom horizontal slider bound to the progress bars 2019-12-18 12:21:38 +01:00
Karl Tauber
a3a60c1c4b ProgressBar: reduced thickness from 6 to 4 (as in IntelliJ and Windows 10) 2019-12-18 11:44:34 +01:00
Karl Tauber
c141cb6c6c CheckBox and RadioButton: fixed cut off outer focus border if checkbox/radiobutton border was explicitly set to a EmptyBorder 2019-12-17 23:24:38 +01:00
Karl Tauber
62765ab6ca TextComponent: support placeholder text that is displayed if text field is empty (set client property "JTextField.placeholderText" to a string) 2019-12-17 18:08:45 +01:00
Karl Tauber
e4f7fed523 TextComponent: scale caret width on HiDPI screens when running on Java 8 2019-12-17 17:34:54 +01:00
Karl Tauber
bf8cc268cc on Mac show mnemonics only when Ctrl and Alt keys are pressed (issue #4) 2019-12-17 11:35:16 +01:00
Karl Tauber
8450e74832 TabbedPane: support separators between tabs (TabbedPane.showTabSeparators) 2019-12-16 20:40:29 +01:00
Karl Tauber
475b258e4a Button: enabled Button.defaultButtonFollowsFocus on Windows, which allows pressing focused button with <kbd>Enter</kbd> key (as in Windows LaF) 2019-12-16 18:11:48 +01:00
Karl Tauber
f20803ae57 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`
2019-12-16 17:39:46 +01:00
Karl Tauber
3fcb17931a fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is zero (default in "Flat Light" and "Flat Dark" themes) 2019-12-15 11:36:24 +01:00
Karl Tauber
736c7b8377 CheckBox: changed CheckBox.arc from radius to diameter to be consistent with Button.arc and Component.arc 2019-12-14 23:36:22 +01:00
Karl Tauber
05743e2d8b FlatUIUtils: renamed and documented component painting methods 2019-12-14 23:17:11 +01:00
Karl Tauber
6cd2c7f26d InternalFrame: test application implemented (issue #11) 2019-12-14 11:57:07 +01:00
Karl Tauber
469e5bd179 ToggleButton: removed "ToggleButton.arc" because it was only used for the background, but not for the border, which is painted in FlatButtonBorder 2019-12-14 00:05:47 +01:00
Karl Tauber
dbeb3f04e7 UI inspector:
- fixed wrong detection of components under mouse location if window contains a menubar
- fixed positioning of tooltip in bottom and right window area to avoid that the tooltip overlaps the inspected component
2019-12-13 23:49:49 +01:00
Karl Tauber
e9b17ac24a UI inspector: support using it in any application 2019-12-13 23:24:10 +01:00
Karl Tauber
65fbcedaa4 TabbedPane: support background color for selected tabs 2019-12-13 23:14:41 +01:00
Karl Tauber
c4183ada11 ScrollPane and FlatSpinner: made getHandler() methods private 2019-12-11 21:58:39 +01:00
Karl Tauber
27f9614633 release 0.21 2019-12-08 12:38:45 +01:00
Karl Tauber
2211cc5596 fixed Swing system colors in dark themes 2019-12-08 10:21:07 +01:00
Karl Tauber
46f0393648 UIDefaultsLoader:
- support `{instance}com.myapp.MyClass` to instantiate any public class with public no-arg constructor
- support `{class}com.myapp.MyClass`
- support loading addon classes from different classloaders (e.g. in NetBeans)
2019-12-07 17:53:59 +01:00
Karl Tauber
b4c1a97687 IntelliJ Themes:
- accept colors starting with two `#` as valid colors because IntelliJ IDEA does it too
- fixed wrong error message when a color reference is missing

(issue #26)
2019-12-06 11:13:50 +01:00
Karl Tauber
adcef385b0 FlatClientProperties: added javadoc comments 2019-12-03 11:33:12 +01:00
Karl Tauber
48e38b2855 ScrollBar: show decrease/increase arrow buttons if client property "JScrollBar.showButtons" is set to true on JScrollPane or JScrollBar (issue #25) 2019-12-03 10:53:39 +01:00
Karl Tauber
2cc8327a08 ScrollPane: paint disabled border if view component (e.g. JTextPane) is disabled 2019-12-01 18:23:30 +01:00
Karl Tauber
404e80082c Button: fixed help button styling in IntelliJ platform themes 2019-12-01 17:53:10 +01:00
Karl Tauber
3fbc21347a Demo: restore last used theme on startup 2019-12-01 13:10:38 +01:00
Karl Tauber
d76f0e2241 moved code that fixes color of links in HTML text from FlatLaf.getDefaults() to FlatLaf.initialize() and invoke it only once (for the case that getDefaults() is invoked from 3rd party code) 2019-11-30 23:23:34 +01:00
Karl Tauber
e5fcc59805 Button: optionally support shadows for improved compatibility with IntelliJ platform themes (e.g. for Material Design Dark theme) 2019-11-30 19:14:37 +01:00
Karl Tauber
de82dac873 Button: optionally support gradient border and gradient background for improved compatibility with IntelliJ platform themes (e.g. Vuesion and Spacegray themes) 2019-11-30 17:58:40 +01:00
Karl Tauber
a14ef72177 FlatLaf.isNativeLookAndFeel() now returns false 2019-11-30 15:41:27 +01:00
60 changed files with 2038 additions and 447 deletions

View File

@@ -1,6 +1,46 @@
FlatLaf Change Log
==================
## 0.22
- TextComponent: Support placeholder text that is displayed if text field is
empty (set client property "JTextField.placeholderText" to a string).
- TextComponent: Scale caret width on HiDPI screens when running on Java 8.
- 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`.
- ProgressBar: Reduced thickness from 6 to 4.
- TabbedPane: Support background color for selected tabs
(`TabbedPane.selectedBackground`) and separators between tabs
(`TabbedPane.showTabSeparators`).
- CheckBox: changed `CheckBox.arc` from radius to diameter to be consistent with
`Button.arc` and `Component.arc`
- Button: Enabled `Button.defaultButtonFollowsFocus` on Windows, which allows
pressing focused button with <kbd>Enter</kbd> key (as in Windows LaF).
- Fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is
zero (default in "Flat Light" and "Flat Dark" themes).
- On Mac show mnemonics only when <kbd>Ctrl</kbd> and <kbd>Alt</kbd> keys are
pressed. (issue #4)
## 0.21
- ScrollBar: Show decrease/increase arrow buttons if client property
"JScrollBar.showButtons" is set to `true` on `JScrollPane` or `JScrollBar`.
(issue #25)
- `FlatLaf.isNativeLookAndFeel()` now returns `false`.
- Button: Optionally support gradient borders, gradient backgrounds and shadows
for improved compatibility with IntelliJ platform themes (e.g. for Vuesion,
Spacegray and Material Design Dark themes).
- Button: Fixed help button styling in IntelliJ platform themes.
- ScrollPane: Paint disabled border if view component (e.g. JTextPane) is
disabled.
- Fixed Swing system colors in dark themes.
## 0.20
- Support using IntelliJ platform themes (.theme.json files).

View File

@@ -45,7 +45,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf
version: 0.20
version: 0.22
Otherwise download `flatlaf-<version>.jar` here:

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
version = "0.20"
version = "0.22"
allprojects {
repositories {

View File

@@ -24,18 +24,83 @@ import javax.swing.JComponent;
*/
public interface FlatClientProperties
{
/**
* Specifies type of a button.
* <p>
* <strong>Component</strong> {@link javax.swing.JButton}<br>
* <strong>Value type</strong> {@link java.lang.String}<br>
* <strong>Allowed Values</strong> {@link BUTTON_TYPE_HELP}
*/
String BUTTON_TYPE = "JButton.buttonType";
/**
* Paint a help button (circle with question mark).
*
* @see #BUTTON_TYPE
*/
String BUTTON_TYPE_HELP = "help";
/**
* Specifies selected state of a checkbox.
* <p>
* <strong>Component</strong> {@link javax.swing.JCheckBox}<br>
* <strong>Value type</strong> {@link java.lang.String}<br>
* <strong>Allowed Values</strong> {@link SELECTED_STATE_INDETERMINATE}
*/
String SELECTED_STATE = "JButton.selectedState";
/**
* Paint an indeterminate state on a checkbox.
*
* @see #SELECTED_STATE
*/
String SELECTED_STATE_INDETERMINATE = "indeterminate";
/**
* Specifies whether the decrease/increase arrow buttons of a scrollbar are shown.
* <p>
* <strong>Component</strong> {@link javax.swing.JScrollBar} or {@link javax.swing.JScrollPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String SCROLL_BAR_SHOW_BUTTONS = "JScrollBar.showButtons";
/**
* Specifies whether separators are shown between tabs.
* <p>
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String TABBED_PANE_SHOW_TAB_SEPARATORS = "JTabbedPane.showTabSeparators";
/**
* Specifies whether a full border is painted around a tabbed pane.
* <p>
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String TABBED_PANE_HAS_FULL_BORDER = "JTabbedPane.hasFullBorder";
/**
* Placeholder text that is only painted if the text field is empty.
* <p>
* <strong>Component</strong> {@link javax.swing.JTextField} or {@link javax.swing.JComboBox}<br>
* <strong>Value type</strong> {@link java.lang.String}
*/
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
/**
* Checks whether a client property of a component has the given value.
*/
static boolean clientPropertyEquals( JComponent c, String key, Object value ) {
return Objects.equals( c.getClientProperty( key ), value );
}
/**
* Checks whether a client property of a component is a boolean and returns its value.
* If the client property is not set, or not a boolean, defaultValue is returned.
*/
static boolean clientPropertyBoolean( JComponent c, String key, boolean defaultValue ) {
Object value = c.getClientProperty( key );
return (value instanceof Boolean) ? (boolean) value : defaultValue;
}
}

View File

@@ -29,6 +29,7 @@ import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.function.Consumer;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
@@ -60,7 +61,9 @@ public abstract class FlatLaf
private PropertyChangeListener desktopPropertyListener;
private KeyEventPostProcessor mnemonicListener;
private static boolean altKeyPressed;
private static boolean showMnemonics;
private Consumer<UIDefaults> postInitialization;
public static boolean install( LookAndFeel newLookAndFeel ) {
try {
@@ -89,7 +92,7 @@ public abstract class FlatLaf
@Override
public boolean isNativeLookAndFeel() {
return true;
return false;
}
@Override
@@ -110,8 +113,7 @@ public abstract class FlatLaf
// add mnemonic listener
mnemonicListener = e -> {
if( e.getKeyCode() == KeyEvent.VK_ALT )
altKeyChanged( e.getID() == KeyEvent.KEY_PRESSED );
checkShowMnemonics( e );
return false;
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( mnemonicListener );
@@ -133,6 +135,18 @@ public abstract class FlatLaf
};
Toolkit.getDefaultToolkit().addPropertyChangeListener( desktopPropertyName, desktopPropertyListener );
}
// Following code should be ideally in initialize(), but needs color from UI defaults.
// Do not move this code to getDefaults() to avoid side effects in the case that
// getDefaults() is directly invoked from 3rd party code. E.g. `new FlatLightLaf().getDefaults()`.
postInitialization = defaults -> {
// update link color in HTML text
Color linkColor = defaults.getColor( "Component.linkColor" );
if( linkColor != null ) {
new HTMLEditorKit().getStyleSheet().addRule(
String.format( "a { color: #%06x; }", linkColor.getRGB() & 0xffffff ) );
}
};
}
@Override
@@ -152,6 +166,7 @@ public abstract class FlatLaf
// restore default link color
new HTMLEditorKit().getStyleSheet().addRule( "a { color: blue; }" );
postInitialization = null;
if( base != null )
base.uninitialize();
@@ -221,11 +236,9 @@ public abstract class FlatLaf
if( useScreenMenuBar )
defaults.put( "MenuBarUI", aquaMenuBarUI );
// update link color in HTML text
Color linkColor = defaults.getColor( "Component.linkColor" );
if( linkColor != null ) {
new HTMLEditorKit().getStyleSheet().addRule(
String.format( "a { color: #%06x; }", linkColor.getRGB() & 0xffffff ) );
if( postInitialization != null ) {
postInitialization.accept( defaults );
postInitialization = null;
}
return defaults;
@@ -269,6 +282,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 ) );
}
/**
@@ -340,14 +356,27 @@ public abstract class FlatLaf
}
public static boolean isShowMnemonics() {
return altKeyPressed || !UIManager.getBoolean( "Component.hideMnemonics" );
return showMnemonics || !UIManager.getBoolean( "Component.hideMnemonics" );
}
private static void altKeyChanged( boolean pressed ) {
if( pressed == altKeyPressed )
private static void checkShowMnemonics( KeyEvent e ) {
int keyCode = e.getKeyCode();
if( SystemInfo.IS_MAC ) {
// Ctrl+Alt keys must be pressed on Mac
if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT )
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED && e.isControlDown() && e.isAltDown() );
} else {
// Alt key must be pressed on Windows and Linux
if( keyCode == KeyEvent.VK_ALT )
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED );
}
}
private static void showMnemonics( boolean show ) {
if( show == showMnemonics )
return;
altKeyPressed = pressed;
showMnemonics = show;
// check whether it is necessary to repaint
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )

View File

@@ -128,6 +128,10 @@ public class IntelliJTheme
defaults.put( "Component.isIntelliJTheme", true );
// enable button shadows
defaults.put( "Button.paintShadow", true );
defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
loadNamedColors( defaults );
// convert Json "ui" structure to UI defaults
@@ -139,6 +143,20 @@ public class IntelliJTheme
applyColorPalette( defaults );
applyCheckBoxColors( defaults );
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
Object helpButtonBackground = defaults.get( "Button.startBackground" );
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
if( helpButtonBackground == null )
helpButtonBackground = defaults.get( "Button.background" );
if( helpButtonBorderColor == null )
helpButtonBorderColor = defaults.get( "Button.borderColor" );
defaults.put( "HelpButton.background", helpButtonBackground );
defaults.put( "HelpButton.borderColor", helpButtonBorderColor );
defaults.put( "HelpButton.disabledBackground", defaults.get( "Panel.background" ) );
defaults.put( "HelpButton.disabledBorderColor", defaults.get( "Button.disabledBorderColor" ) );
defaults.put( "HelpButton.focusedBorderColor", defaults.get( "Button.focusedBorderColor" ) );
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
// IDEA uses TextField.background for editable ComboBox and Spinner
defaults.put( "ComboBox.editableBackground", defaults.get( "TextField.background" ) );
defaults.put( "Spinner.background", defaults.get( "TextField.background" ) );
@@ -212,7 +230,9 @@ public class IntelliJTheme
if( uiValue == null ) {
// fix errors (missing '#' for colors)
if( !valueStr.startsWith( "#" ) && (key.endsWith( "ground" ) || key.endsWith( "Color" )) )
valueStr = "#" + valueStr;
valueStr = fixColorIfValid( "#" + valueStr, valueStr );
else if( valueStr.startsWith( "##" ) )
valueStr = fixColorIfValid( valueStr.substring( 1 ), valueStr );
else if( key.endsWith( ".border" ) || key.endsWith( "Border" ) ) {
List<String> parts = StringUtils.split( valueStr, ',' );
if( parts.size() == 5 && !parts.get( 4 ).startsWith( "#" ) ) {
@@ -259,6 +279,17 @@ public class IntelliJTheme
}
}
private String fixColorIfValid( String newColorStr, String colorStr ) {
try {
// check whether it is valid
UIDefaultsLoader.parseColorRGBA( newColorStr );
return newColorStr;
} catch( IllegalArgumentException ex ) {
return colorStr;
}
}
private void applyColorPalette( UIDefaults defaults ) {
if( icons == null )
return;
@@ -380,17 +411,6 @@ public class IntelliJTheme
private static Set<String> noWildcardReplace = new HashSet<>();
static {
// Button
// IDEA buttons support gradient for background and border, but FlatLaf does not
uiKeyMapping.put( "Button.startBackground", "Button.background" );
uiKeyMapping.put( "Button.startBorderColor", "Button.borderColor" );
uiKeyMapping.put( "Button.default.startBackground", "Button.default.background" );
uiKeyMapping.put( "Button.default.startBorderColor", "Button.default.borderColor" );
uiKeyMapping.put( "Button.endBackground", "" ); // ignore
uiKeyMapping.put( "Button.endBorderColor", "" ); // ignore
uiKeyMapping.put( "Button.default.endBackground", "" ); // ignore
uiKeyMapping.put( "Button.default.endBorderColor", "" ); // ignore
// ComboBox
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );

View File

@@ -22,6 +22,7 @@ import java.awt.Insets;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -30,6 +31,7 @@ import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function;
import javax.swing.UIDefaults;
import javax.swing.UIDefaults.ActiveValue;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
@@ -38,9 +40,9 @@ import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ColorFunctions;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.ScaledNumber;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
/**
* Load UI defaults from properties files associated to Flat LaF classes and add to UI defaults.
@@ -77,6 +79,8 @@ class UIDefaultsLoader
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, UIDefaults defaults ) {
try {
List<ClassLoader> addonClassLoaders = new ArrayList<>();
// load properties files
Properties properties = new Properties();
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
@@ -94,6 +98,10 @@ class UIDefaultsLoader
if( in != null )
properties.load( in );
}
ClassLoader addonClassLoader = addon.getClass().getClassLoader();
if( !addonClassLoaders.contains( addonClassLoader ) )
addonClassLoaders.add( addonClassLoader );
}
}
@@ -131,7 +139,7 @@ class UIDefaultsLoader
String value = resolveValue( properties, (String) e.getValue() );
try {
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver ) );
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver, addonClassLoaders ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
@@ -156,7 +164,7 @@ class UIDefaultsLoader
String value = resolveValue( properties, (String) e.getValue() );
try {
defaults.put( key, parseValue( key, value, resolver ) );
defaults.put( key, parseValue( key, value, resolver, addonClassLoaders ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
@@ -195,13 +203,13 @@ class UIDefaultsLoader
return resolveValue( properties, newValue );
}
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDNUMBER }
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDINTEGER, INSTANCE, CLASS }
static Object parseValue( String key, String value ) {
return parseValue( key, value, v -> v );
return parseValue( key, value, v -> v, Collections.emptyList() );
}
private static Object parseValue( String key, String value, Function<String, String> resolver ) {
private static Object parseValue( String key, String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
value = value.trim();
// null, false, true
@@ -254,12 +262,14 @@ class UIDefaultsLoader
switch( valueType ) {
case STRING: return value;
case INTEGER: return parseInteger( value, true );
case BORDER: return parseBorder( value, resolver );
case ICON: return parseInstance( value );
case BORDER: return parseBorder( value, resolver, addonClassLoaders );
case ICON: return parseInstance( value, addonClassLoaders );
case INSETS: return parseInsets( value );
case SIZE: return parseSize( value );
case COLOR: return parseColorOrFunction( value, true );
case SCALEDNUMBER: return parseScaledNumber( value );
case SCALEDINTEGER: return parseScaledInteger( value );
case INSTANCE: return parseInstance( value, addonClassLoaders );
case CLASS: return parseClass( value, addonClassLoaders );
case UNKNOWN:
default:
// colors
@@ -277,7 +287,7 @@ class UIDefaultsLoader
}
}
private static Object parseBorder( String value, Function<String, String> resolver ) {
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor]
List<String> parts = StringUtils.split( value, ',' );
@@ -292,13 +302,13 @@ class UIDefaultsLoader
: new FlatEmptyBorder( insets );
};
} else
return parseInstance( value );
return parseInstance( value, addonClassLoaders );
}
private static Object parseInstance( String value ) {
private static Object parseInstance( String value, List<ClassLoader> addonClassLoaders ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
return findClass( value, addonClassLoaders ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
@@ -306,6 +316,35 @@ class UIDefaultsLoader
};
}
private static Object parseClass( String value, List<ClassLoader> addonClassLoaders ) {
return (LazyValue) t -> {
try {
return findClass( value, addonClassLoaders );
} catch( ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private static Class<?> findClass( String className, List<ClassLoader> addonClassLoaders )
throws ClassNotFoundException
{
try {
return Class.forName( className );
} catch( ClassNotFoundException ex ) {
// search in addons class loaders
for( ClassLoader addonClassLoader : addonClassLoaders ) {
try {
return addonClassLoader.loadClass( className );
} catch( ClassNotFoundException ex2 ) {
// ignore
}
}
throw ex;
}
}
private static Insets parseInsets( String value ) {
List<String> numbers = StringUtils.split( value, ',' );
try {
@@ -468,11 +507,10 @@ class UIDefaultsLoader
return null;
}
private static ScaledNumber parseScaledNumber( String value ) {
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
private static ActiveValue parseScaledInteger( String value ) {
int val = parseInteger( value, true );
return (ActiveValue) t -> {
return UIScale.scale( val );
};
}
}

View File

@@ -62,7 +62,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatCheckBoxIcon
extends FlatAbstractIcon
{
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
public final int focusWidth = UIManager.getInt( "Component.focusWidth" );
protected final Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusedColor",
UIManager.getColor( "Component.focusColor" ) );
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
@@ -133,17 +133,17 @@ public class FlatCheckBoxIcon
protected void paintFocusBorder( Graphics2D g2 ) {
// the outline focus border is painted outside of the icon
int wh = ICON_SIZE - 1 + (focusWidth * 2);
int arcwh = (arc + focusWidth) * 2;
int arcwh = arc + (focusWidth * 2);
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
}
protected void paintBorder( Graphics2D g2 ) {
int arcwh = arc * 2;
int arcwh = arc;
g2.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
}
protected void paintBackground( Graphics2D g2 ) {
int arcwh = (arc * 2) - 1;
int arcwh = arc - 1;
g2.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
}

View File

@@ -38,12 +38,15 @@ public class FlatArrowButton
extends BasicArrowButton
implements UIResource
{
public static final int DEFAULT_ARROW_WIDTH = 8;
private final boolean chevron;
private final Color foreground;
private final Color disabledForeground;
private final Color hoverForeground;
private final Color hoverBackground;
private int arrowWidth = DEFAULT_ARROW_WIDTH;
private int xOffset = 0;
private int yOffset = 0;
@@ -80,6 +83,14 @@ public class FlatArrowButton
}
}
public int getArrowWidth() {
return arrowWidth;
}
public void setArrowWidth( int arrowWidth ) {
this.arrowWidth = arrowWidth;
}
protected boolean isHover() {
return hover;
}
@@ -128,8 +139,8 @@ public class FlatArrowButton
int direction = getDirection();
boolean vert = (direction == NORTH || direction == SOUTH);
int w = scale( chevron ? 8 : 9 );
int h = scale( chevron ? 4 : 5 );
int w = scale( arrowWidth + (chevron ? 0 : 1) );
int h = scale( (arrowWidth / 2) + (chevron ? 0 : 1) );
int rw = vert ? w : h;
int rh = vert ? h : w;
int x = Math.round( (width - rw) / 2f + scale( (float) xOffset ) );

View File

@@ -23,6 +23,7 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Paint;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
@@ -78,12 +79,12 @@ public class FlatBorder
if( isFocused( c ) ) {
g2.setColor( getFocusColor( c ) );
FlatUIUtils.paintOutlineBorder( g2, x, y, width, height, focusWidth,
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height, focusWidth,
getLineWidth() + scale( (float) innerFocusWidth ), arc );
}
g2.setColor( getBorderColor( c ) );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, borderWidth, arc );
g2.setPaint( getBorderColor( c ) );
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
} finally {
g2.dispose();
}
@@ -93,13 +94,24 @@ public class FlatBorder
return focusColor;
}
protected Color getBorderColor( Component c ) {
boolean enabled = c.isEnabled() && (!(c instanceof JTextComponent) || ((JTextComponent)c).isEditable());
return enabled
protected Paint getBorderColor( Component c ) {
return isEnabled( c )
? (isFocused( c ) ? focusedBorderColor : borderColor)
: disabledBorderColor;
}
protected boolean isEnabled( Component c ) {
if( c instanceof JScrollPane ) {
// check whether view component is disabled
JViewport viewport = ((JScrollPane)c).getViewport();
Component view = (viewport != null) ? viewport.getView() : null;
if( view != null && !isEnabled( view ) )
return false;
}
return c.isEnabled() && (!(c instanceof JTextComponent) || ((JTextComponent)c).isEditable());
}
protected boolean isFocused( Component c ) {
if( c instanceof JScrollPane ) {
JViewport viewport = ((JScrollPane)c).getViewport();

View File

@@ -19,8 +19,10 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Component;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Paint;
import javax.swing.JButton;
import javax.swing.UIManager;
import javax.swing.plaf.UIResource;
@@ -29,10 +31,14 @@ import javax.swing.plaf.UIResource;
* Border for {@link javax.swing.JButton}.
*
* @uiDefault Button.borderColor Color
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
* @uiDefault Button.disabledBorderColor Color
* @uiDefault Button.focusedBorderColor Color
* @uiDefault Button.hoverBorderColor Color optional
* @uiDefault Button.default.borderColor Color
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
* @uiDefault Button.default.hoverBorderColor Color optional
* @uiDefault Button.default.focusedBorderColor Color
* @uiDefault Button.default.focusColor Color
@@ -44,11 +50,13 @@ import javax.swing.plaf.UIResource;
public class FlatButtonBorder
extends FlatBorder
{
protected final Color borderColor = UIManager.getColor( "Button.borderColor" );
protected final Color borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
protected final Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
protected final Color disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
protected final Color focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
protected final Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
protected final Color defaultBorderColor = UIManager.getColor( "Button.default.borderColor" );
protected final Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
protected final Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
protected final Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
@@ -67,14 +75,22 @@ public class FlatButtonBorder
}
@Override
protected Color getBorderColor( Component c ) {
protected Paint getBorderColor( Component c ) {
boolean def = FlatButtonUI.isDefaultButton( c );
return FlatButtonUI.buttonStateColor( c,
Paint color = FlatButtonUI.buttonStateColor( c,
def ? defaultBorderColor : borderColor,
disabledBorderColor,
def ? defaultFocusedBorderColor : focusedBorderColor,
def ? defaultHoverBorderColor : hoverBorderColor,
null );
// change to gradient paint if start/end colors are specified
Color startBg = def ? defaultBorderColor : borderColor;
Color endBg = def ? defaultEndBorderColor : endBorderColor;
if( color == startBg && endBg != null && !startBg.equals( endBg ) )
color = new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg );
return color;
}
@Override

View File

@@ -23,9 +23,11 @@ import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
@@ -39,6 +41,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicButtonUI;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JButton}.
@@ -58,16 +61,24 @@ import com.formdev.flatlaf.FlatLaf;
* @uiDefault Button.arc int
* @uiDefault Button.minimumWidth int
* @uiDefault Button.iconTextGap int
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
* @uiDefault Button.focusedBackground Color optional
* @uiDefault Button.hoverBackground Color optional
* @uiDefault Button.pressedBackground Color optional
* @uiDefault Button.disabledText Color
* @uiDefault Button.default.background Color
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
* @uiDefault Button.default.foreground Color
* @uiDefault Button.default.focusedBackground Color optional
* @uiDefault Button.default.hoverBackground Color optional
* @uiDefault Button.default.pressedBackground Color optional
* @uiDefault Button.default.boldText boolean
* @uiDefault Button.paintShadow boolean default is false
* @uiDefault Button.shadowWidth int default is 2
* @uiDefault Button.shadowColor Color optional
* @uiDefault Button.default.shadowColor Color optional
* @uiDefault Button.toolbar.hoverBackground Color
* @uiDefault Button.toolbar.pressedBackground Color
*
@@ -81,18 +92,25 @@ public class FlatButtonUI
protected int minimumWidth;
protected int iconTextGap;
protected Color startBackground;
protected Color endBackground;
protected Color focusedBackground;
protected Color hoverBackground;
protected Color pressedBackground;
protected Color disabledText;
protected Color defaultBackground;
protected Color defaultEndBackground;
protected Color defaultForeground;
protected Color defaultFocusedBackground;
protected Color defaultHoverBackground;
protected Color defaultPressedBackground;
protected boolean defaultBoldText;
protected int shadowWidth;
protected Color shadowColor;
protected Color defaultShadowColor;
protected Color toolbarHoverBackground;
protected Color toolbarPressedBackground;
@@ -116,16 +134,25 @@ public class FlatButtonUI
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( prefix + "arc" );
arc = UIManager.getInt( "Button.arc" );
minimumWidth = UIManager.getInt( prefix + "minimumWidth" );
iconTextGap = FlatUIUtils.getUIInt( prefix + "iconTextGap", 4 );
startBackground = UIManager.getColor( prefix + "startBackground" );
endBackground = UIManager.getColor( prefix + "endBackground" );
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
disabledText = UIManager.getColor( prefix + "disabledText" );
defaultBackground = UIManager.getColor( "Button.default.background" );
if( UIManager.getBoolean( "Button.paintShadow" ) ) {
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
shadowColor = UIManager.getColor( "Button.shadowColor" );
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
}
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
defaultForeground = UIManager.getColor( "Button.default.foreground" );
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
@@ -140,6 +167,12 @@ public class FlatButtonUI
defaults_initialized = true;
}
if( startBackground != null ) {
Color bg = b.getBackground();
if( bg == null || bg instanceof UIResource )
b.setBackground( startBackground );
}
LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
@@ -201,9 +234,24 @@ public class FlatButtonUI
Border border = c.getBorder();
float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (border instanceof FlatButtonBorder || isToolBarButton( c )) ? scale( (float) this.arc ) : 0;
boolean def = isDefaultButton( c );
FlatUIUtils.setColor( g2, background, isDefaultButton(c) ? defaultBackground : c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
// paint shadow
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && !c.hasFocus() && c.isEnabled() ) {
g2.setColor( shadowColor );
g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ),
c.getWidth() - focusWidth * 2, c.getHeight() - focusWidth * 2, arc, arc ) );
}
// paint background
Color startBg = def ? defaultBackground : startBackground;
Color endBg = def ? defaultEndBackground : endBackground;
if( background == startBg && endBg != null && !startBg.equals( endBg ) )
g2.setPaint( new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg ) );
else
FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() );
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();
}

View File

@@ -52,6 +52,7 @@ import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -239,7 +240,8 @@ public class FlatComboBoxUI
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
editor.applyComponentOrientation( o );
}
} else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) )
editor.repaint();
}
};
}
@@ -316,7 +318,7 @@ public class FlatComboBoxUI
g2.setColor( enabled
? (editableBackground != null && comboBox.isEditable() ? editableBackground : c.getBackground())
: getDisabledBackground( comboBox ) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
@@ -326,7 +328,7 @@ public class FlatComboBoxUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -335,7 +337,7 @@ public class FlatComboBoxUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
}
paint( g, c );

View File

@@ -39,8 +39,10 @@ import javax.swing.plaf.ComponentUI;
*
* <!-- FlatTextFieldUI -->
*
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault FormattedTextField.placeholderForeground Color
*
* @author Karl Tauber
*/

View File

@@ -48,7 +48,7 @@ public class FlatLineBorder
try {
FlatUIUtils.setRenderingHints( g2 );
g2.setColor( lineColor );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, 0f, scale( 1f ), 0f );
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( 1f ), 0f );
} finally {
g2.dispose();
}

View File

@@ -17,14 +17,17 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -51,6 +54,7 @@ import com.formdev.flatlaf.util.SystemInfo;
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault PasswordField.placeholderForeground Color
*
* @author Karl Tauber
*/
@@ -60,6 +64,7 @@ public class FlatPasswordFieldUI
protected int focusWidth;
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color placeholderForeground;
private FocusListener focusListener;
@@ -75,9 +80,11 @@ public class FlatPasswordFieldUI
if( SystemInfo.IS_MAC )
LookAndFeel.installProperty( getComponent(), "echoChar", '\u2022' );
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
@@ -88,6 +95,8 @@ public class FlatPasswordFieldUI
protected void uninstallDefaults() {
super.uninstallDefaults();
placeholderForeground = null;
MigLayoutVisualPadding.uninstall( getComponent() );
}
@@ -107,9 +116,18 @@ public class FlatPasswordFieldUI
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
getComponent().repaint();
}
@Override
protected void paintSafely( Graphics g ) {
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
super.paintSafely( g );
}

View File

@@ -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
*
* <!-- FlatProgressBarUI -->
*
* @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 );

View File

@@ -18,7 +18,9 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.CellRendererPane;
@@ -28,6 +30,8 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JRadioButton}.
@@ -92,6 +96,26 @@ public class FlatRadioButtonUI
defaults_initialized = false;
}
private static Insets tempInsets = new Insets( 0, 0, 0, 0 );
@Override
public Dimension getPreferredSize( JComponent c ) {
Dimension size = super.getPreferredSize( c );
// small insets fix
int focusWidth = getIconFocusWidth( c );
if( focusWidth > 0 ) {
// Increase preferred width and height if insets were explicitly reduced (e.g. with
// an EmptyBorder) and icon has a focus width, which is not included in icon size.
// Otherwise the component may be too small and outer focus border may be cut off.
Insets insets = c.getInsets( tempInsets );
size.width += Math.max( focusWidth - insets.left, 0 ) + Math.max( focusWidth - insets.right, 0 );
size.height += Math.max( focusWidth - insets.top, 0 ) + Math.max( focusWidth - insets.bottom, 0 );
}
return size;
}
@Override
public void paint( Graphics g, JComponent c ) {
// fill background even if opaque if
@@ -104,6 +128,29 @@ public class FlatRadioButtonUI
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
// small insets fix
int focusWidth = getIconFocusWidth( c );
if( focusWidth > 0 ) {
boolean ltr = c.getComponentOrientation().isLeftToRight();
Insets insets = c.getInsets( tempInsets );
int leftOrRightInset = ltr ? insets.left : insets.right;
if( focusWidth > leftOrRightInset ) {
// The left (or right) inset is smaller than the focus width, which may be
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
// In this case the width has been increased in getPreferredSize() and
// here it is necessary to fix icon and text painting location.
int offset = focusWidth - leftOrRightInset;
if( !ltr )
offset = -offset;
// move the graphics origin to the left (or right)
g.translate( offset, 0 );
super.paint( g, c );
g.translate( -offset, 0 );
return;
}
}
super.paint( g, c );
}
@@ -111,4 +158,11 @@ public class FlatRadioButtonUI
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
FlatButtonUI.paintText( g, b, textRect, text, b.isEnabled() ? b.getForeground() : disabledText );
}
private int getIconFocusWidth( JComponent c ) {
AbstractButton b = (AbstractButton) c;
return (b.getIcon() == null && getDefaultIcon() instanceof FlatCheckBoxIcon)
? UIScale.scale( ((FlatCheckBoxIcon)getDefaultIcon()).focusWidth )
: 0;
}
}

View File

@@ -22,11 +22,16 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -38,13 +43,20 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault ScrollBar.foreground Color
* @uiDefault ScrollBar.track Color
* @uiDefault ScrollBar.thumb Color
* @uiDefault ScrollBar.hoverTrackColor Color
* @uiDefault ScrollBar.hoverThumbColor Color
* @uiDefault ScrollBar.width int
* @uiDefault ScrollBar.minimumThumbSize Dimension
* @uiDefault ScrollBar.maximumThumbSize Dimension
* @uiDefault ScrollBar.allowsAbsolutePositioning boolean
*
* <!-- FlatScrollBarUI -->
*
* @uiDefault ScrollBar.hoverTrackColor Color
* @uiDefault ScrollBar.hoverThumbColor Color
* @uiDefault Component.arrowType String triangle (default) or chevron
* @uiDefault ScrollBar.showButtons boolean
* @uiDefault ScrollBar.buttonArrowColor Color
* @uiDefault ScrollBar.buttonDisabledArrowColor Color
*
* @author Karl Tauber
*/
public class FlatScrollBarUI
@@ -53,6 +65,11 @@ public class FlatScrollBarUI
protected Color hoverTrackColor;
protected Color hoverThumbColor;
protected boolean showButtons;
protected String arrowType;
protected Color buttonArrowColor;
protected Color buttonDisabledArrowColor;
private MouseAdapter hoverListener;
private boolean hoverTrack;
private boolean hoverThumb;
@@ -85,6 +102,11 @@ public class FlatScrollBarUI
hoverTrackColor = UIManager.getColor( "ScrollBar.hoverTrackColor" );
hoverThumbColor = UIManager.getColor( "ScrollBar.hoverThumbColor" );
showButtons = UIManager.getBoolean( "ScrollBar.showButtons" );
arrowType = UIManager.getString( "Component.arrowType" );
buttonArrowColor = UIManager.getColor( "ScrollBar.buttonArrowColor" );
buttonDisabledArrowColor = UIManager.getColor( "ScrollBar.buttonDisabledArrowColor" );
}
@Override
@@ -93,6 +115,24 @@ public class FlatScrollBarUI
hoverTrackColor = null;
hoverThumbColor = null;
buttonArrowColor = null;
buttonDisabledArrowColor = null;
}
@Override
protected PropertyChangeListener createPropertyChangeListener() {
return new BasicScrollBarUI.PropertyChangeHandler() {
@Override
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS.equals( e.getPropertyName() ) ) {
scrollbar.revalidate();
scrollbar.repaint();
}
}
};
}
@Override
@@ -102,24 +142,50 @@ public class FlatScrollBarUI
@Override
protected JButton createDecreaseButton( int orientation ) {
return createInvisibleButton();
return createArrowButton( orientation );
}
@Override
protected JButton createIncreaseButton( int orientation ) {
return createInvisibleButton();
return createArrowButton( orientation );
}
private JButton createInvisibleButton() {
JButton button = new JButton();
button.setMinimumSize( new Dimension() );
button.setMaximumSize( new Dimension() );
button.setPreferredSize( new Dimension() );
private JButton createArrowButton( int orientation ) {
FlatArrowButton button = new FlatArrowButton( orientation,
arrowType, buttonArrowColor, buttonDisabledArrowColor, null, hoverTrackColor )
{
@Override
public Dimension getPreferredSize() {
if( isShowButtons() ) {
int w = UIScale.scale( scrollBarWidth );
return new Dimension( w, w );
} else
return new Dimension();
}
@Override
public Dimension getMinimumSize() {
return isShowButtons() ? super.getMinimumSize() : new Dimension();
}
@Override
public Dimension getMaximumSize() {
return isShowButtons() ? super.getMaximumSize() : new Dimension();
}
};
button.setArrowWidth( FlatArrowButton.DEFAULT_ARROW_WIDTH - 2 );
button.setFocusable( false );
button.setRequestFocusEnabled( false );
return button;
}
private boolean isShowButtons() {
Object showButtons = scrollbar.getClientProperty( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS );
if( showButtons == null && scrollbar.getParent() instanceof JScrollPane )
showButtons = ((JScrollPane)scrollbar.getParent()).getClientProperty( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS );
return (showButtons != null) ? Objects.equals( showButtons, true ) : this.showButtons;
}
@Override
protected void paintDecreaseHighlight( Graphics g ) {
// do not paint

View File

@@ -24,13 +24,16 @@ import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollPaneUI;
import com.formdev.flatlaf.FlatClientProperties;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JScrollPane}.
@@ -87,7 +90,30 @@ public class FlatScrollPaneUI
handler = null;
}
public Handler getHandler() {
@Override
protected PropertyChangeListener createPropertyChangeListener() {
return new BasicScrollPaneUI.PropertyChangeHandler() {
@Override
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS.equals( e.getPropertyName() ) ) {
JScrollBar vsb = scrollpane.getVerticalScrollBar();
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
if( vsb != null ) {
vsb.revalidate();
vsb.repaint();
}
if( hsb != null ) {
hsb.revalidate();
hsb.repaint();
}
}
}
};
}
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;

View File

@@ -159,7 +159,7 @@ public class FlatSpinnerUI
handler = null;
}
public Handler getHandler() {
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@@ -267,7 +267,7 @@ public class FlatSpinnerUI
g2.setColor( enabled
? c.getBackground()
: (isIntelliJTheme ? FlatUIUtils.getParentBackground( c ) : disabledBackground) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow buttons background
if( enabled ) {
@@ -277,7 +277,7 @@ public class FlatSpinnerUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -285,7 +285,7 @@ public class FlatSpinnerUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
paint( g, c );
}

View File

@@ -41,6 +41,7 @@ import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.text.View;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTabbedPane}.
@@ -53,11 +54,13 @@ import com.formdev.flatlaf.FlatLaf;
* @uiDefault TabbedPane.foreground Color
* @uiDefault TabbedPane.shadow Color used for scroll arrows and cropped line
* @uiDefault TabbedPane.disabledForeground Color
* @uiDefault TabbedPane.selectedBackground Color optional
* @uiDefault TabbedPane.selectedForeground Color
* @uiDefault TabbedPane.underlineColor Color
* @uiDefault TabbedPane.disabledUnderlineColor Color
* @uiDefault TabbedPane.hoverColor Color
* @uiDefault TabbedPane.focusColor Color
* @uiDefault TabbedPane.tabSeparatorColor Color optional; defaults to TabbedPane.contentAreaColor
* @uiDefault TabbedPane.contentAreaColor Color
* @uiDefault TabbedPane.textIconGap int
* @uiDefault TabbedPane.tabInsets Insets
@@ -65,6 +68,7 @@ import com.formdev.flatlaf.FlatLaf;
* @uiDefault TabbedPane.tabHeight int
* @uiDefault TabbedPane.tabSelectionHeight int
* @uiDefault TabbedPane.contentSeparatorHeight int
* @uiDefault TabbedPane.showTabSeparators boolean
* @uiDefault TabbedPane.hasFullBorder boolean
*
* @author Karl Tauber
@@ -73,16 +77,19 @@ public class FlatTabbedPaneUI
extends BasicTabbedPaneUI
{
protected Color disabledForeground;
protected Color selectedBackground;
protected Color selectedForeground;
protected Color underlineColor;
protected Color disabledUnderlineColor;
protected Color hoverColor;
protected Color focusColor;
protected Color tabSeparatorColor;
protected Color contentAreaColor;
protected int tabHeight;
protected int tabSelectionHeight;
protected int contentSeparatorHeight;
protected boolean showTabSeparators;
protected boolean hasFullBorder;
protected boolean tabsOverlapBorder;
@@ -95,16 +102,19 @@ public class FlatTabbedPaneUI
super.installDefaults();
disabledForeground = UIManager.getColor( "TabbedPane.disabledForeground" );
selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" );
selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" );
underlineColor = UIManager.getColor( "TabbedPane.underlineColor" );
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" );
@@ -124,11 +134,13 @@ public class FlatTabbedPaneUI
super.uninstallDefaults();
disabledForeground = null;
selectedBackground = null;
selectedForeground = null;
underlineColor = null;
disabledUnderlineColor = null;
hoverColor = null;
focusColor = null;
tabSeparatorColor = null;
contentAreaColor = null;
MigLayoutVisualPadding.uninstall( tabPane );
@@ -141,9 +153,12 @@ public class FlatTabbedPaneUI
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( TABBED_PANE_HAS_FULL_BORDER.equals( e.getPropertyName() ) ) {
tabPane.revalidate();
tabPane.repaint();
switch( e.getPropertyName() ) {
case TABBED_PANE_SHOW_TAB_SEPARATORS:
case TABBED_PANE_HAS_FULL_BORDER:
tabPane.revalidate();
tabPane.repaint();
break;
}
}
};
@@ -197,7 +212,7 @@ public class FlatTabbedPaneUI
*/
@Override
protected Insets getContentBorderInsets( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
@@ -262,7 +277,9 @@ public class FlatTabbedPaneUI
? hoverColor
: (enabled && isSelected && tabPane.hasFocus()
? focusColor
: tabPane.getBackgroundAt( tabIndex )) );
: (selectedBackground != null && enabled && isSelected
? selectedBackground
: tabPane.getBackgroundAt( tabIndex ))) );
g.fillRect( x, y, w, h );
}
@@ -270,6 +287,26 @@ public class FlatTabbedPaneUI
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected )
{
// paint tab separators
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
!isLastInRun( tabIndex ) )
{
float sepWidth = UIScale.scale( 1f );
float offset = UIScale.scale( 5f );
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
if( tabPlacement == LEFT || tabPlacement == RIGHT ) {
// paint tab separator at bottom side
((Graphics2D)g).fill( new Rectangle2D.Float( x + offset, y + h - sepWidth, w - (offset * 2), sepWidth ) );
} else if( tabPane.getComponentOrientation().isLeftToRight() ) {
// paint tab separator at right side
((Graphics2D)g).fill( new Rectangle2D.Float( x + w - sepWidth, y + offset, sepWidth, h - (offset * 2) ) );
} else {
// paint tab separator at left side
((Graphics2D)g).fill( new Rectangle2D.Float( x, y + offset, sepWidth, h - (offset * 2) ) );
}
}
if( isSelected )
paintTabSelection( g, tabPlacement, x, y, w, h );
}
@@ -334,7 +371,7 @@ public class FlatTabbedPaneUI
}
/**
* Actually does the nearly the same as super.paintContentBorder() but
* Actually does nearly the same as super.paintContentBorder() but
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
* - not invoking paintContentBorder*Edge() methods
* - repaint selection
@@ -379,7 +416,7 @@ public class FlatTabbedPaneUI
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
@@ -414,6 +451,11 @@ public class FlatTabbedPaneUI
{
}
private boolean isLastInRun( int tabIndex ) {
int run = getRunForTab( tabPane.getTabCount(), tabIndex );
return lastTabInRun( tabPane.getTabCount(), run ) == tabIndex;
}
private boolean isScrollTabLayout() {
return tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
}

View File

@@ -20,9 +20,12 @@ import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JSpinner;
@@ -33,6 +36,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextFieldUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
@@ -57,6 +61,7 @@ import javax.swing.text.JTextComponent;
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextField.placeholderForeground Color
*
* @author Karl Tauber
*/
@@ -66,6 +71,7 @@ public class FlatTextFieldUI
protected int focusWidth;
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color placeholderForeground;
private FocusListener focusListener;
@@ -77,9 +83,11 @@ public class FlatTextFieldUI
protected void installDefaults() {
super.installDefaults();
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
@@ -90,6 +98,8 @@ public class FlatTextFieldUI
protected void uninstallDefaults() {
super.uninstallDefaults();
placeholderForeground = null;
MigLayoutVisualPadding.uninstall( getComponent() );
}
@@ -109,9 +119,18 @@ public class FlatTextFieldUI
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
getComponent().repaint();
}
@Override
protected void paintSafely( Graphics g ) {
paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
paintPlaceholder( g, getComponent(), placeholderForeground );
super.paintSafely( g );
}
@@ -146,12 +165,37 @@ public class FlatTextFieldUI
: (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())
? FlatUIUtils.getParentBackground( c )
: background) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
} finally {
g2.dispose();
}
}
static void paintPlaceholder( Graphics g, JTextComponent c, Color placeholderForeground ) {
// check whether text component is empty
if( c.getDocument().getLength() > 0 )
return;
// check for JComboBox
Container parent = c.getParent();
JComponent jc = (parent instanceof JComboBox) ? (JComboBox<?>) parent : c;
// get placeholder text
Object placeholder = jc.getClientProperty( FlatClientProperties.PLACEHOLDER_TEXT );
if( !(placeholder instanceof String) )
return;
// compute placeholder location
Insets insets = c.getInsets();
FontMetrics fm = c.getFontMetrics( c.getFont() );
int x = insets.left;
int y = insets.top + fm.getAscent() + ((c.getHeight() - insets.top - insets.bottom - fm.getHeight()) / 2);
// paint placeholder
g.setColor( placeholderForeground );
FlatUIUtils.drawString( c, g, (String) placeholder, x, y );
}
@Override
public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( super.getPreferredSize( c ), c );

View File

@@ -38,9 +38,11 @@ import javax.swing.plaf.ComponentUI;
* <!-- FlatButtonUI -->
*
* @uiDefault Component.focusWidth int
* @uiDefault ToggleButton.arc int
* @uiDefault Button.arc int
* @uiDefault ToggleButton.minimumWidth int
* @uiDefault ToggleButton.iconTextGap int
* @uiDefault ToggleButton.startBackground Color optional; if set, a gradient paint is used and ToggleButton.background is ignored
* @uiDefault ToggleButton.endBackground Color optional; if set, a gradient paint is used
* @uiDefault ToggleButton.pressedBackground Color
* @uiDefault ToggleButton.disabledText Color
* @uiDefault ToggleButton.toolbar.hoverBackground Color

View File

@@ -39,6 +39,7 @@ import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.UIScale;
@@ -125,9 +126,73 @@ public class FlatUIUtils
}
/**
* Draws a round rectangle.
* Paints an outer border, which is usually a focus border.
* <p>
* The outside bounds of the painted border are {@code x,y,width,height}.
* The line width of the painted border is {@code focusWidth + lineWidth}.
* The given arc diameter refers to the inner rectangle ({@code x,y,width,height} minus {@code focusWidth}).
*
* @see #paintComponentBorder
* @see #paintComponentBackground
*/
public static void drawRoundRectangle( Graphics2D g, int x, int y, int width, int height,
public static void paintComponentOuterBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentOuterBorderImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentOuterBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
}
private static void paintComponentOuterBorderImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float outerRadius = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
float ow = focusWidth + lineWidth;
float innerRadius = outerRadius - ow;
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createRoundRectanglePath( x, y, width, height, outerRadius, outerRadius, outerRadius, outerRadius ), false );
path.append( createRoundRectanglePath( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerRadius, innerRadius, innerRadius, innerRadius ), false );
g.fill( path );
}
/**
* Draws the border of a component as round rectangle.
* <p>
* The outside bounds of the painted border are
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
*
* @see #paintComponentOuterBorder
* @see #paintComponentBackground
*/
public static void paintComponentBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentBorderImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
}
private static void paintComponentBorderImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
@@ -146,9 +211,33 @@ public class FlatUIUtils
}
/**
* Fills a round rectangle.
* Fills the background of a component with a round rectangle.
* <p>
* The bounds of the painted round rectangle are
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
*
* @see #paintComponentOuterBorder
* @see #paintComponentBorder
*/
public static void fillRoundRectangle( Graphics2D g, int x, int y, int width, int height,
public static void paintComponentBackground( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentBackgroundImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentBackgroundImpl( g, x, y, width, height, focusWidth, arc );
}
private static void paintComponentBackgroundImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float arc )
{
g.fill( new RoundRectangle2D.Float(
@@ -189,25 +278,6 @@ public class FlatUIUtils
return null;
}
/**
* Paints an outline border.
*/
public static void paintOutlineBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float outerArc = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
float ow = focusWidth + lineWidth;
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createOutlinePath( x, y, width, height, outerArc ), false );
path.append( createOutlinePath( x + ow, y + ow, width - (ow * 2), height - (ow * 2), outerArc - ow ), false );
g.fill( path );
}
private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) {
return createRoundRectanglePath( x, y, width, height, arc, arc, arc, arc );
}
/**
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
*/
@@ -222,7 +292,7 @@ public class FlatUIUtils
}
/**
* Creates a filled rounded rectangle shape and allows specifying the radius or each corner.
* Creates a filled rounded rectangle shape and allows specifying the radius of each corner.
*/
public static Shape createRoundRectanglePath( float x, float y, float width, float height,
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
@@ -256,10 +326,16 @@ public class FlatUIUtils
return rect;
}
/**
* Creates a closed path for the given points.
*/
public static Path2D createPath( double... points ) {
return createPath( true, points );
}
/**
* Creates a open or closed path for the given points.
*/
public static Path2D createPath( boolean close, double... points ) {
Path2D path = new Path2D.Float();
path.moveTo( points[0], points[1] );

View File

@@ -0,0 +1,111 @@
/*
* 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.util;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
/**
* @author Karl Tauber
*/
public class HiDPIUtils
{
public interface Painter {
public void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
}
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
paintAtScale1x( g, 0, 0, c.getWidth(), c.getHeight(), painter );
}
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) {
paintAtScale1x( g, x, y, width, height, UIScale.getSystemScaleFactor( g ), painter );
}
/**
* Paint at system scale factor 1x to avoid rounding issues at 125%, 150% and 175% scaling.
* <p>
* Scales the given Graphics2D down to 100% and invokes the
* given painter passing scaled x, y, width and height.
* <p>
* Uses the same scaling calculation as the JRE uses.
*/
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height,
double scaleFactor, Painter painter )
{
if( scaleFactor == 1 ) {
painter.paint( g, x, y, width, height, 1 );
return;
}
// save original transform
AffineTransform transform = g.getTransform();
// scale rectangle
Rectangle2D.Double scaledRect = scale( transform, x, y, width, height );
try {
// unscale to factor 1.0
double scale = 1.0 / scaleFactor;
g.scale( scale, scale );
// compute origin delta x/y
double dx = Math.floor( scaledRect.x ) - transform.getTranslateX();
double dy = Math.floor( scaledRect.y ) - transform.getTranslateY();
// move origin to make sure that origin x/y are at whole numbers
if( dx != 0 || dy != 0 )
g.translate( dx, dy );
int swidth = (int) scaledRect.width;
int sheight = (int) scaledRect.height;
// paint
painter.paint( g, 0, 0, swidth, sheight, scaleFactor );
} finally {
// restore original transform
g.setTransform( transform );
}
}
/**
* Scales a rectangle in the same way as the JRE does in
* sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(),
* which is used by Graphics.fillRect().
*/
private static Rectangle2D.Double scale( AffineTransform transform, int x, int y, int width, int height ) {
double dx1 = transform.getScaleX();
double dy2 = transform.getScaleY();
double px = x * dx1 + transform.getTranslateX();
double py = y * dy2 + transform.getTranslateY();
dx1 *= width;
dy2 *= height;
double newx = normalize( px );
double newy = normalize( py );
dx1 = normalize( px + dx1 ) - newx;
dy2 = normalize( py + dy2 ) - newy;
return new Rectangle2D.Double( newx, newy, dx1, dy2 );
}
private static double normalize( double value ) {
return Math.floor( value + 0.25 ) + 0.25;
}
}

View File

@@ -1,77 +0,0 @@
/*
* 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.util;
import static com.formdev.flatlaf.util.UIScale.scale;
/**
* A number that scales its value.
*
* NOTE:
* Using ScaledNumber in UI defaults works only if the value is get with
* sun.swing.DefaultLookup.getInt(), which is used by some basic UI delegates,
* because this method uses "instanceof Number".
* UIManager.getInt() on the other hand uses "instanceof Integer" and does not work.
*
* @author Karl Tauber
*/
public class ScaledNumber
extends Number
{
private final int value;
public ScaledNumber( int value ) {
this.value = value;
}
@Override
public int intValue() {
return scale( value );
}
@Override
public long longValue() {
return scale( value );
}
@Override
public float floatValue() {
return scale( (float) value );
}
@Override
public double doubleValue() {
return scale( (float) value );
}
@Override
public int hashCode() {
return Integer.hashCode( value );
}
@Override
public boolean equals( Object obj ) {
return (obj instanceof ScaledNumber)
? (value == ((ScaledNumber)obj).value)
: false;
}
@Override
public String toString() {
return Integer.toString( value );
}
}

View File

@@ -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)
*/

View File

@@ -54,14 +54,14 @@
*.acceleratorSelectionForeground=@selectionForeground
#---- system ----
#---- system colors ----
control=@background
controlText=@foreground
infoText=@foreground
text=@foreground
textText=@foreground
window=@background
activeCaption=#434E60
inactiveCaption=#393C3D
controlHighlight=#616669
controlLtHighlight=#303234
controlShadow=#afb3b5
controlDkShadow=#d7d9da
#---- Button ----

View File

@@ -25,8 +25,6 @@ Button.focusedBackground=null
Button.default.background=#4A86C7
Button.default.foreground=#f0f0f0
Button.default.focusedBackground=null
Button.default.hoverBackground=#5B91CC
Button.default.pressedBackground=#6E9ED2
Button.default.borderColor=#3167ad
Button.default.hoverBorderColor=#a8cef6
Button.default.focusedBorderColor=#a8cef6

View File

@@ -61,6 +61,30 @@ ViewportUI=com.formdev.flatlaf.ui.FlatViewportUI
@textComponentMargin=2,6,2,6
#---- system colors ----
desktop=@textComponentBackground
activeCaptionText=@foreground
activeCaptionBorder=@@activeCaption
inactiveCaptionText=@foreground
inactiveCaptionBorder=@@inactiveCaption
window=@background
windowBorder=@foreground
windowText=@foreground
menu=@background
menuText=@foreground
text=@textComponentBackground
textText=@foreground
textHighlight=@selectionBackground
textHighlightText=@selectionForeground
textInactiveText=@disabledText
control=@background
controlText=@foreground
scrollbar=@@ScrollBar.track
info=@@ToolTip.background
infoText=@foreground
#---- Button ----
Button.border=com.formdev.flatlaf.ui.FlatButtonBorder
@@ -70,15 +94,21 @@ Button.margin=2,14,2,14
Button.iconTextGap=4
Button.rollover=true
Button.defaultButtonFollowsFocus=false
[win]Button.defaultButtonFollowsFocus=true
Button.default.borderWidth=1
#---- Caret ----
Caret.width={scaledInteger}1
#---- CheckBox ----
CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon
CheckBox.arc=2
CheckBox.arc=4
CheckBox.margin=2,2,2,2
CheckBox.iconTextGap=4
CheckBox.rollover=true
@@ -117,8 +147,8 @@ Component.hideMnemonics=true
#---- EditorPane ----
EditorPane.border=com.formdev.flatlaf.ui.FlatMarginBorder
EditorPane.background=@textComponentBackground
EditorPane.margin=@textComponentMargin
EditorPane.background=@textComponentBackground
#---- FileChooser ----
@@ -142,8 +172,9 @@ FileView.floppyDriveIcon=com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon
#---- FormattedTextField ----
FormattedTextField.border=com.formdev.flatlaf.ui.FlatBorder
FormattedTextField.background=@textComponentBackground
FormattedTextField.margin=@textComponentMargin
FormattedTextField.background=@textComponentBackground
FormattedTextField.placeholderForeground=@disabledText
#---- HelpButton ----
@@ -202,7 +233,7 @@ OptionPane.maxCharactersPerLine=80
OptionPane.iconMessageGap=16
OptionPane.messagePadding=3
OptionPane.buttonPadding=8
OptionPane.buttonMinimumWidth={scaledNumber}72
OptionPane.buttonMinimumWidth={scaledInteger}72
OptionPane.sameSizeButtons=true
OptionPane.setButtonMargin=false
OptionPane.buttonOrientation=4
@@ -217,8 +248,9 @@ OptionPane.warningIcon=com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon
#---- PasswordField ----
PasswordField.border=com.formdev.flatlaf.ui.FlatBorder
PasswordField.background=@textComponentBackground
PasswordField.margin=@textComponentMargin
PasswordField.background=@textComponentBackground
PasswordField.placeholderForeground=@disabledText
#---- PopupMenu ----
@@ -237,8 +269,9 @@ PopupMenuSeparator.stripeIndent=4
#---- ProgressBar ----
ProgressBar.border=com.formdev.flatlaf.ui.FlatEmptyBorder
ProgressBar.horizontalSize=146,6
ProgressBar.verticalSize=6,146
ProgressBar.arc=4
ProgressBar.horizontalSize=146,4
ProgressBar.verticalSize=4,146
#---- RadioButton ----
@@ -262,6 +295,10 @@ RadioButtonMenuItem.margin=2,2,2,2
#---- ScrollBar ----
ScrollBar.width=10
ScrollBar.showButtons=false
ScrollBar.squareButtons=false
ScrollBar.buttonArrowColor=@@ComboBox.buttonArrowColor
ScrollBar.buttonDisabledArrowColor=@@ComboBox.buttonDisabledArrowColor
#---- ScrollPane ----
@@ -303,8 +340,8 @@ SplitPane.dividerSize={integer}5
SplitPane.continuousLayout=true
SplitPane.border=null
SplitPane.centerOneTouchButtons=true
SplitPane.oneTouchButtonSize={scaledNumber}6
SplitPane.oneTouchButtonOffset={scaledNumber}2
SplitPane.oneTouchButtonSize={scaledInteger}6
SplitPane.oneTouchButtonOffset={scaledInteger}2
SplitPaneDivider.border=null
SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor
@@ -346,22 +383,23 @@ TableHeader.cellBorder=2,3,2,3
#---- TextArea ----
TextArea.border=com.formdev.flatlaf.ui.FlatMarginBorder
TextArea.background=@textComponentBackground
TextArea.margin=@textComponentMargin
TextArea.background=@textComponentBackground
#---- TextField ----
TextField.border=com.formdev.flatlaf.ui.FlatBorder
TextField.background=@textComponentBackground
TextField.margin=@textComponentMargin
TextField.background=@textComponentBackground
TextField.placeholderForeground=@disabledText
#---- TextPane ----
TextPane.border=com.formdev.flatlaf.ui.FlatMarginBorder
TextPane.background=@textComponentBackground
TextPane.margin=@textComponentMargin
TextPane.background=@textComponentBackground
#---- TitledBorder ----
@@ -373,7 +411,6 @@ TitledBorder.border=1,1,1,1,@@Separator.foreground
#---- ToggleButton ----
ToggleButton.border=com.formdev.flatlaf.ui.FlatButtonBorder
ToggleButton.arc=6
ToggleButton.margin=2,14,2,14
ToggleButton.iconTextGap=4
ToggleButton.rollover=true

View File

@@ -54,14 +54,14 @@
*.acceleratorSelectionForeground=@selectionForeground
#---- system ----
#---- system colors ----
control=#e0e0e0
controlText=@foreground
infoText=@foreground
text=@foreground
textText=@foreground
window=@background
activeCaption=#99b4d1
inactiveCaption=#bfcddb
controlHighlight=#e3e3e3
controlLtHighlight=#fff
controlShadow=#a0a0a0
controlDkShadow=#696969
#---- Button ----

View File

@@ -19,5 +19,7 @@
Button.hoverBorderColor=null
Button.default.hoverBorderColor=null
Button.default.hoverBackground=@buttonHoverBackground
Button.default.pressedBackground=@buttonPressedBackground
#---- HelpButton ----
HelpButton.hoverBorderColor=null

View File

@@ -62,21 +62,25 @@ class BasicComponentsPanel
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JComboBox<String> comboBox6 = new JComboBox<>();
JLabel textFieldLabel = new JLabel();
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField4 = new JTextField();
JTextField textField6 = new JTextField();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField2 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
JFormattedTextField formattedTextField4 = new JFormattedTextField();
JFormattedTextField formattedTextField5 = new JFormattedTextField();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField2 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
JPasswordField passwordField4 = new JPasswordField();
JPasswordField passwordField5 = new JPasswordField();
JLabel textAreaLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JTextArea textArea1 = new JTextArea();
@@ -304,6 +308,11 @@ class BasicComponentsPanel
spinner2.setEnabled(false);
add(spinner2, "cell 2 5,growx");
//---- comboBox6 ----
comboBox6.setEditable(true);
comboBox6.putClientProperty("JTextField.placeholderText", "placeholder");
add(comboBox6, "cell 5 5,growx");
//---- textFieldLabel ----
textFieldLabel.setText("JTextField:");
add(textFieldLabel, "cell 0 6");
@@ -328,6 +337,10 @@ class BasicComponentsPanel
textField4.setEditable(false);
add(textField4, "cell 4 6,growx");
//---- textField6 ----
textField6.putClientProperty("JTextField.placeholderText", "placeholder");
add(textField6, "cell 5 6,growx");
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
add(formattedTextFieldLabel, "cell 0 7");
@@ -352,6 +365,10 @@ class BasicComponentsPanel
formattedTextField4.setEditable(false);
add(formattedTextField4, "cell 4 7,growx");
//---- formattedTextField5 ----
formattedTextField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(formattedTextField5, "cell 5 7,growx");
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
add(passwordFieldLabel, "cell 0 8");
@@ -376,6 +393,10 @@ class BasicComponentsPanel
passwordField4.setEditable(false);
add(passwordField4, "cell 4 8,growx");
//---- passwordField5 ----
passwordField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(passwordField5, "cell 5 8,growx");
//---- textAreaLabel ----
textAreaLabel.setText("JTextArea:");
add(textAreaLabel, "cell 0 9");

View File

@@ -253,6 +253,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 5,growx"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox6"
"editable": true
"$client.JTextField.placeholderText": "placeholder"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 5,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textFieldLabel"
"text": "JTextField:"
@@ -287,6 +297,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 6,growx"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField6"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 6,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -321,6 +337,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 7,growx"
} )
add( new FormComponent( "javax.swing.JFormattedTextField" ) {
name: "formattedTextField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 7,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -355,6 +377,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 8,growx"
} )
add( new FormComponent( "javax.swing.JPasswordField" ) {
name: "passwordField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 8,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textAreaLabel"
"text": "JTextArea:"

View File

@@ -77,6 +77,9 @@ class ControlBar
EventQueue.invokeLater( () -> {
// update info label because user scale factor may change
updateInfoLabel();
// this is necessary because embedded JOptionPane's "steal" the default button
frame.getRootPane().setDefaultButton( closeButton );
} );
}
} );
@@ -164,8 +167,6 @@ class ControlBar
if( lafClassName.equals( UIManager.getLookAndFeel().getClass().getName() ) )
return;
FlatLafDemo.prefs.put( FlatLafDemo.KEY_LAF, lafClassName );
EventQueue.invokeLater( () -> {
try {
// change look and feel

View File

@@ -30,7 +30,7 @@ class DemoFrame
extends JFrame
{
DemoFrame() {
int tabIndex = FlatLafDemo.prefs.getInt( FlatLafDemo.KEY_TAB, 0 );
int tabIndex = DemoPrefs.getState().getInt( FlatLafDemo.KEY_TAB, 0 );
initComponents();
controlBar.initialize( this, tabbedPane );
@@ -48,7 +48,7 @@ class DemoFrame
}
private void selectedTabChanged() {
FlatLafDemo.prefs.putInt( FlatLafDemo.KEY_TAB, tabbedPane.getSelectedIndex() );
DemoPrefs.getState().putInt( FlatLafDemo.KEY_TAB, tabbedPane.getSelectedIndex() );
}
private void initComponents() {

View File

@@ -0,0 +1,84 @@
/*
* 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.demo;
import java.io.FileInputStream;
import java.util.prefs.Preferences;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
/**
* @author Karl Tauber
*/
public class DemoPrefs
{
public static final String KEY_LAF = "laf";
public static final String KEY_LAF_INTELLIJ_THEME = "lafIntelliJTheme";
public static final String RESOURCE_PREFIX = "res:";
public static final String FILE_PREFIX = "file:";
public static final String INTELLIJ_THEME_UI_KEY = "__FlatLaf.demo.intelliJTheme";
private static Preferences state;
public static Preferences getState() {
return state;
}
public static void init( String rootPath ) {
state = Preferences.userRoot().node( rootPath );
}
public static void initLaf( String[] args ) {
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = state.get( KEY_LAF, FlatLightLaf.class.getName() );
if( IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) {
String intelliJTheme = state.get( KEY_LAF_INTELLIJ_THEME, "" );
if( intelliJTheme.startsWith( RESOURCE_PREFIX ) )
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( intelliJTheme.substring( RESOURCE_PREFIX.length() ) ) );
else if( intelliJTheme.startsWith( FILE_PREFIX ) )
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( intelliJTheme.substring( FILE_PREFIX.length() ) ) ) );
else
FlatLightLaf.install();
if( !intelliJTheme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( INTELLIJ_THEME_UI_KEY, intelliJTheme );
} else
UIManager.setLookAndFeel( lafClassName );
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
// remember active look and feel
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) )
state.put( KEY_LAF, UIManager.getLookAndFeel().getClass().getName() );
} );
}
}

View File

@@ -16,10 +16,7 @@
package com.formdev.flatlaf.demo;
import java.util.prefs.Preferences;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLightLaf;
/**
* @author Karl Tauber
@@ -27,29 +24,14 @@ import com.formdev.flatlaf.FlatLightLaf;
public class FlatLafDemo
{
static final String PREFS_ROOT_PATH = "/flatlaf-demo";
static final String KEY_LAF = "laf";
static final String KEY_TAB = "tab";
static Preferences prefs;
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
DemoPrefs.init( PREFS_ROOT_PATH );
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
DemoPrefs.initLaf( args );
// create frame
DemoFrame frame = new DemoFrame();

View File

@@ -31,6 +31,14 @@ class MoreComponentsPanel
initComponents();
}
private void changeProgress() {
int value = slider3.getValue();
progressBar1.setValue( value );
progressBar2.setValue( value );
progressBar3.setValue( value );
progressBar4.setValue( value );
}
private void indeterminateCheckBoxActionPerformed() {
boolean indeterminate = indeterminateCheckBox.isSelected();
progressBar1.setIndeterminate( indeterminate );
@@ -46,6 +54,8 @@ class MoreComponentsPanel
JPanel panel1 = new JPanel();
JScrollBar scrollBar2 = new JScrollBar();
JScrollBar scrollBar3 = new JScrollBar();
JScrollBar scrollBar7 = new JScrollBar();
JScrollBar scrollBar8 = new JScrollBar();
JSeparator separator2 = new JSeparator();
JSlider slider2 = new JSlider();
JSlider slider4 = new JSlider();
@@ -60,13 +70,15 @@ class MoreComponentsPanel
JLabel scrollBarLabel = new JLabel();
JScrollBar scrollBar1 = new JScrollBar();
JScrollBar scrollBar4 = new JScrollBar();
JScrollBar scrollBar5 = new JScrollBar();
JScrollBar scrollBar6 = new JScrollBar();
JLabel separatorLabel = new JLabel();
JSeparator separator1 = new JSeparator();
JPanel panel2 = new JPanel();
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();
@@ -102,6 +114,8 @@ class MoreComponentsPanel
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- scrollPaneLabel ----
@@ -121,20 +135,29 @@ class MoreComponentsPanel
scrollPane13.setViewportView(panel1);
}
add(scrollPane13, "cell 1 0,grow,width 70,height 70");
add(scrollBar2, "cell 2 0 1 4,growy");
add(scrollBar2, "cell 2 0 1 6,growy");
//---- scrollBar3 ----
scrollBar3.setEnabled(false);
add(scrollBar3, "cell 2 0 1 4,growy");
add(scrollBar3, "cell 2 0 1 6,growy");
//---- scrollBar7 ----
scrollBar7.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar7, "cell 2 0 1 6,growy");
//---- scrollBar8 ----
scrollBar8.setEnabled(false);
scrollBar8.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar8, "cell 2 0 1 6,growy");
//---- separator2 ----
separator2.setOrientation(SwingConstants.VERTICAL);
add(separator2, "cell 2 0 1 4,growy");
add(separator2, "cell 2 0 1 6,growy");
//---- slider2 ----
slider2.setOrientation(SwingConstants.VERTICAL);
slider2.setValue(30);
add(slider2, "cell 2 0 1 4,growy");
add(slider2, "cell 2 0 1 6,growy");
//---- slider4 ----
slider4.setMinorTickSpacing(10);
@@ -143,19 +166,19 @@ class MoreComponentsPanel
slider4.setPaintLabels(true);
slider4.setOrientation(SwingConstants.VERTICAL);
slider4.setValue(30);
add(slider4, "cell 2 0 1 4,growy");
add(slider4, "cell 2 0 1 6,growy");
add(scrollPane14, "cell 3 0,grow");
//---- progressBar3 ----
progressBar3.setOrientation(SwingConstants.VERTICAL);
progressBar3.setValue(50);
add(progressBar3, "cell 4 0 1 4,growy");
progressBar3.setValue(60);
add(progressBar3, "cell 4 0 1 6,growy");
//---- progressBar4 ----
progressBar4.setOrientation(SwingConstants.VERTICAL);
progressBar4.setValue(55);
progressBar4.setValue(60);
progressBar4.setStringPainted(true);
add(progressBar4, "cell 4 0 1 4,growy");
add(progressBar4, "cell 4 0 1 6,growy");
//======== toolBar2 ========
{
@@ -178,7 +201,7 @@ class MoreComponentsPanel
toggleButton7.setIcon(UIManager.getIcon("Tree.closedIcon"));
toolBar2.add(toggleButton7);
}
add(toolBar2, "cell 4 0 1 4,growy");
add(toolBar2, "cell 4 0 1 6,growy");
//---- scrollBarLabel ----
scrollBarLabel.setText("JScrollBar:");
@@ -193,30 +216,41 @@ class MoreComponentsPanel
scrollBar4.setEnabled(false);
add(scrollBar4, "cell 1 2,growx");
//---- scrollBar5 ----
scrollBar5.setOrientation(Adjustable.HORIZONTAL);
scrollBar5.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar5, "cell 1 3,growx");
//---- scrollBar6 ----
scrollBar6.setOrientation(Adjustable.HORIZONTAL);
scrollBar6.setEnabled(false);
scrollBar6.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar6, "cell 1 4,growx");
//---- separatorLabel ----
separatorLabel.setText("JSeparator:");
add(separatorLabel, "cell 0 3");
add(separator1, "cell 1 3,growx");
add(separatorLabel, "cell 0 5");
add(separator1, "cell 1 5,growx");
//======== panel2 ========
{
panel2.setBorder(new TitledBorder("TitledBorder"));
panel2.setLayout(new FlowLayout());
}
add(panel2, "cell 3 3,grow");
add(panel2, "cell 3 5,grow");
//---- sliderLabel ----
sliderLabel.setText("JSlider:");
add(sliderLabel, "cell 0 4");
add(sliderLabel, "cell 0 6");
//---- slider1 ----
slider1.setValue(30);
add(slider1, "cell 1 4 3 1,aligny top,grow 100 0");
add(slider1, "cell 1 6 3 1,aligny top,grow 100 0");
//---- slider6 ----
slider6.setEnabled(false);
slider6.setValue(30);
add(slider6, "cell 1 4 3 1,aligny top,growy 0");
add(slider6, "cell 1 6 3 1,aligny top,growy 0");
//---- slider3 ----
slider3.setMinorTickSpacing(10);
@@ -224,7 +258,8 @@ class MoreComponentsPanel
slider3.setMajorTickSpacing(50);
slider3.setPaintLabels(true);
slider3.setValue(30);
add(slider3, "cell 1 5 3 1,aligny top,grow 100 0");
slider3.addChangeListener(e -> changeProgress());
add(slider3, "cell 1 7 3 1,aligny top,grow 100 0");
//---- slider5 ----
slider5.setMinorTickSpacing(10);
@@ -233,41 +268,41 @@ class MoreComponentsPanel
slider5.setPaintLabels(true);
slider5.setEnabled(false);
slider5.setValue(30);
add(slider5, "cell 1 5 3 1,aligny top,growy 0");
add(slider5, "cell 1 7 3 1,aligny top,growy 0");
//---- progressBarLabel ----
progressBarLabel.setText("JProgressBar:");
add(progressBarLabel, "cell 0 6");
add(progressBarLabel, "cell 0 8");
//---- progressBar1 ----
progressBar1.setValue(50);
add(progressBar1, "cell 1 6 3 1,growx");
progressBar1.setValue(60);
add(progressBar1, "cell 1 8 3 1,growx");
//---- progressBar2 ----
progressBar2.setStringPainted(true);
progressBar2.setValue(55);
add(progressBar2, "cell 1 6 3 1,growx");
progressBar2.setValue(60);
add(progressBar2, "cell 1 8 3 1,growx");
//---- indeterminateCheckBox ----
indeterminateCheckBox.setText("indeterminate");
indeterminateCheckBox.addActionListener(e -> indeterminateCheckBoxActionPerformed());
add(indeterminateCheckBox, "cell 4 6");
add(indeterminateCheckBox, "cell 4 8");
//---- toolTipLabel ----
toolTipLabel.setText("JToolTip:");
add(toolTipLabel, "cell 0 7");
add(toolTipLabel, "cell 0 9");
//---- toolTip1 ----
toolTip1.setTipText("Some text in tool tip.");
add(toolTip1, "cell 1 7 3 1");
add(toolTip1, "cell 1 9 3 1");
//---- toolTip2 ----
toolTip2.setTipText("Tool tip with\nmultiple\nlines.");
add(toolTip2, "cell 1 7 3 1");
add(toolTip2, "cell 1 9 3 1");
//---- toolBarLabel ----
toolBarLabel.setText("JToolBar:");
add(toolBarLabel, "cell 0 8");
add(toolBarLabel, "cell 0 10");
//======== toolBar1 ========
{
@@ -297,13 +332,14 @@ class MoreComponentsPanel
toggleButton6.setSelected(true);
toolBar1.add(toggleButton6);
}
add(toolBar1, "cell 1 8 3 1,growx");
add(toolBar1, "cell 1 10 3 1,growx");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// 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;

View File

@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[][][][][][]"
"$rowConstraints": "[][][][][][][][][]"
"$rowConstraints": "[][][][][][][][][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -32,26 +32,39 @@ new FormModel {
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 4,growy"
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar3"
"enabled": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 4,growy"
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar7"
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar8"
"enabled": false
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSeparator" ) {
name: "separator2"
"orientation": 1
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 4,growy"
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider2"
"orientation": 1
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 4,growy"
"value": "cell 2 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider4"
@@ -62,7 +75,7 @@ new FormModel {
"orientation": 1
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 4,growy"
"value": "cell 2 0 1 6,growy"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane14"
@@ -72,23 +85,23 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar3"
"orientation": 1
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0 1 4,growy"
"value": "cell 4 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar4"
"orientation": 1
"value": 55
"value": 60
"stringPainted": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0 1 4,growy"
"value": "cell 4 0 1 6,growy"
} )
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
name: "toolBar2"
@@ -113,7 +126,7 @@ new FormModel {
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.closedIcon" )
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0 1 4,growy"
"value": "cell 4 0 1 6,growy"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "scrollBarLabel"
@@ -134,41 +147,56 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2,growx"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar5"
"orientation": 0
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3,growx"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar6"
"orientation": 0
"enabled": false
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "separatorLabel"
"text": "JSeparator:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
"value": "cell 0 5"
} )
add( new FormComponent( "javax.swing.JSeparator" ) {
name: "separator1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3,growx"
"value": "cell 1 5,growx"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": new javax.swing.border.TitledBorder( "TitledBorder" )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 3,grow"
"value": "cell 3 5,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "sliderLabel"
"text": "JSlider:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
"value": "cell 0 6"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider1"
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4 3 1,aligny top,grow 100 0"
"value": "cell 1 6 3 1,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider6"
"enabled": false
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4 3 1,aligny top,growy 0"
"value": "cell 1 6 3 1,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider3"
@@ -177,8 +205,12 @@ 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 5 3 1,aligny top,grow 100 0"
"value": "cell 1 7 3 1,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider5"
@@ -189,32 +221,32 @@ new FormModel {
"enabled": false
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5 3 1,aligny top,growy 0"
"value": "cell 1 7 3 1,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "progressBarLabel"
"text": "JProgressBar:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6"
"value": "cell 0 8"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar1"
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6 3 1,growx"
"value": "cell 1 8 3 1,growx"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar2"
"stringPainted": true
"value": 55
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6 3 1,growx"
"value": "cell 1 8 3 1,growx"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "indeterminateCheckBox"
@@ -224,31 +256,31 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateCheckBoxActionPerformed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 6"
"value": "cell 4 8"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolTipLabel"
"text": "JToolTip:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 7"
"value": "cell 0 9"
} )
add( new FormComponent( "javax.swing.JToolTip" ) {
name: "toolTip1"
"tipText": "Some text in tool tip."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7 3 1"
"value": "cell 1 9 3 1"
} )
add( new FormComponent( "javax.swing.JToolTip" ) {
name: "toolTip2"
"tipText": "Tool tip with\nmultiple\nlines."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7 3 1"
"value": "cell 1 9 3 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolBarLabel"
"text": "JToolBar:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 8"
"value": "cell 0 10"
} )
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
name: "toolBar1"
@@ -282,7 +314,7 @@ new FormModel {
"selected": true
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 8 3 1,growx"
"value": "cell 1 10 3 1,growx"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )

View File

@@ -5,6 +5,7 @@
package com.formdev.flatlaf.demo;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -29,6 +30,14 @@ class TabsPanel
tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy );
}
private void showTabSeparatorsChanged() {
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane2.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane3.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane4.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
}
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
@@ -96,6 +105,7 @@ class TabsPanel
JPanel panel14 = new JPanel();
moreTabsCheckBox = new JCheckBox();
tabScrollCheckBox = new JCheckBox();
showTabSeparatorsCheckBox = new JCheckBox();
hasFullBorderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
@@ -285,6 +295,7 @@ class TabsPanel
// columns
"[]" +
"[]" +
"[]" +
"[]",
// rows
"[center]"));
@@ -301,11 +312,16 @@ class TabsPanel
tabScrollCheckBox.addActionListener(e -> tabScrollChanged());
panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0");
//---- showTabSeparatorsCheckBox ----
showTabSeparatorsCheckBox.setText("JTabbedPane.showTabSeparators");
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
panel14.add(showTabSeparatorsCheckBox, "cell 2 0");
//---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder");
hasFullBorderCheckBox.setMnemonic('F');
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0");
panel14.add(hasFullBorderCheckBox, "cell 3 0,alignx left,growx 0");
}
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
}
@@ -320,6 +336,7 @@ class TabsPanel
private JTabbedPane tabbedPane4;
private JCheckBox moreTabsCheckBox;
private JCheckBox tabScrollCheckBox;
private JCheckBox showTabSeparatorsCheckBox;
private JCheckBox hasFullBorderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -199,7 +199,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][][]"
"$columnConstraints": "[][][][]"
"$rowConstraints": "[center]"
} ) {
name: "panel14"
@@ -225,6 +225,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTabSeparatorsCheckBox"
"text": "JTabbedPane.showTabSeparators"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox"
"text": "JTabbedPane.hasFullBorder"
@@ -234,7 +244,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0,alignx left,growx 0"
"value": "cell 3 0,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11
@@ -245,7 +255,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
"size": new java.awt.Dimension( 610, 515 )
} )
}
}

View File

@@ -37,6 +37,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.event.*;
@@ -46,6 +47,7 @@ import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.DemoPrefs;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.util.StringUtils;
import net.miginfocom.swing.*;
@@ -222,12 +224,15 @@ public class IJThemesPanel
} else if( themeInfo.themeFile != null ) {
try {
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_INTELLIJ_THEME, DemoPrefs.FILE_PREFIX + themeInfo.themeFile );
} catch( Exception ex ) {
ex.printStackTrace();
showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex );
}
} else
} else {
IntelliJTheme.install( getClass().getResourceAsStream( themeInfo.resourceName ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_INTELLIJ_THEME, DemoPrefs.RESOURCE_PREFIX + themeInfo.resourceName );
}
// update all components
FlatLaf.updateUI();
@@ -326,22 +331,36 @@ public class IJThemesPanel
private void selectedCurrentLookAndFeel() {
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
String intelliJTheme = UIManager.getLookAndFeelDefaults().getString( DemoPrefs.INTELLIJ_THEME_UI_KEY );
if( intelliJTheme == null && lookAndFeel instanceof IntelliJTheme.ThemeLaf )
return;
Predicate<IJThemeInfo> test;
if( intelliJTheme != null && intelliJTheme.startsWith( DemoPrefs.RESOURCE_PREFIX ) ) {
String resourceName = intelliJTheme.substring( DemoPrefs.RESOURCE_PREFIX.length() );
test = ti -> Objects.equals( ti.resourceName, resourceName );
} else if( intelliJTheme != null && intelliJTheme.startsWith( DemoPrefs.FILE_PREFIX ) ) {
File themeFile = new File( intelliJTheme.substring( DemoPrefs.FILE_PREFIX.length() ) );
test = ti -> Objects.equals( ti.themeFile, themeFile );
} else {
String lafClassName = lookAndFeel.getClass().getName();
test = ti -> Objects.equals( ti.lafClassName, lafClassName );
}
int newSel = -1;
if( !(lookAndFeel instanceof IntelliJTheme.ThemeLaf) ) {
String lafClassName = lookAndFeel.getClass().getName();
for( int i = 0; i < themes.size(); i++ ) {
if( lafClassName.equals( themes.get( i ).lafClassName ) ) {
newSel = i;
break;
}
for( int i = 0; i < themes.size(); i++ ) {
if( test.test( themes.get( i ) ) ) {
newSel = i;
break;
}
if( newSel >= 0 )
themesList.setSelectedIndex( newSel );
else
themesList.clearSelection();
}
if( newSel >= 0 ) {
if( newSel != themesList.getSelectedIndex() )
themesList.setSelectedIndex( newSel );
} else
themesList.clearSelection();
}
private void initComponents() {

View File

@@ -26,7 +26,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf-jide-oss
version: 0.20
version: 0.22
Otherwise download `flatlaf-jide-oss-<version>.jar` here:

View File

@@ -17,7 +17,7 @@
package com.formdev.flatlaf.jideoss.ui;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyEquals;
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
@@ -181,7 +181,7 @@ public class FlatJideTabbedPaneUI
}
private Insets getContentBorderInsets0( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( _tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
@@ -339,7 +339,7 @@ public class FlatJideTabbedPaneUI
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( _tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );

View File

@@ -33,7 +33,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf-swingx
version: 0.20
version: 0.22
Otherwise download `flatlaf-swingx-<version>.jar` here:

View File

@@ -237,7 +237,7 @@ public class FlatDatePickerUI
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
@@ -247,7 +247,7 @@ public class FlatDatePickerUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -255,7 +255,7 @@ public class FlatDatePickerUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
paint( g, c );
}

View File

@@ -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 );
@@ -85,21 +93,25 @@ public class FlatComponentsTest
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JComboBox<String> comboBox7 = new JComboBox<>();
JLabel textFieldLabel = new JLabel();
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField4 = new JTextField();
JTextField textField6 = new JTextField();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField2 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
JFormattedTextField formattedTextField4 = new JFormattedTextField();
JFormattedTextField formattedTextField5 = new JFormattedTextField();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField2 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
JPasswordField passwordField4 = new JPasswordField();
JPasswordField passwordField5 = new JPasswordField();
JLabel textAreaLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JTextArea textArea1 = new JTextArea();
@@ -135,6 +147,8 @@ public class FlatComponentsTest
JPanel panel1 = new JPanel();
JScrollBar scrollBar2 = new JScrollBar();
JScrollBar scrollBar3 = new JScrollBar();
JScrollBar scrollBar7 = new JScrollBar();
JScrollBar scrollBar8 = new JScrollBar();
JSeparator separator2 = new JSeparator();
JSlider slider2 = new JSlider();
JSlider slider4 = new JSlider();
@@ -156,13 +170,15 @@ public class FlatComponentsTest
JEditorPane editorPane6 = new JEditorPane();
JScrollPane scrollPane16 = new JScrollPane();
JTextPane textPane6 = new JTextPane();
JScrollBar scrollBar5 = new JScrollBar();
JScrollBar scrollBar6 = new JScrollBar();
JLabel separatorLabel = new JLabel();
JSeparator separator1 = new JSeparator();
JPanel panel2 = new JPanel();
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();
@@ -211,6 +227,8 @@ public class FlatComponentsTest
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- labelLabel ----
@@ -433,6 +451,11 @@ public class FlatComponentsTest
spinner2.setEnabled(false);
add(spinner2, "cell 2 6,growx");
//---- comboBox7 ----
comboBox7.setEditable(true);
comboBox7.putClientProperty("JTextField.placeholderText", "placeholder");
add(comboBox7, "cell 5 6,growx");
//---- textFieldLabel ----
textFieldLabel.setText("JTextField:");
add(textFieldLabel, "cell 0 7");
@@ -457,6 +480,10 @@ public class FlatComponentsTest
textField4.setEditable(false);
add(textField4, "cell 4 7,growx");
//---- textField6 ----
textField6.putClientProperty("JTextField.placeholderText", "placeholder");
add(textField6, "cell 5 7,growx");
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
add(formattedTextFieldLabel, "cell 0 8");
@@ -481,6 +508,10 @@ public class FlatComponentsTest
formattedTextField4.setEditable(false);
add(formattedTextField4, "cell 4 8,growx");
//---- formattedTextField5 ----
formattedTextField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(formattedTextField5, "cell 5 8,growx");
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
add(passwordFieldLabel, "cell 0 9");
@@ -505,6 +536,10 @@ public class FlatComponentsTest
passwordField4.setEditable(false);
add(passwordField4, "cell 4 9,growx");
//---- passwordField5 ----
passwordField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(passwordField5, "cell 5 9,growx");
//---- textAreaLabel ----
textAreaLabel.setText("JTextArea:");
add(textAreaLabel, "cell 0 10");
@@ -695,20 +730,29 @@ public class FlatComponentsTest
scrollPane13.setViewportView(panel1);
}
add(scrollPane13, "cell 1 13,grow,width 70,height 70");
add(scrollBar2, "cell 2 13 1 4,growy");
add(scrollBar2, "cell 2 13 1 6,growy");
//---- scrollBar3 ----
scrollBar3.setEnabled(false);
add(scrollBar3, "cell 2 13 1 4,growy");
add(scrollBar3, "cell 2 13 1 6,growy");
//---- scrollBar7 ----
scrollBar7.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar7, "cell 2 13 1 6,growy");
//---- scrollBar8 ----
scrollBar8.setEnabled(false);
scrollBar8.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar8, "cell 2 13 1 6,growy");
//---- separator2 ----
separator2.setOrientation(SwingConstants.VERTICAL);
add(separator2, "cell 2 13 1 4,growy");
add(separator2, "cell 2 13 1 6,growy");
//---- slider2 ----
slider2.setOrientation(SwingConstants.VERTICAL);
slider2.setValue(30);
add(slider2, "cell 2 13 1 4,growy");
add(slider2, "cell 2 13 1 6,growy");
//---- slider4 ----
slider4.setMinorTickSpacing(10);
@@ -717,19 +761,19 @@ public class FlatComponentsTest
slider4.setPaintLabels(true);
slider4.setOrientation(SwingConstants.VERTICAL);
slider4.setValue(30);
add(slider4, "cell 2 13 1 4,growy");
add(slider4, "cell 2 13 1 6,growy");
add(scrollPane14, "cell 3 13,grow");
//---- progressBar3 ----
progressBar3.setOrientation(SwingConstants.VERTICAL);
progressBar3.setValue(50);
add(progressBar3, "cell 4 13 1 4,growy");
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 4,growy");
add(progressBar4, "cell 4 13 1 6,growy");
//======== toolBar2 ========
{
@@ -752,7 +796,7 @@ public class FlatComponentsTest
toggleButton7.setIcon(UIManager.getIcon("Tree.closedIcon"));
toolBar2.add(toggleButton7);
}
add(toolBar2, "cell 4 13 1 4,growy");
add(toolBar2, "cell 4 13 1 6,growy");
//---- scrollBarLabel ----
scrollBarLabel.setText("JScrollBar:");
@@ -807,12 +851,23 @@ public class FlatComponentsTest
}
panel3.add(scrollPane16, "cell 0 2,grow");
}
add(panel3, "cell 5 15 1 7,aligny top,grow 100 0");
add(panel3, "cell 5 15 1 9,aligny top,grow 100 0");
//---- scrollBar5 ----
scrollBar5.setOrientation(Adjustable.HORIZONTAL);
scrollBar5.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar5, "cell 1 16,growx");
//---- scrollBar6 ----
scrollBar6.setOrientation(Adjustable.HORIZONTAL);
scrollBar6.setEnabled(false);
scrollBar6.putClientProperty("JScrollBar.showButtons", true);
add(scrollBar6, "cell 1 17,growx");
//---- separatorLabel ----
separatorLabel.setText("JSeparator:");
add(separatorLabel, "cell 0 16");
add(separator1, "cell 1 16,growx");
add(separatorLabel, "cell 0 18");
add(separator1, "cell 1 18,growx");
//======== panel2 ========
{
@@ -820,20 +875,20 @@ public class FlatComponentsTest
panel2.setOpaque(false);
panel2.setLayout(new FlowLayout());
}
add(panel2, "cell 3 16,grow");
add(panel2, "cell 3 18,grow");
//---- sliderLabel ----
sliderLabel.setText("JSlider:");
add(sliderLabel, "cell 0 17");
add(sliderLabel, "cell 0 19");
//---- slider1 ----
slider1.setValue(30);
add(slider1, "cell 1 17 3 1,aligny top,grow 100 0");
add(slider1, "cell 1 19 3 1,aligny top,grow 100 0");
//---- slider6 ----
slider6.setEnabled(false);
slider6.setValue(30);
add(slider6, "cell 1 17 3 1,aligny top,growy 0");
add(slider6, "cell 1 19 3 1,aligny top,growy 0");
//---- slider3 ----
slider3.setMinorTickSpacing(10);
@@ -841,7 +896,8 @@ public class FlatComponentsTest
slider3.setMajorTickSpacing(50);
slider3.setPaintLabels(true);
slider3.setValue(30);
add(slider3, "cell 1 18 3 1,aligny top,grow 100 0");
slider3.addChangeListener(e -> changeProgress());
add(slider3, "cell 1 20 3 1,aligny top,grow 100 0");
//---- slider5 ----
slider5.setMinorTickSpacing(10);
@@ -850,41 +906,41 @@ public class FlatComponentsTest
slider5.setPaintLabels(true);
slider5.setEnabled(false);
slider5.setValue(30);
add(slider5, "cell 1 18 3 1,aligny top,growy 0");
add(slider5, "cell 1 20 3 1,aligny top,growy 0");
//---- progressBarLabel ----
progressBarLabel.setText("JProgressBar:");
add(progressBarLabel, "cell 0 19");
add(progressBarLabel, "cell 0 21");
//---- progressBar1 ----
progressBar1.setValue(50);
add(progressBar1, "cell 1 19 3 1,growx");
progressBar1.setValue(60);
add(progressBar1, "cell 1 21 3 1,growx");
//---- progressBar2 ----
progressBar2.setStringPainted(true);
progressBar2.setValue(55);
add(progressBar2, "cell 1 19 3 1,growx");
progressBar2.setValue(60);
add(progressBar2, "cell 1 21 3 1,growx");
//---- indeterminateCheckBox ----
indeterminateCheckBox.setText("indeterminate");
indeterminateCheckBox.addActionListener(e -> indeterminateCheckBoxActionPerformed());
add(indeterminateCheckBox, "cell 4 19");
indeterminateCheckBox.addActionListener(e -> indeterminateProgress());
add(indeterminateCheckBox, "cell 4 21");
//---- toolTipLabel ----
toolTipLabel.setText("JToolTip:");
add(toolTipLabel, "cell 0 20");
add(toolTipLabel, "cell 0 22");
//---- toolTip1 ----
toolTip1.setTipText("Some text in tool tip.");
add(toolTip1, "cell 1 20 3 1");
add(toolTip1, "cell 1 22 3 1");
//---- toolTip2 ----
toolTip2.setTipText("Tool tip with\nmultiple\nlines.");
add(toolTip2, "cell 1 20 3 1");
add(toolTip2, "cell 1 22 3 1");
//---- toolBarLabel ----
toolBarLabel.setText("JToolBar:");
add(toolBarLabel, "cell 0 21");
add(toolBarLabel, "cell 0 23");
//======== toolBar1 ========
{
@@ -914,7 +970,7 @@ public class FlatComponentsTest
toggleButton6.setSelected(true);
toolBar1.add(toggleButton6);
}
add(toolBar1, "cell 1 21 3 1,growx");
add(toolBar1, "cell 1 23 3 1,growx");
// JFormDesigner - End of component initialization //GEN-END:initComponents
// BasicComboBoxRenderer customaRenderer = new BasicComboBoxRenderer();
@@ -926,6 +982,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;

View File

@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][][][][]"
"$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][]"
"$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -313,6 +313,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 6,growx"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox7"
"editable": true
"$client.JTextField.placeholderText": "placeholder"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 6,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textFieldLabel"
"text": "JTextField:"
@@ -347,6 +357,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 7,growx"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField6"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 7,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -381,6 +397,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 8,growx"
} )
add( new FormComponent( "javax.swing.JFormattedTextField" ) {
name: "formattedTextField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 8,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -415,6 +437,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 9,growx"
} )
add( new FormComponent( "javax.swing.JPasswordField" ) {
name: "passwordField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 9,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textAreaLabel"
"text": "JTextArea:"
@@ -620,26 +648,39 @@ new FormModel {
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 4,growy"
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar3"
"enabled": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 4,growy"
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar7"
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar8"
"enabled": false
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSeparator" ) {
name: "separator2"
"orientation": 1
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 4,growy"
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider2"
"orientation": 1
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 4,growy"
"value": "cell 2 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider4"
@@ -650,7 +691,7 @@ new FormModel {
"orientation": 1
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13 1 4,growy"
"value": "cell 2 13 1 6,growy"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane14"
@@ -660,23 +701,23 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar3"
"orientation": 1
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 13 1 4,growy"
"value": "cell 4 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar4"
"orientation": 1
"value": 55
"value": 60
"stringPainted": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 13 1 4,growy"
"value": "cell 4 13 1 6,growy"
} )
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
name: "toolBar2"
@@ -701,7 +742,7 @@ new FormModel {
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.closedIcon" )
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 13 1 4,growy"
"value": "cell 4 13 1 6,growy"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "scrollBarLabel"
@@ -762,44 +803,59 @@ new FormModel {
"value": "cell 0 2,grow"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 15 1 7,aligny top,grow 100 0"
"value": "cell 5 15 1 9,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar5"
"orientation": 0
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16,growx"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar6"
"orientation": 0
"enabled": false
"$client.JScrollBar.showButtons": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 17,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "separatorLabel"
"text": "JSeparator:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 16"
"value": "cell 0 18"
} )
add( new FormComponent( "javax.swing.JSeparator" ) {
name: "separator1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16,growx"
"value": "cell 1 18,growx"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": new javax.swing.border.TitledBorder( "TitledBorder" )
"opaque": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 16,grow"
"value": "cell 3 18,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "sliderLabel"
"text": "JSlider:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 17"
"value": "cell 0 19"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider1"
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 17 3 1,aligny top,grow 100 0"
"value": "cell 1 19 3 1,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider6"
"enabled": false
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 17 3 1,aligny top,growy 0"
"value": "cell 1 19 3 1,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider3"
@@ -808,8 +864,12 @@ 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 18 3 1,aligny top,grow 100 0"
"value": "cell 1 20 3 1,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider5"
@@ -820,32 +880,32 @@ new FormModel {
"enabled": false
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 18 3 1,aligny top,growy 0"
"value": "cell 1 20 3 1,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "progressBarLabel"
"text": "JProgressBar:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 19"
"value": "cell 0 21"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar1"
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 19 3 1,growx"
"value": "cell 1 21 3 1,growx"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar2"
"stringPainted": true
"value": 55
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 19 3 1,growx"
"value": "cell 1 21 3 1,growx"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "indeterminateCheckBox"
@@ -853,33 +913,33 @@ 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 19"
"value": "cell 4 21"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolTipLabel"
"text": "JToolTip:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 20"
"value": "cell 0 22"
} )
add( new FormComponent( "javax.swing.JToolTip" ) {
name: "toolTip1"
"tipText": "Some text in tool tip."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 20 3 1"
"value": "cell 1 22 3 1"
} )
add( new FormComponent( "javax.swing.JToolTip" ) {
name: "toolTip2"
"tipText": "Tool tip with\nmultiple\nlines."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 20 3 1"
"value": "cell 1 22 3 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "toolBarLabel"
"text": "JToolBar:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 21"
"value": "cell 0 23"
} )
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
name: "toolBar1"
@@ -913,11 +973,11 @@ new FormModel {
"selected": true
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 21 3 1,growx"
"value": "cell 1 23 3 1,growx"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 750 )
"size": new java.awt.Dimension( 865, 750 )
} )
}
}

View File

@@ -5,6 +5,7 @@
package com.formdev.flatlaf.testing;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -36,6 +37,14 @@ public class FlatContainerTest
tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy );
}
private void showTabSeparatorsChanged() {
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane2.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane3.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane4.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
}
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
@@ -100,6 +109,7 @@ public class FlatContainerTest
JPanel panel14 = new JPanel();
moreTabsCheckBox = new JCheckBox();
tabScrollCheckBox = new JCheckBox();
showTabSeparatorsCheckBox = new JCheckBox();
hasFullBorderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
@@ -291,6 +301,7 @@ public class FlatContainerTest
// columns
"[]" +
"[]" +
"[]" +
"[]",
// rows
"[center]"));
@@ -307,11 +318,16 @@ public class FlatContainerTest
tabScrollCheckBox.addActionListener(e -> tabScrollChanged());
panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0");
//---- showTabSeparatorsCheckBox ----
showTabSeparatorsCheckBox.setText("JTabbedPane.showTabSeparators");
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
panel14.add(showTabSeparatorsCheckBox, "cell 2 0");
//---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder");
hasFullBorderCheckBox.setMnemonic('F');
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0");
panel14.add(hasFullBorderCheckBox, "cell 3 0,alignx left,growx 0");
}
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
}
@@ -326,6 +342,7 @@ public class FlatContainerTest
private JTabbedPane tabbedPane4;
private JCheckBox moreTabsCheckBox;
private JCheckBox tabScrollCheckBox;
private JCheckBox showTabSeparatorsCheckBox;
private JCheckBox hasFullBorderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -200,7 +200,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][][]"
"$columnConstraints": "[][][][]"
"$rowConstraints": "[center]"
} ) {
name: "panel14"
@@ -227,6 +227,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTabSeparatorsCheckBox"
"text": "JTabbedPane.showTabSeparators"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox"
"text": "JTabbedPane.hasFullBorder"
@@ -236,7 +246,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0,alignx left,growx 0"
"value": "cell 3 0,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11
@@ -247,7 +257,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
"size": new java.awt.Dimension( 625, 515 )
} )
}
}

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.testing;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
@@ -25,9 +26,16 @@ import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.lang.reflect.Field;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
@@ -35,6 +43,8 @@ import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.JToolBar;
import javax.swing.JToolTip;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
@@ -53,7 +63,10 @@ public class FlatInspector
private static final Integer HIGHLIGHT_LAYER = 401;
private static final Integer TOOLTIP_LAYER = 402;
private static final int KEY_MODIFIERS_MASK = InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK;
private final JRootPane rootPane;
private final MouseMotionListener mouseMotionListener;
private Component lastComponent;
private int lastX;
@@ -63,10 +76,38 @@ public class FlatInspector
private JComponent highlightFigure;
private JToolTip tip;
/**
* Installs a key listener into the application that allows enabling and disabling
* the UI inspector with the given keystroke (e.g. "ctrl shift alt X").
*/
public static void install( String activationKeys ) {
KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys );
Toolkit.getDefaultToolkit().addAWTEventListener( e -> {
if( e.getID() == KeyEvent.KEY_RELEASED &&
((KeyEvent)e).getKeyCode() == keyStroke.getKeyCode() &&
(((KeyEvent)e).getModifiersEx() & KEY_MODIFIERS_MASK) == (keyStroke.getModifiers() & KEY_MODIFIERS_MASK) )
{
Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
if( activeWindow instanceof RootPaneContainer ) {
JRootPane rootPane = ((RootPaneContainer)activeWindow).getRootPane();
FlatInspector inspector = (FlatInspector) rootPane.getClientProperty( FlatInspector.class );
if( inspector == null ) {
inspector = new FlatInspector( rootPane );
rootPane.putClientProperty( FlatInspector.class, inspector );
inspector.setEnabled( true );
} else {
inspector.uninstall();
rootPane.putClientProperty( FlatInspector.class, null );
}
}
}
}, AWTEvent.KEY_EVENT_MASK );
}
public FlatInspector( JRootPane rootPane ) {
this.rootPane = rootPane;
rootPane.getGlassPane().addMouseMotionListener( new MouseMotionAdapter() {
mouseMotionListener = new MouseMotionAdapter() {
@Override
public void mouseMoved( MouseEvent e ) {
lastX = e.getX();
@@ -74,7 +115,15 @@ public class FlatInspector
inspectParent = e.isShiftDown();
inspect( lastX, lastY );
}
} );
};
rootPane.getGlassPane().addMouseMotionListener( mouseMotionListener );
}
private void uninstall() {
setEnabled( false );
rootPane.getGlassPane().setVisible( false );
rootPane.getGlassPane().removeMouseMotionListener( mouseMotionListener );
}
public void setEnabled( boolean enabled ) {
@@ -106,7 +155,8 @@ public class FlatInspector
private void inspect( int x, int y ) {
Container contentPane = rootPane.getContentPane();
Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y );
Point pt = SwingUtilities.convertPoint( rootPane.getGlassPane(), x, y, contentPane );
Component c = SwingUtilities.getDeepestComponentAt( contentPane, pt.x, pt.y );
if( inspectParent && c != null && c != contentPane )
c = c.getParent();
if( c == contentPane || (c != null && c.getParent() == contentPane) )
@@ -182,9 +232,9 @@ public class FlatInspector
// position the tip in the visible area
Rectangle visibleRect = rootPane.getVisibleRect();
if( tx + size.width > visibleRect.x + visibleRect.width )
tx = visibleRect.x + visibleRect.width - size.width;
tx -= size.width + UIScale.scale( 16 );
if( ty + size.height > visibleRect.y + visibleRect.height )
ty = visibleRect.y + visibleRect.height - size.height;
ty -= size.height + UIScale.scale( 32 );
if( tx < visibleRect.x )
tx = visibleRect.x;
if( ty < visibleRect.y )

View File

@@ -0,0 +1,164 @@
/*
* Created by JFormDesigner on Tue Aug 27 21:47:02 CEST 2019
*/
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.beans.PropertyVetoException;
import javax.swing.*;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatInternalFrameTest
extends FlatTestPanel
{
private static final int GAP = 20;
private final int frameX;
private final int frameY;
private int frameCount = 0;
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatInternalFrameTest" );
frame.showFrame( FlatInternalFrameTest::new );
} );
}
public FlatInternalFrameTest() {
initComponents();
frameX = palette.getX() + palette.getWidth() + UIScale.scale( GAP );
frameY = UIScale.scale( GAP );
createInternalFrame();
}
private void createInternalFrame() {
String title = titleField.getText();
if( title.isEmpty() )
title = "Frame " + (frameCount + 1);
JInternalFrame internalFrame = new JInternalFrame( title,
resizableCheckBox.isSelected(),
closableCheckBox.isSelected(),
maximizableCheckBox.isSelected(),
iconifiableCheckBox.isSelected() );
JPanel panel = new JPanel();
panel.setBackground( new Color( (int) (Math.random() * 0xffffff) ) );
internalFrame.setContentPane( panel );
internalFrame.setBounds( frameX + UIScale.scale( GAP ) * (frameCount % 10),
frameY + UIScale.scale( GAP ) * (frameCount % 10), UIScale.scale( 200 ), UIScale.scale( 200 ) );
desktopPane.add( internalFrame, JLayeredPane.DEFAULT_LAYER );
try {
internalFrame.setSelected( true );
} catch( PropertyVetoException ex ) {
// ignore
}
internalFrame.show();
frameCount++;
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
desktopPane = new JDesktopPane();
palette = new JInternalFrame();
resizableCheckBox = new JCheckBox();
closableCheckBox = new JCheckBox();
iconifiableCheckBox = new JCheckBox();
maximizableCheckBox = new JCheckBox();
titleLabel = new JLabel();
titleField = new JTextField();
createFrameButton = new JButton();
//======== this ========
setLayout(new MigLayout(
"insets dialog,hidemode 3",
// columns
"[grow,fill]",
// rows
"[grow,fill]"));
//======== desktopPane ========
{
//======== palette ========
{
palette.setVisible(true);
palette.setTitle("Internal Frame Generator");
palette.setResizable(true);
palette.putClientProperty("JInternalFrame.isPalette", true);
palette.setIconifiable(true);
Container paletteContentPane = palette.getContentPane();
paletteContentPane.setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]" +
"[fill]",
// rows
"[fill]0" +
"[]0" +
"[]unrel" +
"[]unrel"));
//---- resizableCheckBox ----
resizableCheckBox.setText("Resizable");
resizableCheckBox.setSelected(true);
paletteContentPane.add(resizableCheckBox, "cell 0 0,alignx left,growx 0");
//---- closableCheckBox ----
closableCheckBox.setText("Closable");
closableCheckBox.setSelected(true);
paletteContentPane.add(closableCheckBox, "cell 1 0,alignx left,growx 0");
//---- iconifiableCheckBox ----
iconifiableCheckBox.setText("Iconifiable");
iconifiableCheckBox.setSelected(true);
paletteContentPane.add(iconifiableCheckBox, "cell 0 1,alignx left,growx 0");
//---- maximizableCheckBox ----
maximizableCheckBox.setText("Maximizable");
maximizableCheckBox.setSelected(true);
paletteContentPane.add(maximizableCheckBox, "cell 1 1,alignx left,growx 0");
//---- titleLabel ----
titleLabel.setText("Frame title:");
paletteContentPane.add(titleLabel, "cell 0 2");
paletteContentPane.add(titleField, "cell 1 2");
//---- createFrameButton ----
createFrameButton.setText("Create Frame");
createFrameButton.addActionListener(e -> createInternalFrame());
paletteContentPane.add(createFrameButton, "cell 1 3,alignx right,growx 0");
}
desktopPane.add(palette, JLayeredPane.PALETTE_LAYER);
palette.setBounds(15, 25, 220, 160);
}
add(desktopPane, "cell 0 0,width 600,height 600");
// JFormDesigner - End of component initialization //GEN-END:initComponents
if( UIScale.getUserScaleFactor() > 1 )
palette.setSize( UIScale.scale( palette.getSize() ) );
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JDesktopPane desktopPane;
private JInternalFrame palette;
private JCheckBox resizableCheckBox;
private JCheckBox closableCheckBox;
private JCheckBox iconifiableCheckBox;
private JCheckBox maximizableCheckBox;
private JLabel titleLabel;
private JTextField titleField;
private JButton createFrameButton;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,86 @@
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": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
name: "this"
add( new FormContainer( "javax.swing.JDesktopPane", new FormLayoutManager( class javax.swing.JDesktopPane ) ) {
name: "desktopPane"
add( new FormContainer( "javax.swing.JInternalFrame", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill][fill]"
"$rowConstraints": "[fill]0[]0[]unrel[]unrel"
} ) {
name: "palette"
"visible": true
"title": "Internal Frame Generator"
"resizable": true
"$client.JInternalFrame.isPalette": true
"iconifiable": true
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "resizableCheckBox"
"text": "Resizable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "closableCheckBox"
"text": "Closable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "iconifiableCheckBox"
"text": "Iconifiable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maximizableCheckBox"
"text": "Maximizable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "titleLabel"
"text": "Frame title:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "titleField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "createFrameButton"
"text": "Create Frame"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "createInternalFrame", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3,alignx right,growx 0"
} )
}, new FormLayoutConstraints( null ) {
"x": 15
"y": 25
"width": 220
"height": 160
"layer": 100
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,width 600,height 600"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
} )
}
}

View File

@@ -0,0 +1,142 @@
/*
* 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;
import java.awt.Color;
import javax.swing.*;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatSystemColorsTest
extends FlatTestPanel
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSystemColorsTest" );
frame.showFrame( FlatSystemColorsTest::new );
} );
}
FlatSystemColorsTest() {
initComponents();
String[] systemColors = {
"desktop",
"activeCaption",
"activeCaptionText",
"activeCaptionBorder",
"inactiveCaption",
"inactiveCaptionText",
"inactiveCaptionBorder",
"window",
"windowBorder",
"windowText",
"menu",
"menuText",
"text",
"textText",
"textHighlight",
"textHighlightText",
"textInactiveText",
"control",
"controlText",
"controlHighlight",
"controlLtHighlight",
"controlShadow",
"controlDkShadow",
"scrollbar",
"info",
"infoText",
};
for( String systemColor : systemColors ) {
systemColorsPanel.add( new JLabel( systemColor ) );
systemColorsPanel.add( new Preview( systemColor ), "wrap" );
}
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
systemColorsPanel = new JPanel();
//======== this ========
setLayout(new MigLayout(
"ltr,insets dialog,hidemode 3",
// columns
"[fill]",
// rows
"[grow,fill]"));
//======== systemColorsPanel ========
{
systemColorsPanel.setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]",
// rows
"[]"));
}
add(systemColorsPanel, "cell 0 0");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JPanel systemColorsPanel;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class Preview ----
private static class Preview
extends JPanel
{
private final String colorKey;
private final JPanel colorPreview;
private final JLabel colorCode;
Preview( String colorKey ) {
super( new MigLayout( "ltr,insets 0", "[50,fill][]", "[fill]0" ) );
this.colorKey = colorKey;
colorPreview = new JPanel();
colorPreview.setOpaque( true );
colorCode = new JLabel();
add( colorPreview );
add( colorCode, "wrap" );
update();
}
@Override
public void updateUI() {
super.updateUI();
update();
}
private void update() {
if( colorKey == null )
return; // called from constructor
Color color = UIManager.getColor( colorKey );
colorPreview.setBackground( (color != null) ? new Color( color.getRGB(), true ) : null );
colorCode.setText( (color != null) ? String.format( "#%06x", color.getRGB() & 0xffffff ) : "-" );
}
}
}

View File

@@ -0,0 +1,32 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[grow,fill]"
} ) {
name: "this"
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]"
} ) {
name: "systemColorsPanel"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 415, 350 )
} )
}
}

View File

@@ -24,7 +24,6 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource;
@@ -37,6 +36,7 @@ import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.LookAndFeelsComboBox;
import com.formdev.flatlaf.demo.DemoPrefs;
import com.formdev.flatlaf.demo.intellijthemes.*;
import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.extras.TriStateCheckBox.State;
@@ -52,7 +52,6 @@ public class FlatTestFrame
extends JFrame
{
private static final String PREFS_ROOT_PATH = "/flatlaf-test";
private static final String KEY_LAF = "laf";
private static final String KEY_SCALE_FACTOR = "scaleFactor";
private final String title;
@@ -63,29 +62,17 @@ public class FlatTestFrame
public boolean useApplyComponentOrientation;
public static FlatTestFrame create( String[] args, String title ) {
Preferences prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
DemoPrefs.init( PREFS_ROOT_PATH );
// set scale factor
if( System.getProperty( "flatlaf.uiScale", System.getProperty( "sun.java2d.uiScale" ) ) == null ) {
String scaleFactor = prefs.get( KEY_SCALE_FACTOR, null );
String scaleFactor = DemoPrefs.getState().get( KEY_SCALE_FACTOR, null );
if( scaleFactor != null )
System.setProperty( "flatlaf.uiScale", scaleFactor );
}
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
DemoPrefs.initLaf( args );
// create frame
return new FlatTestFrame( title );
@@ -156,6 +143,9 @@ public class FlatTestFrame
KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
// make the "close" button the default button
getRootPane().setDefaultButton( closeButton );
// close frame
closeButton.addActionListener(e -> dispose());
@@ -183,6 +173,9 @@ public class FlatTestFrame
// enable/disable scale factor combobox
updateScaleFactorComboBox();
// this is necessary because embedded JOptionPane's "steal" the default button
getRootPane().setDefaultButton( closeButton );
} );
}
} );
@@ -239,8 +232,6 @@ public class FlatTestFrame
// hide popup to avoid occasional StackOverflowError when updating UI
lookAndFeelComboBox.setPopupVisible( false );
Preferences.userRoot().node( PREFS_ROOT_PATH ).put( KEY_LAF, lafClassName );
applyLookAndFeel( lafClassName, null, false );
}
@@ -358,14 +349,12 @@ public class FlatTestFrame
// hide popup to avoid occasional StackOverflowError when updating UI
scaleFactorComboBox.setPopupVisible( false );
Preferences prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
if( scaleFactor != null ) {
System.setProperty( "flatlaf.uiScale", scaleFactor );
prefs.put( KEY_SCALE_FACTOR, scaleFactor );
DemoPrefs.getState().put( KEY_SCALE_FACTOR, scaleFactor );
} else {
System.clearProperty( "flatlaf.uiScale" );
prefs.remove( KEY_SCALE_FACTOR );
DemoPrefs.getState().remove( KEY_SCALE_FACTOR );
}
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();

View File

@@ -19,6 +19,7 @@
@background=#ccffcc
@foreground=#ff0000
@selectionBackground=#00aa00
@selectionForeground=#ffff00
@selectionInactiveBackground=#888888
@selectionInactiveForeground=#ffffff
@disabledText=#000088
@@ -37,7 +38,7 @@
*.inactiveBackground=#f0f0f0
*.inactiveForeground=#000088
*.selectionBackground=@selectionBackground
*.selectionForeground=#ffff00
*.selectionForeground=@selectionForeground
*.disabledBackground=#e0e0e0
*.disabledForeground=@disabledText
*.disabledText=@disabledText
@@ -45,24 +46,38 @@
*.acceleratorSelectionForeground=#ffffff
#---- system colors ----
activeCaption=#99b4d1
inactiveCaption=#bfcddb
controlHighlight=#e3e3e3
controlLtHighlight=#fff
controlShadow=#a0a0a0
controlDkShadow=#696969
#---- Button ----
Button.background=#ffffff
Button.startBackground=#fff
Button.endBackground=#bbb
Button.focusedBackground=#00ffff
Button.hoverBackground=#ffff00
Button.pressedBackground=#FFC800
Button.borderColor=#0000ff
Button.startBorderColor=#00f
Button.endBorderColor=#f00
Button.disabledBorderColor=#000088
Button.focusedBorderColor=#466d94
Button.hoverBorderColor=#ff0000
Button.default.background=#dddddd
Button.default.startBackground=#ddd
Button.default.endBackground=#888
Button.default.foreground=#880000
Button.default.focusedBackground=#00ffff
Button.default.hoverBackground=#ffff00
Button.default.pressedBackground=#FFC800
Button.default.borderColor=#ff0000
Button.default.startBorderColor=#f00
Button.default.endBorderColor=#00f
Button.default.hoverBorderColor=#ff0000
Button.default.focusedBorderColor=#537699
Button.default.focusColor=#ff0000
@@ -214,10 +229,13 @@ SplitPaneDivider.oneTouchHoverArrowColor=#ff0000
#---- TabbedPane ----
TabbedPane.disabledForeground=#777777
TabbedPane.selectedBackground=#0f0
TabbedPane.selectedForeground=#00f
TabbedPane.underlineColor=#4A88C7
TabbedPane.disabledUnderlineColor=#7a7a7a
TabbedPane.hoverColor=#eeeeee
TabbedPane.focusColor=#dddddd
TabbedPane.tabSeparatorColor=#00f
TabbedPane.contentAreaColor=#bbbbbb

View File

@@ -69,3 +69,8 @@ TaskPane.titleOver=#0000aa
TaskPane.specialTitleBackground=#00ffff
TaskPane.specialTitleForeground=#444444
TaskPane.specialTitleOver=#dd0000
#---- TitledPanel ----
JXTitledPanel.borderColor=@@Button.startBorderColor