mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
86 Commits
styling-ty
...
animated-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d7a6ff331 | ||
|
|
23fc3674c9 | ||
|
|
34a7214dd8 | ||
|
|
26d7008c04 | ||
|
|
3b489e8e1a | ||
|
|
ccbf577f46 | ||
|
|
b903f18130 | ||
|
|
9523c89c51 | ||
|
|
aa6fb2fcce | ||
|
|
e4fa2e28ea | ||
|
|
b2245e2246 | ||
|
|
13a6b92e47 | ||
|
|
9ba008002b | ||
|
|
8914cf78a1 | ||
|
|
d360375b4f | ||
|
|
1caab194af | ||
|
|
31754eba5d | ||
|
|
3cfa16b8b7 | ||
|
|
f80d2bacf4 | ||
|
|
5df3717d94 | ||
|
|
68897f04a2 | ||
|
|
4cb6aeae36 | ||
|
|
0a765a35bf | ||
|
|
6c0b122fbc | ||
|
|
4da2bd90cb | ||
|
|
f0275192c6 | ||
|
|
df905a1d73 | ||
|
|
ad8ad06f44 | ||
|
|
d6b9e2df62 | ||
|
|
5c9b36556f | ||
|
|
80a8348a99 | ||
|
|
005c9f471e | ||
|
|
b40532a830 | ||
|
|
fc7a4408e9 | ||
|
|
93b5f0081d | ||
|
|
ce049ea3ee | ||
|
|
fcc39b2db5 | ||
|
|
cb70fb4e82 | ||
|
|
2593a43d72 | ||
|
|
e44ff5b72a | ||
|
|
22cb1b50a6 | ||
|
|
a42c413705 | ||
|
|
d59d38dc7c | ||
|
|
77582be7fd | ||
|
|
0cb50355b7 | ||
|
|
a2d66e91ff | ||
|
|
ccdb981917 | ||
|
|
d80b581ace | ||
|
|
53efb6711d | ||
|
|
1de6e875f9 | ||
|
|
95a15c3cf8 | ||
|
|
ab320684f5 | ||
|
|
a284b69a1e | ||
|
|
b590f41254 | ||
|
|
a97076ead5 | ||
|
|
0b6df8be1c | ||
|
|
150bab0b57 | ||
|
|
d3355eda65 | ||
|
|
fbf10e553d | ||
|
|
fb37be5734 | ||
|
|
54e6cefa67 | ||
|
|
33b25c1129 | ||
|
|
44d8545c09 | ||
|
|
7a2808243c | ||
|
|
1be84de26b | ||
|
|
78e37f7ab4 | ||
|
|
f742f83834 | ||
|
|
e6e4e53a73 | ||
|
|
7c594ba7a9 | ||
|
|
d34619824c | ||
|
|
80297f113f | ||
|
|
80f51bfe1e | ||
|
|
587f431ef4 | ||
|
|
e560f9cbd6 | ||
|
|
80235d53f4 | ||
|
|
892b9a732e | ||
|
|
d8a0a015e4 | ||
|
|
e60e3b9fae | ||
|
|
6715f01b8c | ||
|
|
465af9bc41 | ||
|
|
435cf05f9f | ||
|
|
943e211cf1 | ||
|
|
ad0a13004e | ||
|
|
04bb6a5275 | ||
|
|
d3c917eac1 | ||
|
|
4c13271a5b |
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -34,6 +34,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
if: matrix.java == '1.8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
|
||||
57
CHANGELOG.md
57
CHANGELOG.md
@@ -12,6 +12,22 @@ FlatLaf Change Log
|
||||
- Style classes allow defining style rules at a single place (in UI defaults)
|
||||
and use them in any component. (PR #388)\
|
||||
E.g.: `mySlider.putClientProperty( "FlatLaf.styleClass", "myclass" );`
|
||||
- Typography defines several font styles for headers and various text sizes,
|
||||
which makes it easy to use consistent font styles across the application. (PR
|
||||
#396)
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- Unified backgrounds for window title bar is now enabled by default (window
|
||||
title bar has now same background color as window content). Bottom separator
|
||||
for menu bars is no longer painted (if unified background is enabled).
|
||||
- Show Windows 11 snap layouts menu when hovering the mouse over the maximize
|
||||
button. (issues #397 and #407)
|
||||
- Possibility to hide window title bar icon (for single window set client
|
||||
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
||||
value `TitlePane.showIcon` to `false`).
|
||||
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
|
||||
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
||||
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
||||
(issue #416)
|
||||
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
||||
icons (set client property `JTextField.leadingIcon` or
|
||||
`JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368)
|
||||
@@ -44,25 +60,58 @@ FlatLaf Change Log
|
||||
incompatible changes in FlatLaf properties files.
|
||||
- Slider: Support specifying width of thumb border (see UI value
|
||||
`Slider.thumbBorderWidth`).
|
||||
- TabbedPane: Optionally paint selected tab as card. (PR #343)
|
||||
- Added more color functions to class `ColorFunctions` for easy use in
|
||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||
`tint()`, `shade()` and `luma()`.
|
||||
- Support defining fonts in FlatLaf properties files. (issue #384)
|
||||
- Extras: Added class `FlatDesktop` for easy integration into macOS screen menu
|
||||
(About, Preferences and Quit) when using Java 8.
|
||||
- Added method `FlatLaf.registerCustomDefaultsSource(URL packageUrl)` for JPMS.
|
||||
(issue #325)
|
||||
- Extras:
|
||||
- Added class `FlatDesktop` for easy integration into macOS screen menu
|
||||
(About, Preferences and Quit) when using Java 8.
|
||||
- `FlatSVGIcon`: Support loading SVG from `URL` (for JPMS), `URI`, `File` or
|
||||
`InputStream`. (issues #419 and #325)
|
||||
- `FlatSVGUtils`: Support loading SVG from `URL` (for JPMS). (issue #325)
|
||||
|
||||
|
||||
## 1.6.4
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox: Fixed regression in FlatLaf 1.6.3 that makes selected item invisible
|
||||
in popup list if `DefaultListCellRenderer` is used as renderer. If using
|
||||
default renderer, it works. (issue #426)
|
||||
|
||||
|
||||
## 1.6.3
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed regression in FlatLaf 1.6.2 that may display
|
||||
text in non-editable combo boxes in bold. (issue #423)
|
||||
- Tree: Fixed editing cell issue with custom cell renderer and cell editor that
|
||||
use same component for rendering and editing. (issue #385)
|
||||
|
||||
|
||||
## 1.6.2
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed background painted outside of border if round
|
||||
edges are enabled (client property `JComponent.roundRect` is `true`). (similar
|
||||
to issue #382; regression since fixing #330 in FlatLaf 1.4)
|
||||
- Tree: Fixed editing cell issue with custom cell renderer and cell editor that
|
||||
use same component for rendering and editing. (issue #385)
|
||||
- ComboBox: Fixed `NullPointerException`, which may occur under special
|
||||
circumstances. (issue #408)
|
||||
- Table: Do not select text in cell editor when it gets focus (when
|
||||
`JTable.surrendersFocusOnKeystroke` is `true`) and
|
||||
`TextComponent.selectAllOnFocusPolicy` is `once` (the default) or `always`.
|
||||
(issue #395)
|
||||
- Linux: Fixed NPE when using `java.awt.TrayIcon`. (issue #405)
|
||||
- FileChooser: Workaround for crash on Windows with Java 17 32-bit (disabled
|
||||
Windows icons). Java 17 64-bit is not affected. (issue #403)
|
||||
- Native window decorations: Fixed layout loop, which may occur under special
|
||||
circumstances and slows down the application. (issue #420)
|
||||
|
||||
|
||||
## 1.6.1
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "1.6.1"
|
||||
val releaseVersion = "1.6.4"
|
||||
val developmentVersion = "2.0-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
@@ -331,6 +331,24 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||
|
||||
/**
|
||||
* Specifies whether the window icon should be shown in the window title bar
|
||||
* (requires enabled window decorations).
|
||||
* <p>
|
||||
* Setting this shows/hides the windows icon
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* This client property has higher priority than UI default {@code TitlePane.showIcon}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
||||
|
||||
/**
|
||||
* Background color of window title bar (requires enabled window decorations).
|
||||
* <p>
|
||||
@@ -375,6 +393,35 @@ public interface FlatClientProperties
|
||||
|
||||
//---- JTabbedPane --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of the selected tab.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||
|
||||
/**
|
||||
* Paint the selected tab underlined.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||
|
||||
/**
|
||||
* Paint the selected tab as card.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||
|
||||
/**
|
||||
* Specifies whether separators are shown between tabs.
|
||||
* <p>
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
@@ -392,6 +393,7 @@ public abstract class FlatLaf
|
||||
"EditorPane.inactiveBackground",
|
||||
"FormattedTextField.disabledBackground",
|
||||
"PasswordField.disabledBackground",
|
||||
"RootPane.background",
|
||||
"Spinner.disabledBackground",
|
||||
"TextArea.disabledBackground",
|
||||
"TextArea.inactiveBackground",
|
||||
@@ -410,7 +412,8 @@ public abstract class FlatLaf
|
||||
"Spinner.disabledForeground",
|
||||
"ToggleButton.disabledText" );
|
||||
putDefaults( defaults, defaults.getColor( "textText" ),
|
||||
"DesktopIcon.foreground" );
|
||||
"DesktopIcon.foreground",
|
||||
"RootPane.foreground" );
|
||||
|
||||
initFonts( defaults );
|
||||
initIconColors( defaults, isDark() );
|
||||
@@ -420,7 +423,7 @@ public abstract class FlatLaf
|
||||
// (using defaults.remove() to avoid that lazy value is resolved and icon loaded here)
|
||||
Object icon = defaults.remove( "InternalFrame.icon" );
|
||||
defaults.put( "InternalFrame.icon", icon );
|
||||
defaults.put( "TitlePane.icon", icon );
|
||||
defaults.put( "TitlePane.icon", icon ); // no longer used, but keep for compatibility
|
||||
|
||||
// get addons and sort them by priority
|
||||
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
|
||||
@@ -533,13 +536,16 @@ public abstract class FlatLaf
|
||||
// use active value for all fonts to allow changing fonts in all components with:
|
||||
// UIManager.put( "defaultFont", myFont );
|
||||
// (this is similar as in Nimbus L&F)
|
||||
Object activeFont = new ActiveFont( null, -1, 0, 0, 0, 0 );
|
||||
Object activeFont = new ActiveFont( null, null, -1, 0, 0, 0, 0 );
|
||||
|
||||
// override fonts
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
||||
defaults.put( key, activeFont );
|
||||
}
|
||||
|
||||
// add fonts that are not set in BasicLookAndFeel
|
||||
defaults.put( "RootPane.font", activeFont );
|
||||
}
|
||||
|
||||
private void initDefaultFont( UIDefaults defaults ) {
|
||||
@@ -617,7 +623,7 @@ public abstract class FlatLaf
|
||||
|
||||
/** @since 1.1 */
|
||||
public static ActiveValue createActiveFontValue( float scaleFactor ) {
|
||||
return new ActiveFont( null, -1, 0, 0, 0, scaleFactor );
|
||||
return new ActiveFont( null, null, -1, 0, 0, 0, scaleFactor );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,6 +757,9 @@ public abstract class FlatLaf
|
||||
* and can therefore override all UI defaults.
|
||||
* <p>
|
||||
* Invoke this method before setting the look and feel.
|
||||
* <p>
|
||||
* If using Java modules, the package must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #registerCustomDefaultsSource(URL)}.
|
||||
*
|
||||
* @param packageName a package name (e.g. "com.myapp.resources")
|
||||
*/
|
||||
@@ -792,6 +801,32 @@ public abstract class FlatLaf
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a package where FlatLaf searches for properties files with custom UI defaults.
|
||||
* <p>
|
||||
* See {@link #registerCustomDefaultsSource(String)} for details.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the properties files
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code FlatLaf.registerCustomDefaultsSource( MyApp.class.getResource( "/com/myapp/themes/" ) )}.
|
||||
*
|
||||
* @param packageUrl a package URL
|
||||
* @since 2
|
||||
*/
|
||||
public static void registerCustomDefaultsSource( URL packageUrl ) {
|
||||
if( customDefaultsSources == null )
|
||||
customDefaultsSources = new ArrayList<>();
|
||||
customDefaultsSources.add( packageUrl );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public static void unregisterCustomDefaultsSource( URL packageUrl ) {
|
||||
if( customDefaultsSources == null )
|
||||
return;
|
||||
|
||||
customDefaultsSources.remove( packageUrl );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a folder where FlatLaf searches for properties files with custom UI defaults.
|
||||
* <p>
|
||||
@@ -1191,6 +1226,7 @@ public abstract class FlatLaf
|
||||
static class ActiveFont
|
||||
implements ActiveValue
|
||||
{
|
||||
private final String baseFontKey;
|
||||
private final List<String> families;
|
||||
private final int style;
|
||||
private final int styleChange;
|
||||
@@ -1200,7 +1236,9 @@ public abstract class FlatLaf
|
||||
|
||||
// cache (scaled/derived) font
|
||||
private FontUIResource font;
|
||||
private Font lastDefaultFont;
|
||||
private Font lastBaseFont;
|
||||
|
||||
private boolean inCreateValue;
|
||||
|
||||
/**
|
||||
* @param families list of font families, or {@code null}
|
||||
@@ -1211,9 +1249,10 @@ public abstract class FlatLaf
|
||||
* @param relativeSize added to size of base font, or {@code 0}
|
||||
* @param scaleSize multiply size of base font, or {@code 0}
|
||||
*/
|
||||
ActiveFont( List<String> families, int style, int styleChange,
|
||||
ActiveFont( String baseFontKey, List<String> families, int style, int styleChange,
|
||||
int absoluteSize, int relativeSize, float scaleSize )
|
||||
{
|
||||
this.baseFontKey = baseFontKey;
|
||||
this.families = families;
|
||||
this.style = style;
|
||||
this.styleChange = styleChange;
|
||||
@@ -1224,16 +1263,30 @@ public abstract class FlatLaf
|
||||
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
Font defaultFont = UIManager.getFont( "defaultFont" );
|
||||
if( inCreateValue )
|
||||
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
||||
|
||||
// fallback (to avoid NPE in case that this is used in another Laf)
|
||||
if( defaultFont == null )
|
||||
defaultFont = UIManager.getFont( "Label.font" );
|
||||
Font baseFont = null;
|
||||
|
||||
if( lastDefaultFont != defaultFont ) {
|
||||
lastDefaultFont = defaultFont;
|
||||
inCreateValue = true;
|
||||
try {
|
||||
if( baseFontKey != null )
|
||||
baseFont = (Font) UIDefaultsLoader.lazyUIManagerGet( baseFontKey );
|
||||
|
||||
font = derive( defaultFont, fontSize -> UIScale.scale( fontSize ) );
|
||||
if( baseFont == null )
|
||||
baseFont = UIManager.getFont( "defaultFont" );
|
||||
|
||||
// fallback (to avoid NPE in case that this is used in another Laf)
|
||||
if( baseFont == null )
|
||||
baseFont = UIManager.getFont( "Label.font" );
|
||||
} finally {
|
||||
inCreateValue = false;
|
||||
}
|
||||
|
||||
if( lastBaseFont != baseFont ) {
|
||||
lastBaseFont = baseFont;
|
||||
|
||||
font = derive( baseFont, fontSize -> UIScale.scale( fontSize ) );
|
||||
}
|
||||
|
||||
return font;
|
||||
|
||||
@@ -22,13 +22,12 @@ import java.awt.Font;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StreamTokenizer;
|
||||
import java.io.StringReader;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -56,6 +55,7 @@ import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SoftCache;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -84,7 +84,7 @@ class UIDefaultsLoader
|
||||
|
||||
private static int parseColorDepth;
|
||||
|
||||
private static final Cache<String, Object> fontCache = new Cache<>();
|
||||
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
||||
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
@@ -158,6 +158,18 @@ class UIDefaultsLoader
|
||||
properties.load( in );
|
||||
}
|
||||
}
|
||||
} else if( source instanceof URL ) {
|
||||
// load from package URL
|
||||
URL packageUrl = (URL) source;
|
||||
for( Class<?> lafClass : lafClasses ) {
|
||||
URL propertiesUrl = new URL( packageUrl + lafClass.getSimpleName() + ".properties" );
|
||||
|
||||
try( InputStream in = propertiesUrl.openStream() ) {
|
||||
properties.load( in );
|
||||
} catch( FileNotFoundException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
} else if( source instanceof File ) {
|
||||
// load from folder
|
||||
File folder = (File) source;
|
||||
@@ -429,10 +441,7 @@ class UIDefaultsLoader
|
||||
// check whether value type is specified in the value
|
||||
if( value.startsWith( "#" ) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( value.startsWith( "\"" ) && value.indexOf( '"', 1 ) == value.length() - 1 ) {
|
||||
valueType = ValueType.STRING;
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
int end = value.indexOf( TYPE_PREFIX_END );
|
||||
if( end != -1 ) {
|
||||
try {
|
||||
@@ -524,6 +533,12 @@ class UIDefaultsLoader
|
||||
case GRAYFILTER: return parseGrayFilter( value );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
// string
|
||||
if( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
|
||||
resultValueType[0] = ValueType.STRING;
|
||||
return value.substring( 1, value.length() - 1 );
|
||||
}
|
||||
|
||||
// colors
|
||||
Object color = parseColorOrFunction( value, resolver, false );
|
||||
if( color != null ) {
|
||||
@@ -1039,7 +1054,7 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]]
|
||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
||||
*/
|
||||
private static Object parseFont( String value ) {
|
||||
Object font = fontCache.get( value );
|
||||
@@ -1052,6 +1067,7 @@ class UIDefaultsLoader
|
||||
int relativeSize = 0;
|
||||
float scaleSize = 0;
|
||||
List<String> families = null;
|
||||
String baseFontKey = null;
|
||||
|
||||
// use StreamTokenizer to split string because it supports quoted strings
|
||||
StreamTokenizer st = new StreamTokenizer( new StringReader( value ) );
|
||||
@@ -1101,6 +1117,12 @@ class UIDefaultsLoader
|
||||
scaleSize = parseInteger( param.substring( 0, param.length() - 1 ), true ) / 100f;
|
||||
else
|
||||
absoluteSize = parseInteger( param, true );
|
||||
} else if( firstChar == '$' ) {
|
||||
// reference to base font
|
||||
if( baseFontKey != null )
|
||||
throw new IllegalArgumentException( "baseFontKey specified more than once in '" + value + "'" );
|
||||
|
||||
baseFontKey = param.substring( 1 );
|
||||
} else {
|
||||
// font family
|
||||
if( families == null )
|
||||
@@ -1127,7 +1149,7 @@ class UIDefaultsLoader
|
||||
throw new IllegalArgumentException( "can not use '+italic' and '-italic' in '" + value + "'" );
|
||||
}
|
||||
|
||||
font = new FlatLaf.ActiveFont( families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
||||
font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
||||
fontCache.put( value, font );
|
||||
return font;
|
||||
}
|
||||
@@ -1280,7 +1302,7 @@ class UIDefaultsLoader
|
||||
* For use in LazyValue to get value for given key from UIManager and report error
|
||||
* if not found. If key is prefixed by '?', then no error is reported.
|
||||
*/
|
||||
private static Object lazyUIManagerGet( String uiKey ) {
|
||||
static Object lazyUIManagerGet( String uiKey ) {
|
||||
boolean optional = false;
|
||||
if( uiKey.startsWith( OPTIONAL_PREFIX ) ) {
|
||||
uiKey = uiKey.substring( OPTIONAL_PREFIX.length() );
|
||||
@@ -1296,43 +1318,4 @@ class UIDefaultsLoader
|
||||
private static void throwMissingParametersException( String value ) {
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
}
|
||||
|
||||
//---- class Cache --------------------------------------------------------
|
||||
|
||||
private static class Cache<K,V>
|
||||
{
|
||||
private final Map<K, CacheReference<K,V>> map = new HashMap<>();
|
||||
private final ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
V get( K key ) {
|
||||
expungeStaleEntries();
|
||||
CacheReference<K,V> ref = map.get( key );
|
||||
return (ref != null) ? ref.get() : null;
|
||||
}
|
||||
|
||||
void put( K key, V value ) {
|
||||
expungeStaleEntries();
|
||||
map.put( key, new CacheReference<>( key, value, queue ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
void expungeStaleEntries() {
|
||||
Reference<? extends V> reference;
|
||||
while( (reference = queue.poll()) != null )
|
||||
map.remove( ((CacheReference<K,V>)reference).key );
|
||||
}
|
||||
|
||||
//---- class CacheReference ----
|
||||
|
||||
private static class CacheReference<K,V>
|
||||
extends SoftReference<V>
|
||||
{
|
||||
final K key;
|
||||
|
||||
public CacheReference( K key, V value, ReferenceQueue<? super V> queue ) {
|
||||
super( value, queue );
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,13 @@ public abstract class FlatAbstractIcon
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void paintIcon( Component c, Graphics2D g2 );
|
||||
/**
|
||||
* Paint the icon at {@code [0,0]} location.
|
||||
* <p>
|
||||
* The given graphics context is scaled.
|
||||
* Use unscaled coordinates, width and height for painting.
|
||||
*/
|
||||
protected abstract void paintIcon( Component c, Graphics2D g );
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
import com.formdev.flatlaf.util.AnimatedPainter;
|
||||
|
||||
/**
|
||||
* Base class for animated icons that scales width and height, creates and initializes
|
||||
@@ -30,7 +31,7 @@ import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
* <p>
|
||||
* This class does not store any state information (needed for animation) in its instance.
|
||||
* Instead a client property is set on the painted component.
|
||||
* This makes it possible to use a share icon instance for multiple components.
|
||||
* This makes it possible to use a shared icon instance for multiple components.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -45,11 +46,34 @@ public abstract class FlatAnimatedIcon
|
||||
@Override
|
||||
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
super.paintIcon( c, g, x, y );
|
||||
AnimatedIcon.AnimationSupport.saveIconLocation( this, c, x, y );
|
||||
AnimatedPainter.saveRepaintLocation( this, c, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
AnimatedIcon.AnimationSupport.paintIcon( this, c, g, 0, 0 );
|
||||
paintWithAnimation( c, g, 0, 0, getIconWidth(), getIconHeight() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates painting to {@link #paintIconAnimated(Component, Graphics2D, float[])}.
|
||||
* Ignores the given bounds because {@code [x,y]} are always {@code [0,0]} and
|
||||
* {@code [width,height]} are scaled, but painting code should use unscaled width
|
||||
* and height because given graphics context is scaled.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@Override
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
paintIconAnimated( c, g, animatedValues );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the icon at {@code 0,0} location.
|
||||
* <p>
|
||||
* The given graphics context is scaled.
|
||||
* Use unscaled coordinates, width and height for painting.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
protected abstract void paintIconAnimated( Component c, Graphics2D g, float[] animatedValues );
|
||||
}
|
||||
|
||||
@@ -575,22 +575,6 @@ public class FlatComboBoxUI
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public void paintCurrentValue( Graphics g, Rectangle bounds, boolean hasFocus ) {
|
||||
// apply clipping using rounded rectangle to avoid that renderer paints
|
||||
// outside of border if combobox uses larger arc for edges
|
||||
// (e.g. FlatClientProperties.COMPONENT_ROUND_RECT is true)
|
||||
FlatBorder border = FlatUIUtils.getOutsideFlatBorder( comboBox );
|
||||
if( border != null ) {
|
||||
int clipArc = border.getArc( comboBox ) - (border.getLineWidth( comboBox ) * 2);
|
||||
if( clipArc > 0 ) {
|
||||
int x = bounds.x;
|
||||
int width = bounds.width + bounds.height;
|
||||
if( !comboBox.getComponentOrientation().isLeftToRight() )
|
||||
x -= bounds.height;
|
||||
((Graphics2D)g).clip( FlatUIUtils.createComponentRectangle(
|
||||
x, bounds.y, width, bounds.height, scale( (float) clipArc ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
paddingBorder.uninstall();
|
||||
|
||||
ListCellRenderer<Object> renderer = comboBox.getRenderer();
|
||||
@@ -604,11 +588,20 @@ public class FlatComboBoxUI
|
||||
c.setBackground( getBackground( enabled ) );
|
||||
c.setForeground( getForeground( enabled ) );
|
||||
|
||||
// make renderer component temporary non-opaque to avoid that renderer paints
|
||||
// background outside of border if combobox uses larger arc for edges
|
||||
// (e.g. FlatClientProperties.COMPONENT_ROUND_RECT is true)
|
||||
if( c instanceof JComponent )
|
||||
((JComponent)c).setOpaque( false );
|
||||
|
||||
boolean shouldValidate = (c instanceof JPanel);
|
||||
|
||||
paddingBorder.install( c );
|
||||
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
|
||||
paddingBorder.uninstall();
|
||||
|
||||
if( c instanceof JComponent )
|
||||
((JComponent)c).setOpaque( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -262,12 +262,20 @@ public class FlatFileChooserUI
|
||||
|
||||
@Override
|
||||
public FileView getFileView( JFileChooser fc ) {
|
||||
return fileView;
|
||||
return doNotUseSystemIcons() ? super.getFileView( fc ) : fileView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearIconCache() {
|
||||
fileView.clearIconCache();
|
||||
if( doNotUseSystemIcons() )
|
||||
super.clearIconCache();
|
||||
else
|
||||
fileView.clearIconCache();
|
||||
}
|
||||
|
||||
private boolean doNotUseSystemIcons() {
|
||||
// Java 17 32bit craches on Windows when using system icons
|
||||
return SystemInfo.isWindows && SystemInfo.isJava_17_orLater && !SystemInfo.isX86_64;
|
||||
}
|
||||
|
||||
//---- class FlatFileView -------------------------------------------------
|
||||
|
||||
@@ -53,6 +53,9 @@ public class FlatMenuBarBorder
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( !showBottomSeparator( c ) )
|
||||
return;
|
||||
|
||||
float lineHeight = scale( (float) 1 );
|
||||
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||
}
|
||||
@@ -68,4 +71,9 @@ public class FlatMenuBarBorder
|
||||
insets.right = scale( margin.right );
|
||||
return insets;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected boolean showBottomSeparator( Component c ) {
|
||||
return !FlatMenuBarUI.useUnifiedBackground( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
@@ -189,10 +190,8 @@ public class FlatMenuBarUI
|
||||
return background;
|
||||
|
||||
// use parent background for unified title pane
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
if( UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ) )
|
||||
background = FlatUIUtils.getParentBackground( c );
|
||||
if( useUnifiedBackground( c ) )
|
||||
background = FlatUIUtils.getParentBackground( c );
|
||||
|
||||
// paint background in full screen mode
|
||||
if( FlatUIUtils.isFullScreen( rootPane ) )
|
||||
@@ -202,6 +201,22 @@ public class FlatMenuBarUI
|
||||
return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background;
|
||||
}
|
||||
|
||||
/**@since 2 */
|
||||
static boolean useUnifiedBackground( Component c ) {
|
||||
// check whether:
|
||||
// - TitlePane.unifiedBackground is true and
|
||||
// - menu bar is the "main" menu bar and
|
||||
// - window has custom decorations enabled
|
||||
|
||||
JRootPane rootPane;
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
return UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||
rootPane.getParent() instanceof Window &&
|
||||
rootPane.getJMenuBar() == c &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() );
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,8 @@ public class FlatNativeWindowBorder
|
||||
}
|
||||
|
||||
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds )
|
||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
||||
{
|
||||
if( canUseJBRCustomDecorations ) {
|
||||
JBRCustomDecorations.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
||||
@@ -245,9 +246,8 @@ public class FlatNativeWindowBorder
|
||||
if( !isSupported() )
|
||||
return;
|
||||
|
||||
nativeProvider.setTitleBarHeight( window, titleBarHeight );
|
||||
nativeProvider.setTitleBarHitTestSpots( window, hitTestSpots );
|
||||
nativeProvider.setTitleBarAppIconBounds( window, appIconBounds );
|
||||
nativeProvider.updateTitleBarInfo( window, titleBarHeight, hitTestSpots,
|
||||
appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
}
|
||||
|
||||
static boolean showWindow( Window window, int cmd ) {
|
||||
@@ -268,7 +268,7 @@ public class FlatNativeWindowBorder
|
||||
try {
|
||||
/*
|
||||
Class<?> cls = Class.forName( "com.formdev.flatlaf.natives.jna.windows.FlatWindowsNativeWindowBorder" );
|
||||
Method m = cls.getMethod( "getInstance" );
|
||||
java.lang.reflect.Method m = cls.getMethod( "getInstance" );
|
||||
setNativeProvider( (Provider) m.invoke( null ) );
|
||||
*/
|
||||
setNativeProvider( FlatWindowsNativeWindowBorder.getInstance() );
|
||||
@@ -292,9 +292,9 @@ public class FlatNativeWindowBorder
|
||||
{
|
||||
boolean hasCustomDecoration( Window window );
|
||||
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
||||
void setTitleBarHeight( Window window, int titleBarHeight );
|
||||
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
|
||||
void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds );
|
||||
void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds );
|
||||
|
||||
// commands for showWindow(); values must match Win32 API
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
|
||||
|
||||
@@ -22,18 +22,22 @@ import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicOptionPaneUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -79,6 +83,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatOptionPaneUI -->
|
||||
*
|
||||
* @uiDefault OptionPane.showIcon boolean
|
||||
* @uiDefault OptionPane.iconMessageGap int
|
||||
* @uiDefault OptionPane.messagePadding int
|
||||
* @uiDefault OptionPane.maxCharactersPerLine int
|
||||
@@ -88,6 +93,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatOptionPaneUI
|
||||
extends BasicOptionPaneUI
|
||||
{
|
||||
/** @since 2 */ protected boolean showIcon;
|
||||
protected int iconMessageGap;
|
||||
protected int messagePadding;
|
||||
protected int maxCharactersPerLine;
|
||||
@@ -102,6 +108,7 @@ public class FlatOptionPaneUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
showIcon = UIManager.getBoolean( "OptionPane.showIcon" );
|
||||
iconMessageGap = UIManager.getInt( "OptionPane.iconMessageGap" );
|
||||
messagePadding = UIManager.getInt( "OptionPane.messagePadding" );
|
||||
maxCharactersPerLine = UIManager.getInt( "OptionPane.maxCharactersPerLine" );
|
||||
@@ -116,6 +123,24 @@ public class FlatOptionPaneUI
|
||||
updateChildPanels( optionPane );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
|
||||
// hide window title bar icon
|
||||
// (only if showIcon is false, otherwise the default behavior is used)
|
||||
if( !showIcon && "ancestor".equals( e.getPropertyName() ) && e.getNewValue() != null ) {
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( optionPane );
|
||||
if( rootPane != null &&
|
||||
rootPane.getContentPane().getComponentCount() > 0 &&
|
||||
rootPane.getContentPane().getComponent( 0 ) == optionPane )
|
||||
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, false );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumOptionPaneSize() {
|
||||
return UIScale.scale( super.getMinimumOptionPaneSize() );
|
||||
|
||||
@@ -66,6 +66,9 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatWindowResizer -->
|
||||
*
|
||||
* @uiDefault RootPane.font Font unused
|
||||
* @uiDefault RootPane.background Color
|
||||
* @uiDefault RootPane.foreground Color unused
|
||||
* @uiDefault RootPane.borderDragThickness int
|
||||
* @uiDefault RootPane.cornerDragWidth int
|
||||
* @uiDefault RootPane.honorFrameMinimumSizeOnResize boolean
|
||||
@@ -126,8 +129,23 @@ public class FlatRootPaneUI
|
||||
protected void installDefaults( JRootPane c ) {
|
||||
super.installDefaults( c );
|
||||
|
||||
// Give the root pane useful background, foreground and font.
|
||||
// Background is used for title bar and menu bar if native window decorations
|
||||
// and unified background are enabled.
|
||||
// Foreground and font are usually not used, but set for completeness.
|
||||
// Not using LookAndFeel.installColorsAndFont() here because it will not work
|
||||
// because the properties are null by default but inherit non-null values from parent.
|
||||
if( !c.isBackgroundSet() || c.getBackground() instanceof UIResource )
|
||||
c.setBackground( UIManager.getColor( "RootPane.background" ) );
|
||||
if( !c.isForegroundSet() || c.getForeground() instanceof UIResource )
|
||||
c.setForeground( UIManager.getColor( "RootPane.foreground" ) );
|
||||
if( !c.isFontSet() || c.getFont() instanceof UIResource )
|
||||
c.setFont( UIManager.getFont( "RootPane.font" ) );
|
||||
|
||||
// Update background color of JFrame or JDialog parent to avoid bad border
|
||||
// on HiDPI screens when switching from light to dark Laf.
|
||||
// Window background color is also used in native window decorations
|
||||
// to fill background when window is initially shown or when resizing window.
|
||||
// The background of JFrame is initialized in JFrame.frameInit() and
|
||||
// the background of JDialog in JDialog.dialogInit(),
|
||||
// but it was not updated when switching Laf.
|
||||
@@ -313,6 +331,11 @@ public class FlatRootPaneUI
|
||||
}
|
||||
break;
|
||||
|
||||
case FlatClientProperties.TITLE_BAR_SHOW_ICON:
|
||||
if( titlePane != null )
|
||||
titlePane.updateIcon();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.TITLE_BAR_BACKGROUND:
|
||||
case FlatClientProperties.TITLE_BAR_FOREGROUND:
|
||||
if( titlePane != null )
|
||||
|
||||
@@ -40,6 +40,8 @@ import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
@@ -134,12 +136,15 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.maximumTabWidth int optional
|
||||
* @uiDefault TabbedPane.tabHeight int
|
||||
* @uiDefault TabbedPane.tabSelectionHeight int
|
||||
* @uiDefault TabbedPane.cardTabSelectionHeight int
|
||||
* @uiDefault TabbedPane.contentSeparatorHeight int
|
||||
* @uiDefault TabbedPane.showTabSeparators boolean
|
||||
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
||||
* @uiDefault TabbedPane.hasFullBorder boolean
|
||||
* @uiDefault TabbedPane.activeTabBorder boolean
|
||||
*
|
||||
* @uiDefault TabbedPane.tabLayoutPolicy String wrap (default) or scroll
|
||||
* @uiDefault TabbedPane.tabType String underlined (default) or card
|
||||
* @uiDefault TabbedPane.tabsPopupPolicy String never or asNeeded (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPolicy String never, asNeeded or asNeededSingle (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPlacement String both (default) or trailing
|
||||
@@ -165,6 +170,10 @@ public class FlatTabbedPaneUI
|
||||
extends BasicTabbedPaneUI
|
||||
implements StyleableUI
|
||||
{
|
||||
// tab type
|
||||
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
||||
/** @since 2 */ protected static final int TAB_TYPE_CARD = 1;
|
||||
|
||||
// tabs popup policy / scroll arrows policy
|
||||
protected static final int NEVER = 0;
|
||||
// protected static final int ALWAYS = 1;
|
||||
@@ -200,12 +209,14 @@ public class FlatTabbedPaneUI
|
||||
@Styleable protected int maximumTabWidth;
|
||||
@Styleable protected int tabHeight;
|
||||
@Styleable protected int tabSelectionHeight;
|
||||
/** @since 2 */ @Styleable protected int cardTabSelectionHeight;
|
||||
@Styleable protected int contentSeparatorHeight;
|
||||
@Styleable protected boolean showTabSeparators;
|
||||
@Styleable protected boolean tabSeparatorsFullHeight;
|
||||
@Styleable protected boolean hasFullBorder;
|
||||
@Styleable protected boolean tabsOpaque = true;
|
||||
|
||||
@Styleable(type=String.class) private int tabType;
|
||||
@Styleable(type=String.class) private int tabsPopupPolicy;
|
||||
@Styleable(type=String.class) private int scrollButtonsPolicy;
|
||||
@Styleable(type=String.class) private int scrollButtonsPlacement;
|
||||
@@ -318,12 +329,14 @@ public class FlatTabbedPaneUI
|
||||
maximumTabWidth = UIManager.getInt( "TabbedPane.maximumTabWidth" );
|
||||
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||
cardTabSelectionHeight = UIManager.getInt( "TabbedPane.cardTabSelectionHeight" );
|
||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||
tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" );
|
||||
|
||||
tabType = parseTabType( UIManager.getString( "TabbedPane.tabType" ) );
|
||||
tabsPopupPolicy = parseTabsPopupPolicy( UIManager.getString( "TabbedPane.tabsPopupPolicy" ) );
|
||||
scrollButtonsPolicy = parseScrollButtonsPolicy( UIManager.getString( "TabbedPane.scrollButtonsPolicy" ) );
|
||||
scrollButtonsPlacement = parseScrollButtonsPlacement( UIManager.getString( "TabbedPane.scrollButtonsPlacement" ) );
|
||||
@@ -560,6 +573,13 @@ public class FlatTabbedPaneUI
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FocusListener createFocusListener() {
|
||||
Handler handler = getHandler();
|
||||
handler.focusDelegate = super.createFocusListener();
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutManager createLayoutManager() {
|
||||
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT )
|
||||
@@ -618,6 +638,7 @@ public class FlatTabbedPaneUI
|
||||
|
||||
if( value instanceof String ) {
|
||||
switch( key ) {
|
||||
case "tabType": value = parseTabType( (String) value ); break;
|
||||
case "tabsPopupPolicy": value = parseTabsPopupPolicy( (String) value ); break;
|
||||
case "scrollButtonsPolicy": value = parseScrollButtonsPolicy( (String) value ); break;
|
||||
case "scrollButtonsPlacement": value = parseScrollButtonsPlacement( (String) value ); break;
|
||||
@@ -707,8 +728,25 @@ public class FlatTabbedPaneUI
|
||||
return;
|
||||
|
||||
Rectangle r = getTabBounds( tabPane, tabIndex );
|
||||
if( r != null )
|
||||
tabPane.repaint( r );
|
||||
if( r == null )
|
||||
return;
|
||||
|
||||
// increase size of repaint region to include part of content border
|
||||
if( contentSeparatorHeight > 0 &&
|
||||
getTabType() == TAB_TYPE_CARD &&
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
||||
{
|
||||
int sh = scale( contentSeparatorHeight );
|
||||
switch( tabPane.getTabPlacement() ) {
|
||||
default:
|
||||
case TOP: r.height += sh; break;
|
||||
case BOTTOM: r.height += sh; r.y -= sh; break;
|
||||
case LEFT: r.width += sh; break;
|
||||
case RIGHT: r.width += sh; r.x -= sh; break;
|
||||
}
|
||||
}
|
||||
|
||||
tabPane.repaint( r );
|
||||
}
|
||||
|
||||
private boolean inCalculateEqual;
|
||||
@@ -1045,16 +1083,21 @@ public class FlatTabbedPaneUI
|
||||
int x, int y, int w, int h, boolean isSelected )
|
||||
{
|
||||
// paint tab background
|
||||
Color background = getTabBackground( tabPlacement, tabIndex, isSelected );
|
||||
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||
g.fillRect( x, y, w, h );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Color getTabBackground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||
boolean enabled = tabPane.isEnabled();
|
||||
Color background = enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
return enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
? hoverColor
|
||||
: (enabled && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane )
|
||||
? focusColor
|
||||
: (selectedBackground != null && enabled && isSelected
|
||||
? selectedBackground
|
||||
: tabPane.getBackgroundAt( tabIndex )));
|
||||
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||
g.fillRect( x, y, w, h );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1064,7 +1107,62 @@ public class FlatTabbedPaneUI
|
||||
// paint tab separators
|
||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
|
||||
!isLastInRun( tabIndex ) )
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
{
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
// some separators need to be omitted if selected tab is painted as card
|
||||
int selectedIndex = tabPane.getSelectedIndex();
|
||||
if( tabIndex != selectedIndex - 1 && tabIndex != selectedIndex )
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
} else
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
}
|
||||
|
||||
// paint active tab border
|
||||
if( isSelected && getTabType() == TAB_TYPE_CARD )
|
||||
paintCardTabBorder( g, tabPlacement, tabIndex, x, y, w, h );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void paintCardTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
|
||||
float borderWidth = scale( (float) contentSeparatorHeight );
|
||||
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
|
||||
|
||||
switch( tabPlacement ) {
|
||||
default:
|
||||
case TOP:
|
||||
case BOTTOM:
|
||||
// paint left and right tab border
|
||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
||||
break;
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
// paint top and bottom tab border
|
||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( cardTabSelectionHeight <= 0 ) {
|
||||
// if there is no tab selection indicator, paint a top border as well
|
||||
switch( tabPlacement ) {
|
||||
default:
|
||||
case TOP:
|
||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
||||
break;
|
||||
case BOTTOM:
|
||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
||||
break;
|
||||
case LEFT:
|
||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
||||
break;
|
||||
case RIGHT:
|
||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintTabCloseButton( Graphics g, int tabIndex, int x, int y, int w, int h ) {
|
||||
@@ -1110,26 +1208,30 @@ public class FlatTabbedPaneUI
|
||||
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
|
||||
|
||||
// paint underline selection
|
||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
||||
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||
int tabSelectionHeight = scale( this.tabSelectionHeight );
|
||||
int tabSelectionHeight = scale( atBottom ? this.tabSelectionHeight : cardTabSelectionHeight );
|
||||
int sx, sy;
|
||||
switch( tabPlacement ) {
|
||||
case TOP:
|
||||
default:
|
||||
int sy = y + h + contentInsets.top - tabSelectionHeight;
|
||||
sy = atBottom ? (y + h + contentInsets.top - tabSelectionHeight) : y;
|
||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
g.fillRect( x, y - contentInsets.bottom, w, tabSelectionHeight );
|
||||
sy = atBottom ? (y - contentInsets.bottom) : (y + h - tabSelectionHeight);
|
||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
||||
break;
|
||||
|
||||
case LEFT:
|
||||
int sx = x + w + contentInsets.left - tabSelectionHeight;
|
||||
sx = atBottom ? (x + w + contentInsets.left - tabSelectionHeight) : x;
|
||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
g.fillRect( x - contentInsets.right, y, tabSelectionHeight, h );
|
||||
sx = atBottom ? (x - contentInsets.right) : (x + w - tabSelectionHeight);
|
||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1141,6 +1243,7 @@ public class FlatTabbedPaneUI
|
||||
* - paint full border (if enabled)
|
||||
* - not invoking paintContentBorder*Edge() methods
|
||||
* - repaint selection
|
||||
* - painting active tab border style
|
||||
*/
|
||||
@Override
|
||||
protected void paintContentBorder( Graphics g, int tabPlacement, int selectedIndex ) {
|
||||
@@ -1189,12 +1292,49 @@ public class FlatTabbedPaneUI
|
||||
Insets ci = new Insets( 0, 0, 0, 0 );
|
||||
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
|
||||
|
||||
// paint content separator or full border
|
||||
g.setColor( contentAreaColor );
|
||||
// create path for content separator or full border
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Rectangle2D.Float( x, y, w, h ), false );
|
||||
path.append( new Rectangle2D.Float( x + (ci.left / 100f), y + (ci.top / 100f),
|
||||
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
|
||||
|
||||
// add gap for selected tab to path
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
float csh = scale( (float) contentSeparatorHeight );
|
||||
|
||||
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
|
||||
Rectangle2D.Float innerTabRect = new Rectangle2D.Float( tabRect.x + csh, tabRect.y + csh,
|
||||
tabRect.width - (csh * 2), tabRect.height - (csh * 2) );
|
||||
|
||||
// Ensure that the separator outside the tabViewport is present (doesn't get cutoff by the active tab)
|
||||
// If left unsolved the active tab is "visible" in the separator (the gap) even when outside the viewport
|
||||
if( tabViewport != null )
|
||||
Rectangle2D.intersect( tabViewport.getBounds(), innerTabRect, innerTabRect );
|
||||
|
||||
Rectangle2D.Float gap = null;
|
||||
if( isHorizontalTabPlacement() ) {
|
||||
if( innerTabRect.width > 0 ) {
|
||||
float y2 = (tabPlacement == TOP) ? y : y + h - csh;
|
||||
gap = new Rectangle2D.Float( innerTabRect.x, y2, innerTabRect.width, csh );
|
||||
}
|
||||
} else {
|
||||
if( innerTabRect.height > 0 ) {
|
||||
float x2 = (tabPlacement == LEFT) ? x : x + w - csh;
|
||||
gap = new Rectangle2D.Float( x2, innerTabRect.y, csh, innerTabRect.height );
|
||||
}
|
||||
}
|
||||
|
||||
if( gap != null ) {
|
||||
path.append( gap, false );
|
||||
|
||||
// fill gap in case that the tab is colored (e.g. focused or hover)
|
||||
g.setColor( getTabBackground( tabPlacement, selectedIndex, true ) );
|
||||
((Graphics2D)g).fill( gap );
|
||||
}
|
||||
}
|
||||
|
||||
// paint content separator or full border
|
||||
g.setColor( contentAreaColor );
|
||||
((Graphics2D)g).fill( path );
|
||||
|
||||
// repaint selection in scroll-tab-layout because it may be painted before
|
||||
@@ -1399,6 +1539,15 @@ public class FlatTabbedPaneUI
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_HIDE_TAB_AREA_WITH_ONE_TAB, hideTabAreaWithOneTab );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected int getTabType() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TAB_TYPE );
|
||||
|
||||
return (value instanceof String)
|
||||
? parseTabType( (String) value )
|
||||
: tabType;
|
||||
}
|
||||
|
||||
protected int getTabsPopupPolicy() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TABS_POPUP_POLICY );
|
||||
|
||||
@@ -1451,6 +1600,18 @@ public class FlatTabbedPaneUI
|
||||
: tabWidthMode;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected static int parseTabType( String str ) {
|
||||
if( str == null )
|
||||
return TAB_TYPE_UNDERLINED;
|
||||
|
||||
switch( str ) {
|
||||
default:
|
||||
case TABBED_PANE_TAB_TYPE_UNDERLINED: return TAB_TYPE_UNDERLINED;
|
||||
case TABBED_PANE_TAB_TYPE_CARD: return TAB_TYPE_CARD;
|
||||
}
|
||||
}
|
||||
|
||||
protected static int parseTabsPopupPolicy( String str ) {
|
||||
if( str == null )
|
||||
return AS_NEEDED;
|
||||
@@ -2264,11 +2425,12 @@ public class FlatTabbedPaneUI
|
||||
|
||||
private class Handler
|
||||
implements MouseListener, MouseMotionListener, PropertyChangeListener,
|
||||
ChangeListener, ComponentListener, ContainerListener
|
||||
ChangeListener, ComponentListener, ContainerListener, FocusListener
|
||||
{
|
||||
MouseListener mouseDelegate;
|
||||
PropertyChangeListener propertyChangeDelegate;
|
||||
ChangeListener changeDelegate;
|
||||
FocusListener focusDelegate;
|
||||
|
||||
private final PropertyChangeListener contentListener = this::contentPropertyChange;
|
||||
|
||||
@@ -2438,6 +2600,10 @@ public class FlatTabbedPaneUI
|
||||
break;
|
||||
|
||||
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
||||
case TABBED_PANE_TAB_TYPE:
|
||||
tabPane.repaint();
|
||||
break;
|
||||
|
||||
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
||||
case TABBED_PANE_HAS_FULL_BORDER:
|
||||
case TABBED_PANE_HIDE_TAB_AREA_WITH_ONE_TAB:
|
||||
@@ -2536,6 +2702,20 @@ public class FlatTabbedPaneUI
|
||||
if( !(c instanceof UIResource) )
|
||||
c.removePropertyChangeListener( contentListener );
|
||||
}
|
||||
|
||||
//---- interface FocusListener ----
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
focusDelegate.focusGained( e );
|
||||
repaintTab( tabPane.getSelectedIndex() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
focusDelegate.focusLost( e );
|
||||
repaintTab( tabPane.getSelectedIndex() );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatTabbedPaneLayout -----------------------------------------
|
||||
|
||||
@@ -50,8 +50,6 @@ import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
@@ -66,7 +64,6 @@ import javax.swing.border.Border;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder;
|
||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
@@ -80,6 +77,8 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.embeddedForeground Color
|
||||
* @uiDefault TitlePane.borderColor Color optional
|
||||
* @uiDefault TitlePane.unifiedBackground boolean
|
||||
* @uiDefault TitlePane.showIcon boolean
|
||||
* @uiDefault TitlePane.noIconLeftGap int
|
||||
* @uiDefault TitlePane.iconSize Dimension
|
||||
* @uiDefault TitlePane.iconMargins Insets
|
||||
* @uiDefault TitlePane.titleMargins Insets
|
||||
@@ -88,7 +87,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.centerTitle boolean
|
||||
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
||||
* @uiDefault TitlePane.menuBarTitleGap int
|
||||
* @uiDefault TitlePane.icon Icon
|
||||
* @uiDefault TitlePane.closeIcon Icon
|
||||
* @uiDefault TitlePane.iconifyIcon Icon
|
||||
* @uiDefault TitlePane.maximizeIcon Icon
|
||||
@@ -106,6 +104,8 @@ public class FlatTitlePane
|
||||
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
||||
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
||||
|
||||
/** @since 2 */ protected final boolean showIcon = FlatUIUtils.getUIBoolean( "TitlePane.showIcon", true );
|
||||
/** @since 2 */ protected final int noIconLeftGap = FlatUIUtils.getUIInt( "TitlePane.noIconLeftGap", 8 );
|
||||
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
||||
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
|
||||
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
|
||||
@@ -224,6 +224,11 @@ public class FlatTitlePane
|
||||
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
|
||||
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
|
||||
|
||||
// initially hide buttons that are only supported in frames
|
||||
iconifyButton.setVisible( false );
|
||||
maximizeButton.setVisible( false );
|
||||
restoreButton.setVisible( false );
|
||||
|
||||
buttonPanel = new JPanel() {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
@@ -243,11 +248,9 @@ public class FlatTitlePane
|
||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||
// but at this time the owner window type is unknown (not yet added)
|
||||
// so we add the iconify/maximize/restore buttons and they are hidden
|
||||
// so we add the iconify/maximize/restore buttons and they are shown
|
||||
// later in frameStateChanged(), which is invoked from addNotify()
|
||||
|
||||
restoreButton.setVisible( false );
|
||||
|
||||
buttonPanel.add( iconifyButton );
|
||||
buttonPanel.add( maximizeButton );
|
||||
buttonPanel.add( restoreButton );
|
||||
@@ -337,36 +340,27 @@ public class FlatTitlePane
|
||||
|
||||
protected void updateIcon() {
|
||||
// get window images
|
||||
List<Image> images = window.getIconImages();
|
||||
if( images.isEmpty() ) {
|
||||
// search in owners
|
||||
for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) {
|
||||
images = owner.getIconImages();
|
||||
if( !images.isEmpty() )
|
||||
break;
|
||||
List<Image> images = null;
|
||||
if( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICON, showIcon ) ) {
|
||||
images = window.getIconImages();
|
||||
if( images.isEmpty() ) {
|
||||
// search in owners
|
||||
for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) {
|
||||
images = owner.getIconImages();
|
||||
if( !images.isEmpty() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasIcon = true;
|
||||
boolean hasIcon = (images != null && !images.isEmpty());
|
||||
|
||||
// set icon
|
||||
if( !images.isEmpty() )
|
||||
iconLabel.setIcon( new FlatTitlePaneIcon( images, iconSize ) );
|
||||
else {
|
||||
// no icon set on window --> use default icon
|
||||
Icon defaultIcon = UIManager.getIcon( "TitlePane.icon" );
|
||||
if( defaultIcon != null && (defaultIcon.getIconWidth() == 0 || defaultIcon.getIconHeight() == 0) )
|
||||
defaultIcon = null;
|
||||
if( defaultIcon != null ) {
|
||||
if( defaultIcon instanceof ImageIcon )
|
||||
defaultIcon = new ScaledImageIcon( (ImageIcon) defaultIcon, iconSize.width, iconSize.height );
|
||||
iconLabel.setIcon( defaultIcon );
|
||||
} else
|
||||
hasIcon = false;
|
||||
}
|
||||
iconLabel.setIcon( hasIcon ? new FlatTitlePaneIcon( images, iconSize ) : null );
|
||||
|
||||
// show/hide icon
|
||||
iconLabel.setVisible( hasIcon );
|
||||
leftPanel.setBorder( hasIcon ? null : new FlatEmptyBorder( 0, noIconLeftGap, 0, 0 ) );
|
||||
|
||||
updateNativeTitleBarHeightAndHitTestSpotsLater();
|
||||
}
|
||||
@@ -508,7 +502,7 @@ public class FlatTitlePane
|
||||
|
||||
protected void menuBarLayouted() {
|
||||
updateNativeTitleBarHeightAndHitTestSpotsLater();
|
||||
revalidate();
|
||||
doLayout();
|
||||
}
|
||||
|
||||
/*debug
|
||||
@@ -521,17 +515,23 @@ public class FlatTitlePane
|
||||
g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight );
|
||||
}
|
||||
if( debugHitTestSpots != null ) {
|
||||
g.setColor( Color.red );
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
for( Rectangle r : debugHitTestSpots )
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
}
|
||||
if( debugAppIconBounds != null ) {
|
||||
g.setColor( Color.blue);
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
Rectangle r = debugAppIconBounds;
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
paintRect( g, Color.red, r );
|
||||
}
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
paintRect( g, Color.blue, debugAppIconBounds );
|
||||
paintRect( g, Color.blue, debugMinimizeButtonBounds );
|
||||
paintRect( g, Color.magenta, debugMaximizeButtonBounds );
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
}
|
||||
|
||||
private void paintRect( Graphics g, Color color, Rectangle r ) {
|
||||
if( r == null )
|
||||
return;
|
||||
|
||||
g.setColor( color );
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
}
|
||||
debug*/
|
||||
|
||||
@@ -702,9 +702,15 @@ debug*/
|
||||
return window != null && FlatNativeWindowBorder.hasCustomDecoration( window );
|
||||
}
|
||||
|
||||
// used to invoke updateNativeTitleBarHeightAndHitTestSpots() only once from latest invokeLater()
|
||||
private int laterCounter;
|
||||
|
||||
protected void updateNativeTitleBarHeightAndHitTestSpotsLater() {
|
||||
laterCounter++;
|
||||
EventQueue.invokeLater( () -> {
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
laterCounter--;
|
||||
if( laterCounter == 0 )
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -722,8 +728,9 @@ debug*/
|
||||
|
||||
List<Rectangle> hitTestSpots = new ArrayList<>();
|
||||
Rectangle appIconBounds = null;
|
||||
|
||||
if( iconLabel.isVisible() ) {
|
||||
// compute real icon size (without insets; 1px wider for easier hitting)
|
||||
// compute real icon size (without insets; 1px larger for easier hitting)
|
||||
Point location = SwingUtilities.convertPoint( iconLabel, 0, 0, window );
|
||||
Insets iconInsets = iconLabel.getInsets();
|
||||
Rectangle iconBounds = new Rectangle(
|
||||
@@ -759,7 +766,7 @@ debug*/
|
||||
|
||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
|
||||
r = getNativeHitTestSpot( menuBarPlaceholder );
|
||||
r = getNativeHitTestSpot( menuBar );
|
||||
if( r != null ) {
|
||||
Component horizontalGlue = findHorizontalGlue( menuBar );
|
||||
if( horizontalGlue != null ) {
|
||||
@@ -768,18 +775,18 @@ debug*/
|
||||
// the glue component area can used to move the window.
|
||||
|
||||
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
|
||||
int x2 = glueLocation.x + horizontalGlue.getWidth();
|
||||
Rectangle r2;
|
||||
if( getComponentOrientation().isLeftToRight() ) {
|
||||
int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x;
|
||||
r.width -= trailingWidth;
|
||||
r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height );
|
||||
r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height );
|
||||
|
||||
r.width = glueLocation.x - r.x;
|
||||
} else {
|
||||
int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW);
|
||||
r.x += leadingWidth;
|
||||
r.width -= leadingWidth;
|
||||
r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height );
|
||||
r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height );
|
||||
|
||||
r.width = (r.x + r.width) - x2;
|
||||
r.x = x2;
|
||||
}
|
||||
r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
|
||||
hitTestSpots.add( r2 );
|
||||
}
|
||||
|
||||
@@ -787,16 +794,30 @@ debug*/
|
||||
}
|
||||
}
|
||||
|
||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds );
|
||||
Rectangle minimizeButtonBounds = boundsInWindow( iconifyButton );
|
||||
Rectangle maximizeButtonBounds = boundsInWindow( maximizeButton.isVisible() ? maximizeButton : restoreButton );
|
||||
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
||||
|
||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
||||
hitTestSpots, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
|
||||
/*debug
|
||||
debugTitleBarHeight = titleBarHeight;
|
||||
debugHitTestSpots = hitTestSpots;
|
||||
debugAppIconBounds = appIconBounds;
|
||||
debugMinimizeButtonBounds = minimizeButtonBounds;
|
||||
debugMaximizeButtonBounds = maximizeButtonBounds;
|
||||
debugCloseButtonBounds = closeButtonBounds;
|
||||
repaint();
|
||||
debug*/
|
||||
}
|
||||
|
||||
private Rectangle boundsInWindow( JComponent c ) {
|
||||
return c.isShowing()
|
||||
? SwingUtilities.convertRectangle( c.getParent(), c.getBounds(), window )
|
||||
: null;
|
||||
}
|
||||
|
||||
protected Rectangle getNativeHitTestSpot( JComponent c ) {
|
||||
Dimension size = c.getSize();
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
@@ -804,17 +825,16 @@ debug*/
|
||||
|
||||
Point location = SwingUtilities.convertPoint( c, 0, 0, window );
|
||||
Rectangle r = new Rectangle( location, size );
|
||||
// slightly increase rectangle so that component receives mouseExit events
|
||||
r.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
|
||||
return r;
|
||||
}
|
||||
|
||||
private static final int HIT_TEST_SPOT_GROW = 2;
|
||||
|
||||
/*debug
|
||||
private int debugTitleBarHeight;
|
||||
private List<Rectangle> debugHitTestSpots;
|
||||
private Rectangle debugAppIconBounds;
|
||||
private Rectangle debugMinimizeButtonBounds;
|
||||
private Rectangle debugMaximizeButtonBounds;
|
||||
private Rectangle debugCloseButtonBounds;
|
||||
debug*/
|
||||
|
||||
//---- class FlatTitlePaneBorder ------------------------------------------
|
||||
@@ -846,7 +866,7 @@ debug*/
|
||||
Border menuBarBorder = getMenuBarBorder();
|
||||
if( menuBarBorder != null ) {
|
||||
// if menu bar is embedded, paint menu bar border
|
||||
menuBarBorder.paintBorder( c, g, x, y, width, height );
|
||||
menuBarBorder.paintBorder( rootPane.getJMenuBar(), g, x, y, width, height );
|
||||
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) ) {
|
||||
// paint border between title pane and content if border color is specified
|
||||
float lineHeight = UIScale.scale( (float) 1 );
|
||||
|
||||
@@ -54,6 +54,10 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
// https://github.com/oberth/custom-chrome
|
||||
// https://github.com/rossy/borderless-window
|
||||
//
|
||||
// Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
// https://github.com/dotnet/wpf/issues/4825#issuecomment-930442736
|
||||
//
|
||||
|
||||
/**
|
||||
* Native window border support for Windows 10 when using custom decorations.
|
||||
@@ -177,30 +181,24 @@ class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHeight( Window window, int titleBarHeight ) {
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds )
|
||||
{
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.titleBarHeight = titleBarHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||
wndProc.closeButtonBounds = cloneRectange( closeButtonBounds );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
|
||||
private static Rectangle cloneRectange( Rectangle rect ) {
|
||||
return (rect != null) ? new Rectangle( rect ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -303,14 +301,21 @@ class FlatWindowsNativeWindowBorder
|
||||
HTCLIENT = 1,
|
||||
HTCAPTION = 2,
|
||||
HTSYSMENU = 3,
|
||||
HTTOP = 12;
|
||||
HTMINBUTTON = 8,
|
||||
HTMAXBUTTON = 9,
|
||||
HTTOP = 12,
|
||||
HTCLOSE = 20;
|
||||
|
||||
private Window window;
|
||||
private final long hwnd;
|
||||
|
||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||
private int titleBarHeight;
|
||||
private Rectangle[] hitTestSpots;
|
||||
private Rectangle appIconBounds;
|
||||
private Rectangle minimizeButtonBounds;
|
||||
private Rectangle maximizeButtonBounds;
|
||||
private Rectangle closeButtonBounds;
|
||||
|
||||
WndProc( Window window ) {
|
||||
this.window = window;
|
||||
@@ -355,7 +360,7 @@ class FlatWindowsNativeWindowBorder
|
||||
|
||||
// invoked from native code
|
||||
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) {
|
||||
// scale-down mouse x/y
|
||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||
Point pt = scaleDown( x, y );
|
||||
int sx = pt.x;
|
||||
int sy = pt.y;
|
||||
@@ -363,9 +368,26 @@ class FlatWindowsNativeWindowBorder
|
||||
// return HTSYSMENU if mouse is over application icon
|
||||
// - left-click on HTSYSMENU area shows system menu
|
||||
// - double-left-click sends WM_CLOSE
|
||||
if( appIconBounds != null && appIconBounds.contains( sx, sy ) )
|
||||
if( contains( appIconBounds, sx, sy ) )
|
||||
return HTSYSMENU;
|
||||
|
||||
// return HTMINBUTTON if mouse is over minimize button
|
||||
// - hovering mouse over HTMINBUTTON area shows tooltip on Windows 10/11
|
||||
if( contains( minimizeButtonBounds, sx, sy ) )
|
||||
return HTMINBUTTON;
|
||||
|
||||
// return HTMAXBUTTON if mouse is over maximize/restore button
|
||||
// - hovering mouse over HTMAXBUTTON area shows tooltip on Windows 10
|
||||
// - hovering mouse over HTMAXBUTTON area shows snap layouts menu on Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
if( contains( maximizeButtonBounds, sx, sy ) )
|
||||
return HTMAXBUTTON;
|
||||
|
||||
// return HTCLOSE if mouse is over close button
|
||||
// - hovering mouse over HTCLOSE area shows tooltip on Windows 10/11
|
||||
if( contains( closeButtonBounds, sx, sy ) )
|
||||
return HTCLOSE;
|
||||
|
||||
boolean isOnTitleBar = (sy < titleBarHeight);
|
||||
|
||||
if( isOnTitleBar ) {
|
||||
@@ -382,6 +404,10 @@ class FlatWindowsNativeWindowBorder
|
||||
return isOnResizeBorder ? HTTOP : HTCLIENT;
|
||||
}
|
||||
|
||||
private boolean contains( Rectangle rect, int x, int y ) {
|
||||
return (rect != null && rect.contains( x, y ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales down in the same way as AWT.
|
||||
* See AwtWin32GraphicsDevice::ScaleDownX() and ::ScaleDownY()
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.border.Border;
|
||||
|
||||
/**
|
||||
* Border that automatically animates painting on component value changes.
|
||||
* <p>
|
||||
* {@link #getAnimatableValues(Component)} returns the animatable value(s) of the component.
|
||||
* If the value(s) have changed, then {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])}
|
||||
* is invoked multiple times with animated value(s) (from old value(s) to new value(s)).
|
||||
* If {@link #getAnimatableValues(Component)} returns multiple values, then each value
|
||||
* gets its own independent animation, which may start/end at different points in time,
|
||||
* may have different duration, resolution and interpolator.
|
||||
* <p>
|
||||
* Example for an animated border:
|
||||
* <pre>
|
||||
* private class MyAnimatedBorder
|
||||
* implements AnimatedBorder
|
||||
* {
|
||||
* @Override
|
||||
* public float[] getAnimatableValues( Component c ) {
|
||||
* return new float[] { c.isFocusOwner() ? 1 : 0 };
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
* int lh = UIScale.scale( 2 );
|
||||
*
|
||||
* g.setColor( Color.blue );
|
||||
* g.fillRect( x, y + height - lh, Math.round( width * animatedValues[0] ), lh );
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public Insets getBorderInsets( Component c ) {
|
||||
* return UIScale.scale( new Insets( 4, 4, 4, 4 ) );
|
||||
* }
|
||||
*
|
||||
* @Override public boolean isBorderOpaque() { return false; }
|
||||
* }
|
||||
*
|
||||
* // sample usage
|
||||
* JTextField textField = new JTextField();
|
||||
* textField.setBorder( new MyAnimatedBorder() );
|
||||
* </pre>
|
||||
*
|
||||
* Animation works only if the component passed to {@link #paintBorder(Component, Graphics, int, int, int, int)}
|
||||
* is a instance of {@link JComponent}.
|
||||
* A client property is set on the component to store the animation state.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public interface AnimatedBorder
|
||||
extends Border, AnimatedPainter
|
||||
{
|
||||
/**
|
||||
* Invokes {@link #paintWithAnimation(Component, Graphics, int, int, int, int)}.
|
||||
*/
|
||||
@Override
|
||||
default void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
paintWithAnimation( c, g, x, y, width, height );
|
||||
}
|
||||
}
|
||||
@@ -18,62 +18,87 @@ package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import com.formdev.flatlaf.util.Animator.Interpolator;
|
||||
|
||||
/**
|
||||
* Icon that automatically animates painting on component value changes.
|
||||
* <p>
|
||||
* {@link #getValue(Component)} returns the value of the component.
|
||||
* If the value changes, then {@link #paintIconAnimated(Component, Graphics, int, int, float)}
|
||||
* is invoked multiple times with animated value (from old value to new value).
|
||||
* {@link #getAnimatableValues(Component)} returns the animatable value(s) of the component.
|
||||
* If the value(s) have changed, then {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])}
|
||||
* is invoked multiple times with animated value(s) (from old value(s) to new value(s)).
|
||||
* If {@link #getAnimatableValues(Component)} returns multiple values, then each value
|
||||
* gets its own independent animation, which may start/end at different points in time,
|
||||
* may have different duration, resolution and interpolator.
|
||||
* <p>
|
||||
* Example for an animated icon:
|
||||
* <pre>
|
||||
* private class AnimatedMinimalTestIcon
|
||||
* private class MyAnimatedIcon
|
||||
* implements AnimatedIcon
|
||||
* {
|
||||
* @Override
|
||||
* public float[] getAnimatableValues( Component c ) {
|
||||
* return new float[] { ((AbstractButton)c).isSelected() ? 1 : 0 };
|
||||
* }
|
||||
*
|
||||
* @Override public int getIconWidth() { return 100; }
|
||||
* @Override public int getIconHeight() { return 20; }
|
||||
*
|
||||
* @Override
|
||||
* public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||
* int w = getIconWidth();
|
||||
* int h = getIconHeight();
|
||||
*
|
||||
* public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
* g.setColor( Color.red );
|
||||
* g.drawRect( x, y, w - 1, h - 1 );
|
||||
* g.fillRect( x, y, Math.round( w * animatedValue ), h );
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public float getValue( Component c ) {
|
||||
* return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||
* g.drawRect( x, y, width - 1, height - 1 );
|
||||
* g.fillRect( x, y, Math.round( width * animatedValues[0] ), height );
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // sample usage
|
||||
* JCheckBox checkBox = new JCheckBox( "test" );
|
||||
* checkBox.setIcon( new AnimatedMinimalTestIcon() );
|
||||
* checkBox.setIcon( new MyAnimatedIcon() );
|
||||
* </pre>
|
||||
*
|
||||
* Animation works only if the component passed to {@link #paintIcon(Component, Graphics, int, int)}
|
||||
* is a instance of {@link JComponent}.
|
||||
* is an instance of {@link JComponent}.
|
||||
* A client property is set on the component to store the animation state.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public interface AnimatedIcon
|
||||
extends Icon
|
||||
extends Icon, AnimatedPainter
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@Override
|
||||
public default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
AnimationSupport.paintIcon( this, c, g, x, y );
|
||||
default float[] getAnimatableValues( Component c ) {
|
||||
// for compatibility
|
||||
return new float[] { getValue( c ) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the icon for the given animated value.
|
||||
* Invokes {@link #paintWithAnimation(Component, Graphics, int, int, int, int)}.
|
||||
*/
|
||||
@Override
|
||||
default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
paintWithAnimation( c, g, x, y, getIconWidth(), getIconHeight() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@Override
|
||||
default void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
// for compatibility
|
||||
paintIconAnimated( c, g, x, y, animatedValues[0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the icon for the given (animated) value.
|
||||
*
|
||||
* @param c the component that this icon belongs to
|
||||
* @param g the graphics context
|
||||
@@ -82,52 +107,45 @@ public interface AnimatedIcon
|
||||
* @param animatedValue the animated value, which is either equal to what {@link #getValue(Component)}
|
||||
* returned, or somewhere between the previous value and the latest value
|
||||
* that {@link #getValue(Component)} returned
|
||||
*
|
||||
* @deprecated override {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])} instead
|
||||
*/
|
||||
void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue );
|
||||
@Deprecated
|
||||
default void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the component.
|
||||
* Gets the animatable value of the component.
|
||||
* <p>
|
||||
* This can be any value and depends on the component.
|
||||
* If the value changes, then this class animates from the old value to the new one.
|
||||
* <p>
|
||||
* For a toggle button this could be {@code 0} for off and {@code 1} for on.
|
||||
*
|
||||
* @deprecated override {@link #getAnimatableValues(Component)} instead
|
||||
*/
|
||||
float getValue( Component c );
|
||||
|
||||
/**
|
||||
* Returns whether animation is enabled for this icon (default is {@code true}).
|
||||
*/
|
||||
default boolean isAnimationEnabled() {
|
||||
return true;
|
||||
@Deprecated
|
||||
default float getValue( Component c ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the duration of the animation in milliseconds (default is 150).
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @since TODO
|
||||
*/
|
||||
default int getAnimationDuration() {
|
||||
return 150;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resolution of the animation in milliseconds (default is 10).
|
||||
* Resolution is the amount of time between timing events.
|
||||
*/
|
||||
default int getAnimationResolution() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolator for the animation.
|
||||
* Default is {@link CubicBezierEasing#STANDARD_EASING}.
|
||||
*/
|
||||
default Interpolator getAnimationInterpolator() {
|
||||
return CubicBezierEasing.STANDARD_EASING;
|
||||
@Override
|
||||
default Object getAnimationClientPropertyKey() {
|
||||
// for compatibility
|
||||
return getClientPropertyKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client property key used to store the animation support.
|
||||
*
|
||||
* @deprecated override {@link #getAnimationClientPropertyKey()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default Object getClientPropertyKey() {
|
||||
return getClass();
|
||||
}
|
||||
@@ -135,115 +153,25 @@ public interface AnimatedIcon
|
||||
//---- class AnimationSupport ---------------------------------------------
|
||||
|
||||
/**
|
||||
* Animation support class that stores the animation state and implements the animation.
|
||||
* Animation support.
|
||||
*/
|
||||
@Deprecated
|
||||
class AnimationSupport
|
||||
{
|
||||
private float startValue;
|
||||
private float targetValue;
|
||||
private float animatedValue;
|
||||
private float fraction;
|
||||
|
||||
private Animator animator;
|
||||
|
||||
// last x,y coordinates of the icon needed to repaint while animating
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link AnimatedPainter#paintWithAnimation(Component, Graphics, int, int, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static void paintIcon( AnimatedIcon icon, Component c, Graphics g, int x, int y ) {
|
||||
if( !isAnimationEnabled( icon, c ) ) {
|
||||
// paint without animation if animation is disabled or
|
||||
// component is not a JComponent and therefore does not support
|
||||
// client properties, which are required to keep animation state
|
||||
paintIconImpl( icon, c, g, x, y, null );
|
||||
return;
|
||||
}
|
||||
|
||||
JComponent jc = (JComponent) c;
|
||||
Object key = icon.getClientPropertyKey();
|
||||
AnimationSupport as = (AnimationSupport) jc.getClientProperty( key );
|
||||
if( as == null ) {
|
||||
// painted first time --> do not animate, but remember current component value
|
||||
as = new AnimationSupport();
|
||||
as.startValue = as.targetValue = as.animatedValue = icon.getValue( c );
|
||||
as.x = x;
|
||||
as.y = y;
|
||||
jc.putClientProperty( key, as );
|
||||
} else {
|
||||
// get component value
|
||||
float value = icon.getValue( c );
|
||||
|
||||
if( value != as.targetValue ) {
|
||||
// value changed --> (re)start animation
|
||||
|
||||
if( as.animator == null ) {
|
||||
// create animator
|
||||
AnimationSupport as2 = as;
|
||||
as.animator = new Animator( icon.getAnimationDuration(), fraction -> {
|
||||
// check whether component was removed while animation is running
|
||||
if( !c.isDisplayable() ) {
|
||||
as2.animator.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// compute animated value
|
||||
as2.animatedValue = as2.startValue + ((as2.targetValue - as2.startValue) * fraction);
|
||||
as2.fraction = fraction;
|
||||
|
||||
// repaint icon
|
||||
c.repaint( as2.x, as2.y, icon.getIconWidth(), icon.getIconHeight() );
|
||||
}, () -> {
|
||||
as2.startValue = as2.animatedValue = as2.targetValue;
|
||||
as2.animator = null;
|
||||
} );
|
||||
}
|
||||
|
||||
if( as.animator.isRunning() ) {
|
||||
// if animation is still running, restart it from the current
|
||||
// animated value to the new target value with reduced duration
|
||||
as.animator.cancel();
|
||||
int duration2 = (int) (icon.getAnimationDuration() * as.fraction);
|
||||
if( duration2 > 0 )
|
||||
as.animator.setDuration( duration2 );
|
||||
as.startValue = as.animatedValue;
|
||||
} else {
|
||||
// new animation
|
||||
as.animator.setDuration( icon.getAnimationDuration() );
|
||||
as.animator.setResolution( icon.getAnimationResolution() );
|
||||
as.animator.setInterpolator( icon.getAnimationInterpolator() );
|
||||
|
||||
as.animatedValue = as.startValue;
|
||||
}
|
||||
|
||||
as.targetValue = value;
|
||||
as.animator.start();
|
||||
}
|
||||
|
||||
as.x = x;
|
||||
as.y = y;
|
||||
}
|
||||
|
||||
paintIconImpl( icon, c, g, x, y, as );
|
||||
}
|
||||
|
||||
private static void paintIconImpl( AnimatedIcon icon, Component c, Graphics g, int x, int y, AnimationSupport as ) {
|
||||
float value = (as != null) ? as.animatedValue : icon.getValue( c );
|
||||
icon.paintIconAnimated( c, g, x, y, value );
|
||||
}
|
||||
|
||||
private static boolean isAnimationEnabled( AnimatedIcon icon, Component c ) {
|
||||
return Animator.useAnimation() && icon.isAnimationEnabled() && c instanceof JComponent;
|
||||
AnimatedPainterSupport.paint( icon, c, (Graphics2D) g, x, y, icon.getIconWidth(), icon.getIconHeight() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link AnimatedPainter#saveRepaintLocation(AnimatedPainter, Component, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static void saveIconLocation( AnimatedIcon icon, Component c, int x, int y ) {
|
||||
if( !isAnimationEnabled( icon, c ) )
|
||||
return;
|
||||
|
||||
AnimationSupport as = (AnimationSupport) ((JComponent)c).getClientProperty( icon.getClientPropertyKey() );
|
||||
if( as != null ) {
|
||||
as.x = x;
|
||||
as.y = y;
|
||||
}
|
||||
AnimatedPainterSupport.saveRepaintLocation( icon, c, x, y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.JComponent;
|
||||
import com.formdev.flatlaf.util.Animator.Interpolator;
|
||||
|
||||
/**
|
||||
* Painter that automatically animates painting on component value(s) changes.
|
||||
* <p>
|
||||
* {@link #getAnimatableValues(Component)} returns the animatable value(s) of the component.
|
||||
* If the value(s) have changed, then {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])}
|
||||
* is invoked multiple times with animated value(s) (from old value(s) to new value(s)).
|
||||
* If {@link #getAnimatableValues(Component)} returns multiple values, then each value
|
||||
* gets its own independent animation, which may start/end at different points in time,
|
||||
* may have different duration, resolution and interpolator.
|
||||
* <p>
|
||||
* See {@link AnimatedBorder} or {@link AnimatedIcon} for examples.
|
||||
* <p>
|
||||
* Animation works only if the component passed to {@link #paintWithAnimation(Component, Graphics, int, int, int, int)}
|
||||
* is an instance of {@link JComponent}.
|
||||
* A client property is set on the component to store the animation state.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public interface AnimatedPainter
|
||||
{
|
||||
/**
|
||||
* Gets the animatable value(s) of the component.
|
||||
* <p>
|
||||
* This can be any value(s) and depends on the component.
|
||||
* If the value(s) changes, then this class animates from the old value(s) to the new ones.
|
||||
* If multiple values are returned, then each value gets its own independent animation.
|
||||
* <p>
|
||||
* For a toggle button this could be {@code 0} for off and {@code 1} for on.
|
||||
* A complex check box could return values for selected, hover, pressed and focused states.
|
||||
* The painter then can show independent animations for those states.
|
||||
*/
|
||||
float[] getAnimatableValues( Component c );
|
||||
|
||||
/**
|
||||
* Starts painting.
|
||||
* Either invokes {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])}
|
||||
* once to paint current value(s) (see {@link #getAnimatableValues(Component)}. Or if value(s) has
|
||||
* changed, compared to last painting, then it starts an animation and invokes
|
||||
* {@link #paintAnimated(Component, Graphics2D, int, int, int, int, float[])}
|
||||
* multiple times with animated value(s) (from old value(s) to new value(s)).
|
||||
*
|
||||
* @param c the component that this painter belongs to
|
||||
* @param g the graphics context
|
||||
* @param x the x coordinate of the paint area
|
||||
* @param y the y coordinate of the paint area
|
||||
* @param width the width of the paint area
|
||||
* @param height the height of the paint area
|
||||
*/
|
||||
default void paintWithAnimation( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
AnimatedPainterSupport.paint( this, c, (Graphics2D) g, x, y, width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the given (animated) value(s).
|
||||
* <p>
|
||||
* Invoked from {@link #paintWithAnimation(Component, Graphics, int, int, int, int)}.
|
||||
*
|
||||
* @param c the component that this painter belongs to
|
||||
* @param g the graphics context
|
||||
* @param x the x coordinate of the paint area
|
||||
* @param y the y coordinate of the paint area
|
||||
* @param width the width of the paint area
|
||||
* @param height the height of the paint area
|
||||
* @param animatedValues the animated values, which are either equal to what {@link #getAnimatableValues(Component)}
|
||||
* returned, or somewhere between the previous values and the latest values
|
||||
* that {@link #getAnimatableValues(Component)} returned
|
||||
*/
|
||||
void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues );
|
||||
|
||||
/**
|
||||
* Invoked from animator to repaint an area.
|
||||
* <p>
|
||||
* Useful to limit the repaint region. E.g. if only the bottom border is animated.
|
||||
* If more than one border side is animated (e.g. bottom and right side), then it
|
||||
* makes no sense to do separate repaints because the Swing repaint manager unions
|
||||
* the regions and the whole component is repainted.
|
||||
* <p>
|
||||
* The default implementation repaints the whole given area.
|
||||
*/
|
||||
default void repaintDuringAnimation( Component c, int x, int y, int width, int height ) {
|
||||
c.repaint( x, y, width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether animation is enabled for this painter (default is {@code true}).
|
||||
*/
|
||||
default boolean isAnimationEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the duration of the animation in milliseconds (default is 150).
|
||||
*/
|
||||
default int getAnimationDuration() {
|
||||
return 150;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resolution of the animation in milliseconds (default is 10).
|
||||
* Resolution is the amount of time between timing events.
|
||||
*/
|
||||
default int getAnimationResolution() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolator for the animation.
|
||||
* Default is {@link CubicBezierEasing#STANDARD_EASING}.
|
||||
*/
|
||||
default Interpolator getAnimationInterpolator() {
|
||||
return CubicBezierEasing.STANDARD_EASING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the duration of the animation in milliseconds (default is 150)
|
||||
* for the given value index and value.
|
||||
*/
|
||||
default int getAnimationDuration( int valueIndex, float value ) {
|
||||
return getAnimationDuration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resolution of the animation in milliseconds (default is 10)
|
||||
* for the given value index and value.
|
||||
* Resolution is the amount of time between timing events.
|
||||
*/
|
||||
default int getAnimationResolution( int valueIndex, float value ) {
|
||||
return getAnimationResolution();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolator for the animation
|
||||
* for the given value index and value.
|
||||
* Default is {@link CubicBezierEasing#STANDARD_EASING}.
|
||||
*/
|
||||
default Interpolator getAnimationInterpolator( int valueIndex, float value ) {
|
||||
return getAnimationInterpolator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client property key used to store the animation support.
|
||||
*/
|
||||
default Object getAnimationClientPropertyKey() {
|
||||
return getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves location for repainting animated area with
|
||||
* {@link AnimatedPainter#repaintDuringAnimation(Component, int, int, int, int)}.
|
||||
* Only needed when graphics context passed to {@link #paintWithAnimation(Component, Graphics, int, int, int, int)}
|
||||
* uses transformed location.
|
||||
*/
|
||||
static void saveRepaintLocation( AnimatedPainter painter, Component c, int x, int y ) {
|
||||
AnimatedPainterSupport.saveRepaintLocation( painter, c, x, y );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
/**
|
||||
* Animation support class that stores the animation state and implements the animation.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
class AnimatedPainterSupport
|
||||
{
|
||||
private final int valueIndex;
|
||||
|
||||
private float startValue;
|
||||
private float targetValue;
|
||||
private float animatedValue;
|
||||
private float fraction;
|
||||
|
||||
private Animator animator;
|
||||
|
||||
// last bounds of the paint area needed to repaint while animating
|
||||
private int x;
|
||||
private int y;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
private AnimatedPainterSupport( int valueIndex ) {
|
||||
this.valueIndex = valueIndex;
|
||||
}
|
||||
|
||||
static void paint( AnimatedPainter painter, Component c, Graphics2D g,
|
||||
int x, int y, int width, int height )
|
||||
{
|
||||
// get animatable component values
|
||||
float[] values = painter.getAnimatableValues( c );
|
||||
|
||||
if( !isAnimationEnabled( painter, c ) ) {
|
||||
// paint without animation if animation is disabled or
|
||||
// component is not a JComponent and therefore does not support
|
||||
// client properties, which are required to keep animation state
|
||||
painter.paintAnimated( c, g, x, y, width, height, values );
|
||||
return;
|
||||
}
|
||||
|
||||
JComponent jc = (JComponent) c;
|
||||
Object key = painter.getAnimationClientPropertyKey();
|
||||
AnimatedPainterSupport[] ass = (AnimatedPainterSupport[]) jc.getClientProperty( key );
|
||||
|
||||
// check whether length of values array has changed
|
||||
if( ass != null && ass.length != values.length ) {
|
||||
// cancel all running animations
|
||||
for( int i = 0; i < ass.length; i++ ) {
|
||||
AnimatedPainterSupport as = ass[i];
|
||||
if( as.animator != null )
|
||||
as.animator.cancel();
|
||||
}
|
||||
ass = null;
|
||||
}
|
||||
|
||||
if( ass == null ) {
|
||||
ass = new AnimatedPainterSupport[values.length];
|
||||
jc.putClientProperty( key, ass );
|
||||
}
|
||||
|
||||
for( int i = 0; i < ass.length; i++ ) {
|
||||
AnimatedPainterSupport as = ass[i];
|
||||
float value = values[i];
|
||||
|
||||
if( as == null ) {
|
||||
// painted first time --> do not animate, but remember current component value
|
||||
as = new AnimatedPainterSupport( i );
|
||||
as.startValue = as.targetValue = as.animatedValue = value;
|
||||
ass[i] = as;
|
||||
} else if( value != as.targetValue ) {
|
||||
// value changed --> (re)start animation
|
||||
|
||||
int animationDuration = painter.getAnimationDuration( as.valueIndex, value );
|
||||
|
||||
// do not animate if animation duration (for current value) is zero
|
||||
if( animationDuration <= 0 ) {
|
||||
if( as.animator != null ) {
|
||||
as.animator.cancel();
|
||||
as.animator = null;
|
||||
}
|
||||
as.startValue = as.targetValue = as.animatedValue = value;
|
||||
as.fraction = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( as.animator == null ) {
|
||||
// create animator
|
||||
AnimatedPainterSupport as2 = as;
|
||||
as.animator = new Animator( 1, fraction -> {
|
||||
// check whether component was removed while animation is running
|
||||
if( !c.isDisplayable() ) {
|
||||
as2.animator.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// compute animated value
|
||||
as2.animatedValue = as2.startValue + ((as2.targetValue - as2.startValue) * fraction);
|
||||
as2.fraction = fraction;
|
||||
|
||||
// repaint
|
||||
painter.repaintDuringAnimation( c, as2.x, as2.y, as2.width, as2.height );
|
||||
}, () -> {
|
||||
as2.startValue = as2.animatedValue = as2.targetValue;
|
||||
as2.animator = null;
|
||||
} );
|
||||
}
|
||||
|
||||
if( as.animator.isRunning() ) {
|
||||
// if animation is still running, restart it from the current
|
||||
// animated value to the new target value with reduced duration
|
||||
as.animator.cancel();
|
||||
int duration2 = (int) (animationDuration * as.fraction);
|
||||
if( duration2 > 0 )
|
||||
as.animator.setDuration( duration2 );
|
||||
as.startValue = as.animatedValue;
|
||||
} else {
|
||||
// new animation
|
||||
as.animator.setDuration( animationDuration );
|
||||
|
||||
as.animatedValue = as.startValue;
|
||||
}
|
||||
|
||||
// update animator for new value
|
||||
as.animator.setResolution( painter.getAnimationResolution( as.valueIndex, value ) );
|
||||
as.animator.setInterpolator( painter.getAnimationInterpolator( as.valueIndex, value ) );
|
||||
|
||||
// start animation
|
||||
as.targetValue = value;
|
||||
as.animator.start();
|
||||
}
|
||||
|
||||
as.x = x;
|
||||
as.y = y;
|
||||
as.width = width;
|
||||
as.height = height;
|
||||
}
|
||||
|
||||
float[] animatedValues = new float[ass.length];
|
||||
for( int i = 0; i < ass.length; i++ )
|
||||
animatedValues[i] = ass[i].animatedValue;
|
||||
|
||||
painter.paintAnimated( c, g, x, y, width, height, animatedValues );
|
||||
}
|
||||
|
||||
private static boolean isAnimationEnabled( AnimatedPainter painter, Component c ) {
|
||||
return Animator.useAnimation() && painter.isAnimationEnabled() && c instanceof JComponent;
|
||||
}
|
||||
|
||||
static void saveRepaintLocation( AnimatedPainter painter, Component c, int x, int y ) {
|
||||
if( !isAnimationEnabled( painter, c ) )
|
||||
return;
|
||||
|
||||
AnimatedPainterSupport[] ass = (AnimatedPainterSupport[]) ((JComponent)c).getClientProperty( painter.getAnimationClientPropertyKey() );
|
||||
if( ass != null ) {
|
||||
for( int i = 0; i < ass.length; i++ ) {
|
||||
AnimatedPainterSupport as = ass[i];
|
||||
as.x = x;
|
||||
as.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* A simple cache (map) that uses soft references for the values.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public class SoftCache<K,V>
|
||||
implements Map<K, V>
|
||||
{
|
||||
private final Map<K, CacheReference<K,V>> map;
|
||||
private final ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
public SoftCache() {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
public SoftCache( int initialCapacity ) {
|
||||
map = new HashMap<>( initialCapacity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
expungeStaleEntries();
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
expungeStaleEntries();
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return map.containsKey( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValue( Object value ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.get( key ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put( K key, V value ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.put( key, new CacheReference<>( key, value, queue ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.remove( key ) );
|
||||
}
|
||||
|
||||
private V getRef( CacheReference<K,V> ref ) {
|
||||
return (ref != null) ? ref.get() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll( Map<? extends K, ? extends V> m ) {
|
||||
expungeStaleEntries();
|
||||
for( Entry<? extends K, ? extends V> e : m.entrySet() )
|
||||
put( e.getKey(), e.getValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
expungeStaleEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
expungeStaleEntries();
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public void forEach( BiConsumer<? super K, ? super V> action ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public void replaceAll( BiFunction<? super K, ? super V, ? extends V> function ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private void expungeStaleEntries() {
|
||||
Reference<? extends V> reference;
|
||||
while( (reference = queue.poll()) != null )
|
||||
map.remove( ((CacheReference<K,V>)reference).key );
|
||||
}
|
||||
|
||||
//---- class CacheReference ----
|
||||
|
||||
private static class CacheReference<K,V>
|
||||
extends SoftReference<V>
|
||||
{
|
||||
// needed to remove reference from map in expungeStaleEntries()
|
||||
final K key;
|
||||
|
||||
CacheReference( K key, V value, ReferenceQueue<? super V> queue ) {
|
||||
super( value, queue );
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ public class SystemInfo
|
||||
public static final boolean isJava_9_orLater;
|
||||
public static final boolean isJava_11_orLater;
|
||||
public static final boolean isJava_15_orLater;
|
||||
/** @since 2 */ public static final boolean isJava_17_orLater;
|
||||
|
||||
// Java VMs
|
||||
public static final boolean isJetBrainsJVM;
|
||||
@@ -82,6 +83,7 @@ public class SystemInfo
|
||||
isJava_9_orLater = (javaVersion >= toVersion( 9, 0, 0, 0 ));
|
||||
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
|
||||
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
|
||||
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
|
||||
|
||||
// Java VMs
|
||||
isJetBrainsJVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
||||
|
||||
@@ -26,6 +26,68 @@
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
#---- typography / fonts ----
|
||||
|
||||
# headings
|
||||
h00.font = +24
|
||||
h0.font = +18
|
||||
h1.font = +12 $semibold.font
|
||||
h2.font = +6 $semibold.font
|
||||
h3.font = +3 $semibold.font
|
||||
h4.font = bold
|
||||
|
||||
h1.regular.font = +12
|
||||
h2.regular.font = +6
|
||||
h3.regular.font = +3
|
||||
|
||||
# text
|
||||
large.font = +2
|
||||
medium.font = -1
|
||||
small.font = -2
|
||||
mini.font = -3
|
||||
|
||||
# default font
|
||||
#defaultFont = ...
|
||||
|
||||
# font weights
|
||||
# Windows
|
||||
[win]light.font = "Segoe UI Light"
|
||||
[win]semibold.font = "Segoe UI Semibold"
|
||||
# macOS
|
||||
[mac]light.font = "HelveticaNeue-Thin"
|
||||
[mac]semibold.font = "HelveticaNeue-Medium"
|
||||
# Linux
|
||||
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
|
||||
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium"
|
||||
# fallback for unknown platform
|
||||
light.font = +0
|
||||
semibold.font = +0
|
||||
|
||||
# monospaced
|
||||
[win]monospaced.font = Consolas, "Courier New", Monospaced
|
||||
[mac]monospaced.font = Menlo, Monospaced
|
||||
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
|
||||
monospaced.font = Monospaced
|
||||
|
||||
# styles
|
||||
[style].h00 = font: $h00.font
|
||||
[style].h0 = font: $h0.font
|
||||
[style].h1 = font: $h1.font
|
||||
[style].h2 = font: $h2.font
|
||||
[style].h3 = font: $h3.font
|
||||
[style].h4 = font: $h4.font
|
||||
[style].h1.regular = font: $h1.regular.font
|
||||
[style].h2.regular = font: $h2.regular.font
|
||||
[style].h3.regular = font: $h3.regular.font
|
||||
[style].large = font: $large.font
|
||||
[style].medium = font: $medium.font
|
||||
[style].small = font: $small.font
|
||||
[style].mini = font: $mini.font
|
||||
[style].light = font: $light.font
|
||||
[style].semibold = font: $semibold.font
|
||||
[style].monospaced = font: $monospaced.font
|
||||
|
||||
|
||||
#---- UI delegates ----
|
||||
|
||||
ButtonUI = com.formdev.flatlaf.ui.FlatButtonUI
|
||||
@@ -394,6 +456,7 @@ OptionPane.messageAreaBorder = 0,0,0,0
|
||||
OptionPane.buttonAreaBorder = 12,0,0,0
|
||||
OptionPane.messageForeground = null
|
||||
|
||||
OptionPane.showIcon = false
|
||||
OptionPane.maxCharactersPerLine = 80
|
||||
OptionPane.iconMessageGap = 16
|
||||
OptionPane.messagePadding = 3
|
||||
@@ -587,6 +650,7 @@ SplitPaneDivider.gripGap = 2
|
||||
|
||||
TabbedPane.tabHeight = 32
|
||||
TabbedPane.tabSelectionHeight = 3
|
||||
TabbedPane.cardTabSelectionHeight = 2
|
||||
TabbedPane.contentSeparatorHeight = 1
|
||||
TabbedPane.showTabSeparators = false
|
||||
TabbedPane.tabSeparatorsFullHeight = false
|
||||
@@ -608,6 +672,9 @@ TabbedPane.tabAlignment = center
|
||||
# allowed values: preferred, equal or compact
|
||||
TabbedPane.tabWidthMode = preferred
|
||||
|
||||
# allowed values: underlined or card
|
||||
TabbedPane.tabType = underlined
|
||||
|
||||
# allowed values: chevron or triangle
|
||||
TabbedPane.arrowType = chevron
|
||||
TabbedPane.buttonInsets = 2,1,2,1
|
||||
@@ -709,7 +776,9 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground
|
||||
|
||||
TitlePane.useWindowDecorations = true
|
||||
TitlePane.menuBarEmbedded = true
|
||||
TitlePane.unifiedBackground = false
|
||||
TitlePane.unifiedBackground = true
|
||||
TitlePane.showIcon = true
|
||||
TitlePane.noIconLeftGap = 8
|
||||
TitlePane.iconSize = 16,16
|
||||
TitlePane.iconMargins = 3,8,3,8
|
||||
TitlePane.titleMargins = 3,0,3,0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -685,12 +685,14 @@ public class TestFlatStyleableInfo
|
||||
"maximumTabWidth", int.class,
|
||||
"tabHeight", int.class,
|
||||
"tabSelectionHeight", int.class,
|
||||
"cardTabSelectionHeight", int.class,
|
||||
"contentSeparatorHeight", int.class,
|
||||
"showTabSeparators", boolean.class,
|
||||
"tabSeparatorsFullHeight", boolean.class,
|
||||
"hasFullBorder", boolean.class,
|
||||
"tabsOpaque", boolean.class,
|
||||
|
||||
"tabType", String.class,
|
||||
"tabsPopupPolicy", String.class,
|
||||
"scrollButtonsPolicy", String.class,
|
||||
"scrollButtonsPlacement", String.class,
|
||||
|
||||
@@ -849,12 +849,14 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "maximumTabWidth: 100" );
|
||||
ui.applyStyle( "tabHeight: 30" );
|
||||
ui.applyStyle( "tabSelectionHeight: 3" );
|
||||
ui.applyStyle( "cardTabSelectionHeight: 2" );
|
||||
ui.applyStyle( "contentSeparatorHeight: 1" );
|
||||
ui.applyStyle( "showTabSeparators: false" );
|
||||
ui.applyStyle( "tabSeparatorsFullHeight: false" );
|
||||
ui.applyStyle( "hasFullBorder: false" );
|
||||
ui.applyStyle( "tabsOpaque: false" );
|
||||
|
||||
ui.applyStyle( "tabType: card" );
|
||||
ui.applyStyle( "tabsPopupPolicy: asNeeded" );
|
||||
ui.applyStyle( "scrollButtonsPolicy: asNeeded" );
|
||||
ui.applyStyle( "scrollButtonsPlacement: both" );
|
||||
|
||||
@@ -22,6 +22,10 @@ import javax.swing.text.DefaultEditorKit;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
import com.formdev.flatlaf.icons.FlatSearchIcon;
|
||||
import net.miginfocom.layout.AC;
|
||||
import net.miginfocom.layout.BoundSize;
|
||||
import net.miginfocom.layout.ConstraintParser;
|
||||
import net.miginfocom.layout.DimConstraint;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -130,6 +134,22 @@ class BasicComponentsPanel
|
||||
JTextField leadingIconTextField = new JTextField();
|
||||
JTextField trailingIconTextField = new JTextField();
|
||||
JTextField iconsTextField = new JTextField();
|
||||
JLabel fontsLabel = new JLabel();
|
||||
JLabel h00Label = new JLabel();
|
||||
JLabel h0Label = new JLabel();
|
||||
JLabel h1Label = new JLabel();
|
||||
JLabel h2Label = new JLabel();
|
||||
JLabel h3Label = new JLabel();
|
||||
JLabel h4Label = new JLabel();
|
||||
JLabel lightLabel = new JLabel();
|
||||
JLabel semiboldLabel = new JLabel();
|
||||
JLabel fontZoomLabel = new JLabel();
|
||||
JLabel largeLabel = new JLabel();
|
||||
JLabel defaultLabel = new JLabel();
|
||||
JLabel mediumLabel = new JLabel();
|
||||
JLabel smallLabel = new JLabel();
|
||||
JLabel miniLabel = new JLabel();
|
||||
JLabel monospacedLabel = new JLabel();
|
||||
JPopupMenu popupMenu1 = new JPopupMenu();
|
||||
JMenuItem cutMenuItem = new JMenuItem();
|
||||
JMenuItem copyMenuItem = new JMenuItem();
|
||||
@@ -160,6 +180,8 @@ class BasicComponentsPanel
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]0" +
|
||||
"[]"));
|
||||
|
||||
//---- labelLabel ----
|
||||
@@ -667,6 +689,85 @@ class BasicComponentsPanel
|
||||
iconsTextField.setText("text");
|
||||
add(iconsTextField, "cell 3 14,growx");
|
||||
|
||||
//---- fontsLabel ----
|
||||
fontsLabel.setText("Typography / Fonts:");
|
||||
add(fontsLabel, "cell 0 15");
|
||||
|
||||
//---- h00Label ----
|
||||
h00Label.setText("H00");
|
||||
h00Label.putClientProperty("FlatLaf.styleClass", "h00");
|
||||
add(h00Label, "cell 1 15 5 1");
|
||||
|
||||
//---- h0Label ----
|
||||
h0Label.setText("H0");
|
||||
h0Label.putClientProperty("FlatLaf.styleClass", "h0");
|
||||
add(h0Label, "cell 1 15 5 1");
|
||||
|
||||
//---- h1Label ----
|
||||
h1Label.setText("H1");
|
||||
h1Label.putClientProperty("FlatLaf.styleClass", "h1");
|
||||
add(h1Label, "cell 1 15 5 1");
|
||||
|
||||
//---- h2Label ----
|
||||
h2Label.setText("H2");
|
||||
h2Label.putClientProperty("FlatLaf.styleClass", "h2");
|
||||
add(h2Label, "cell 1 15 5 1");
|
||||
|
||||
//---- h3Label ----
|
||||
h3Label.setText("H3");
|
||||
h3Label.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(h3Label, "cell 1 15 5 1");
|
||||
|
||||
//---- h4Label ----
|
||||
h4Label.setText("H4");
|
||||
h4Label.putClientProperty("FlatLaf.styleClass", "h4");
|
||||
add(h4Label, "cell 1 15 5 1");
|
||||
|
||||
//---- lightLabel ----
|
||||
lightLabel.setText("light");
|
||||
lightLabel.putClientProperty("FlatLaf.style", "font: 200% $light.font");
|
||||
add(lightLabel, "cell 1 15 5 1,gapx 30");
|
||||
|
||||
//---- semiboldLabel ----
|
||||
semiboldLabel.setText("semibold");
|
||||
semiboldLabel.putClientProperty("FlatLaf.style", "font: 200% $semibold.font");
|
||||
add(semiboldLabel, "cell 1 15 5 1");
|
||||
|
||||
//---- fontZoomLabel ----
|
||||
fontZoomLabel.setText("(200%)");
|
||||
fontZoomLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
fontZoomLabel.setEnabled(false);
|
||||
add(fontZoomLabel, "cell 1 15 5 1");
|
||||
|
||||
//---- largeLabel ----
|
||||
largeLabel.setText("large");
|
||||
largeLabel.putClientProperty("FlatLaf.styleClass", "large");
|
||||
add(largeLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- defaultLabel ----
|
||||
defaultLabel.setText("default");
|
||||
add(defaultLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- mediumLabel ----
|
||||
mediumLabel.setText("medium");
|
||||
mediumLabel.putClientProperty("FlatLaf.styleClass", "medium");
|
||||
add(mediumLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- smallLabel ----
|
||||
smallLabel.setText("small");
|
||||
smallLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(smallLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- miniLabel ----
|
||||
miniLabel.setText("mini");
|
||||
miniLabel.putClientProperty("FlatLaf.styleClass", "mini");
|
||||
add(miniLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- monospacedLabel ----
|
||||
monospacedLabel.setText("monospaced");
|
||||
monospacedLabel.putClientProperty("FlatLaf.styleClass", "monospaced");
|
||||
add(monospacedLabel, "cell 1 16 5 1,gapx 30");
|
||||
|
||||
//======== popupMenu1 ========
|
||||
{
|
||||
|
||||
@@ -705,37 +806,55 @@ class BasicComponentsPanel
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
// hide some components
|
||||
Component[] hiddenComponents = {
|
||||
labelLabel, label1, label2,
|
||||
button13, button14, button15, button16, comboBox5, comboBox6,
|
||||
textField6, passwordField5,
|
||||
|
||||
textFieldLabel, textField2, textField4, textField6,
|
||||
formattedTextFieldLabel, formattedTextField1, formattedTextField2, formattedTextField3, formattedTextField4, formattedTextField5,
|
||||
passwordFieldLabel, passwordField1, passwordField2, passwordField3, passwordField4, passwordField5,
|
||||
textAreaLabel, scrollPane1, scrollPane2, scrollPane3, scrollPane4, textArea5,
|
||||
editorPaneLabel, scrollPane5, scrollPane6, scrollPane7, scrollPane8, editorPane5,
|
||||
textPaneLabel, scrollPane9, scrollPane10, scrollPane11, scrollPane12, textPane5,
|
||||
|
||||
errorHintsLabel, errorHintsTextField, errorHintsComboBox, errorHintsSpinner,
|
||||
warningHintsLabel, warningHintsTextField, warningHintsComboBox, warningHintsSpinner,
|
||||
|
||||
fontZoomLabel,
|
||||
};
|
||||
for( Component c : hiddenComponents )
|
||||
c.setVisible( false );
|
||||
|
||||
// move leading/trailing icon fields and password fields some rows up
|
||||
Component[] formattedTextFields = { formattedTextFieldLabel, formattedTextField1, formattedTextField2, formattedTextField3, formattedTextField4 };
|
||||
Component[] passwordFields = { passwordFieldLabel, passwordField1, passwordField2, passwordField3, passwordField4 };
|
||||
Component[] iconsFields = { iconsLabel, leadingIconTextField, trailingIconTextField, iconsTextField };
|
||||
// update layout (change row gaps to zero)
|
||||
MigLayout layout = (MigLayout) getLayout();
|
||||
for( int i = 0; i < iconsFields.length; i++ ) {
|
||||
Object cons = layout.getComponentConstraints( passwordFields[i] );
|
||||
layout.setComponentConstraints( iconsFields[i], cons );
|
||||
}
|
||||
for( int i = 0; i < passwordFields.length; i++ ) {
|
||||
Object cons = layout.getComponentConstraints( formattedTextFields[i] );
|
||||
layout.setComponentConstraints( passwordFields[i], cons );
|
||||
}
|
||||
Object rowCons = layout.getRowConstraints();
|
||||
AC ac = (rowCons instanceof String)
|
||||
? ConstraintParser.parseColumnConstraints( (String) rowCons )
|
||||
: (AC) rowCons;
|
||||
BoundSize zeroGap = ConstraintParser.parseBoundSize( "0", true, true );
|
||||
DimConstraint[] rows = ac.getConstaints();
|
||||
rows[6].setGapBefore( zeroGap );
|
||||
rows[7].setGapBefore( zeroGap );
|
||||
rows[8].setGapBefore( zeroGap );
|
||||
rows[9].setGapBefore( zeroGap );
|
||||
rows[10].setGapBefore( zeroGap );
|
||||
rows[11].setGapBefore( zeroGap );
|
||||
rows[11].setGapAfter( zeroGap );
|
||||
rows[12].setGapBefore( zeroGap );
|
||||
rows[13].setGapBefore( zeroGap );
|
||||
rows[15].setGapBefore( zeroGap );
|
||||
layout.setRowConstraints( ac );
|
||||
|
||||
// move two text field into same row as spinners
|
||||
spinnerLabel.setText( "JSpinner / JTextField:" );
|
||||
layout.setComponentConstraints( textField1, "cell 3 5,growx" );
|
||||
layout.setComponentConstraints( textField3, "cell 4 5,growx" );
|
||||
|
||||
// make "Not editable disabled" combobox smaller
|
||||
Object cons = layout.getComponentConstraints( comboBox4 );
|
||||
layout.setComponentConstraints( comboBox4, cons + ",width 50:50" );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][sizegroup 1][sizegroup 1][sizegroup 1][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]para[][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]para[][][][]0[]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
@@ -671,9 +671,120 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 14,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fontsLabel"
|
||||
"text": "Typography / Fonts:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 15"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h00Label"
|
||||
"text": "H00"
|
||||
"$client.FlatLaf.styleClass": "h00"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h0Label"
|
||||
"text": "H0"
|
||||
"$client.FlatLaf.styleClass": "h0"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h1Label"
|
||||
"text": "H1"
|
||||
"$client.FlatLaf.styleClass": "h1"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h2Label"
|
||||
"text": "H2"
|
||||
"$client.FlatLaf.styleClass": "h2"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h3Label"
|
||||
"text": "H3"
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h4Label"
|
||||
"text": "H4"
|
||||
"$client.FlatLaf.styleClass": "h4"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "lightLabel"
|
||||
"text": "light"
|
||||
"$client.FlatLaf.style": "font: 200% $light.font"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1,gapx 30"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "semiboldLabel"
|
||||
"text": "semibold"
|
||||
"$client.FlatLaf.style": "font: 200% $semibold.font"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fontZoomLabel"
|
||||
"text": "(200%)"
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"enabled": false
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "largeLabel"
|
||||
"text": "large"
|
||||
"$client.FlatLaf.styleClass": "large"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "defaultLabel"
|
||||
"text": "default"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "mediumLabel"
|
||||
"text": "medium"
|
||||
"$client.FlatLaf.styleClass": "medium"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "smallLabel"
|
||||
"text": "small"
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "miniLabel"
|
||||
"text": "mini"
|
||||
"$client.FlatLaf.styleClass": "mini"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "monospacedLabel"
|
||||
"text": "monospaced"
|
||||
"$client.FlatLaf.styleClass": "monospaced"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1,gapx 30"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 920, 480 )
|
||||
"size": new java.awt.Dimension( 920, 550 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
|
||||
name: "popupMenu1"
|
||||
@@ -693,7 +804,7 @@ new FormModel {
|
||||
"mnemonic": 80
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 500 )
|
||||
"location": new java.awt.Point( 0, 570 )
|
||||
"size": new java.awt.Dimension( 91, 87 )
|
||||
} )
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.prefs.Preferences;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||
import com.formdev.flatlaf.FlatDarkLaf;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
@@ -50,7 +51,6 @@ import com.formdev.flatlaf.ui.JBRCustomDecorations;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.layout.ConstraintParser;
|
||||
import net.miginfocom.layout.LC;
|
||||
import net.miginfocom.layout.UnitValue;
|
||||
@@ -160,8 +160,7 @@ class DemoFrame
|
||||
|
||||
private void aboutActionPerformed() {
|
||||
JLabel titleLabel = new JLabel( "FlatLaf Demo" );
|
||||
Font titleFont = titleLabel.getFont();
|
||||
titleLabel.setFont( titleFont.deriveFont( (float) titleFont.getSize() + UIScale.scale( 6 ) ) );
|
||||
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
|
||||
|
||||
String link = "https://www.formdev.com/flatlaf/";
|
||||
JLabel linkLabel = new JLabel( "<html><a href=\"#\">" + link + "</a></html>" );
|
||||
@@ -216,6 +215,7 @@ class DemoFrame
|
||||
|
||||
menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations );
|
||||
unifiedTitleBarMenuItem.setEnabled( windowDecorations );
|
||||
showTitleBarIconMenuItem.setEnabled( windowDecorations );
|
||||
}
|
||||
|
||||
private void menuBarEmbeddedChanged() {
|
||||
@@ -228,6 +228,16 @@ class DemoFrame
|
||||
FlatLaf.repaintAllFramesAndDialogs();
|
||||
}
|
||||
|
||||
private void showTitleBarIcon() {
|
||||
boolean showIcon = showTitleBarIconMenuItem.isSelected();
|
||||
|
||||
// for main frame (because already created)
|
||||
getRootPane().putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, showIcon );
|
||||
|
||||
// for other not yet created frames/dialogs
|
||||
UIManager.put( "TitlePane.showIcon", showIcon );
|
||||
}
|
||||
|
||||
private void underlineMenuSelection() {
|
||||
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
|
||||
}
|
||||
@@ -467,6 +477,7 @@ class DemoFrame
|
||||
windowDecorationsCheckBoxMenuItem = new JCheckBoxMenuItem();
|
||||
menuBarEmbeddedCheckBoxMenuItem = new JCheckBoxMenuItem();
|
||||
unifiedTitleBarMenuItem = new JCheckBoxMenuItem();
|
||||
showTitleBarIconMenuItem = new JCheckBoxMenuItem();
|
||||
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
|
||||
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
|
||||
animatedLafChangeMenuItem = new JCheckBoxMenuItem();
|
||||
@@ -718,13 +729,11 @@ class DemoFrame
|
||||
|
||||
//---- windowDecorationsCheckBoxMenuItem ----
|
||||
windowDecorationsCheckBoxMenuItem.setText("Window decorations");
|
||||
windowDecorationsCheckBoxMenuItem.setSelected(true);
|
||||
windowDecorationsCheckBoxMenuItem.addActionListener(e -> windowDecorationsChanged());
|
||||
optionsMenu.add(windowDecorationsCheckBoxMenuItem);
|
||||
|
||||
//---- menuBarEmbeddedCheckBoxMenuItem ----
|
||||
menuBarEmbeddedCheckBoxMenuItem.setText("Embedded menu bar");
|
||||
menuBarEmbeddedCheckBoxMenuItem.setSelected(true);
|
||||
menuBarEmbeddedCheckBoxMenuItem.addActionListener(e -> menuBarEmbeddedChanged());
|
||||
optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem);
|
||||
|
||||
@@ -733,6 +742,11 @@ class DemoFrame
|
||||
unifiedTitleBarMenuItem.addActionListener(e -> unifiedTitleBar());
|
||||
optionsMenu.add(unifiedTitleBarMenuItem);
|
||||
|
||||
//---- showTitleBarIconMenuItem ----
|
||||
showTitleBarIconMenuItem.setText("Show window title bar icon");
|
||||
showTitleBarIconMenuItem.addActionListener(e -> showTitleBarIcon());
|
||||
optionsMenu.add(showTitleBarIconMenuItem);
|
||||
|
||||
//---- underlineMenuSelectionMenuItem ----
|
||||
underlineMenuSelectionMenuItem.setText("Use underline menu selection");
|
||||
underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection());
|
||||
@@ -876,6 +890,11 @@ class DemoFrame
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
||||
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
||||
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
|
||||
|
||||
if( JBRCustomDecorations.isSupported() ) {
|
||||
// If the JetBrains Runtime is used, it forces the use of it's own custom
|
||||
// window decoration, which can not disabled.
|
||||
@@ -885,6 +904,7 @@ class DemoFrame
|
||||
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||
unsupported( menuBarEmbeddedCheckBoxMenuItem );
|
||||
unsupported( unifiedTitleBarMenuItem );
|
||||
unsupported( showTitleBarIconMenuItem );
|
||||
}
|
||||
|
||||
if( SystemInfo.isMacOS )
|
||||
@@ -917,6 +937,7 @@ class DemoFrame
|
||||
private JCheckBoxMenuItem windowDecorationsCheckBoxMenuItem;
|
||||
private JCheckBoxMenuItem menuBarEmbeddedCheckBoxMenuItem;
|
||||
private JCheckBoxMenuItem unifiedTitleBarMenuItem;
|
||||
private JCheckBoxMenuItem showTitleBarIconMenuItem;
|
||||
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
|
||||
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
|
||||
private JCheckBoxMenuItem animatedLafChangeMenuItem;
|
||||
|
||||
@@ -354,7 +354,6 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "windowDecorationsCheckBoxMenuItem"
|
||||
"text": "Window decorations"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -363,7 +362,6 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "menuBarEmbeddedCheckBoxMenuItem"
|
||||
"text": "Embedded menu bar"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -377,6 +375,14 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedTitleBar", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "showTitleBarIconMenuItem"
|
||||
"text": "Show window title bar icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "underlineMenuSelectionMenuItem"
|
||||
"text": "Use underline menu selection"
|
||||
|
||||
@@ -18,11 +18,15 @@ package com.formdev.flatlaf.demo;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.ui.FlatDropShadowBorder;
|
||||
import com.formdev.flatlaf.ui.FlatPopupMenuBorder;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -87,6 +91,9 @@ class HintManager
|
||||
|
||||
initComponents();
|
||||
|
||||
setOpaque( false );
|
||||
updateBalloonBorder();
|
||||
|
||||
hintLabel.setText( "<html>" + hint.message + "</html>" );
|
||||
|
||||
// grab all mouse events to avoid that components overlapped
|
||||
@@ -98,8 +105,28 @@ class HintManager
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
setBackground( UIManager.getColor( "HintPanel.backgroundColor" ) );
|
||||
setBorder( new FlatPopupMenuBorder() );
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf )
|
||||
setBackground( UIManager.getColor( "HintPanel.backgroundColor" ) );
|
||||
else {
|
||||
// using nonUIResource() because otherwise Nimbus does not fill the background
|
||||
setBackground( FlatUIUtils.nonUIResource( UIManager.getColor( "info" ) ) );
|
||||
}
|
||||
|
||||
if( hint != null )
|
||||
updateBalloonBorder();
|
||||
}
|
||||
|
||||
private void updateBalloonBorder() {
|
||||
int direction;
|
||||
switch( hint.position ) {
|
||||
case SwingConstants.LEFT: direction = SwingConstants.RIGHT; break;
|
||||
case SwingConstants.TOP: direction = SwingConstants.BOTTOM; break;
|
||||
case SwingConstants.RIGHT: direction = SwingConstants.LEFT; break;
|
||||
case SwingConstants.BOTTOM: direction = SwingConstants.TOP; break;
|
||||
default: throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
setBorder( new BalloonBorder( direction, FlatUIUtils.getUIColor( "PopupMenu.borderColor", Color.gray ) ) );
|
||||
}
|
||||
|
||||
void showHint() {
|
||||
@@ -115,11 +142,6 @@ class HintManager
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
setBorder( new FlatDropShadowBorder(
|
||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||
UIManager.getInsets( "Popup.dropShadowInsets" ),
|
||||
FlatUIUtils.getUIFloat( "Popup.dropShadowOpacity", 0.5f ) ) );
|
||||
|
||||
// use invokeLater because at this time the UI delegates
|
||||
// of child components are not yet updated
|
||||
EventQueue.invokeLater( () -> {
|
||||
@@ -216,4 +238,127 @@ class HintManager
|
||||
private JButton gotItButton;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
//---- class BalloonBorder ------------------------------------------------
|
||||
|
||||
private static class BalloonBorder
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
private static int ARC = 8;
|
||||
private static int ARROW_XY = 16;
|
||||
private static int ARROW_SIZE = 8;
|
||||
private static int SHADOW_SIZE = 6;
|
||||
private static int SHADOW_TOP_SIZE = 3;
|
||||
private static int SHADOW_SIZE2 = SHADOW_SIZE + 2;
|
||||
|
||||
private final int direction;
|
||||
private final Color borderColor;
|
||||
|
||||
private final Border shadowBorder;
|
||||
|
||||
public BalloonBorder( int direction, Color borderColor ) {
|
||||
super( 1 + SHADOW_TOP_SIZE, 1 + SHADOW_SIZE, 1 + SHADOW_SIZE, 1 + SHADOW_SIZE );
|
||||
|
||||
this.direction = direction;
|
||||
this.borderColor = borderColor;
|
||||
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT: left += ARROW_SIZE; break;
|
||||
case SwingConstants.TOP: top += ARROW_SIZE; break;
|
||||
case SwingConstants.RIGHT: right += ARROW_SIZE; break;
|
||||
case SwingConstants.BOTTOM: bottom += ARROW_SIZE; break;
|
||||
}
|
||||
|
||||
shadowBorder = UIManager.getLookAndFeel() instanceof FlatLaf
|
||||
? new FlatDropShadowBorder(
|
||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||
new Insets( SHADOW_SIZE2, SHADOW_SIZE2, SHADOW_SIZE2, SHADOW_SIZE2 ),
|
||||
FlatUIUtils.getUIFloat( "Popup.dropShadowOpacity", 0.5f ) )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.translate( x, y );
|
||||
|
||||
// shadow coordinates
|
||||
int sx = 0;
|
||||
int sy = 0;
|
||||
int sw = width;
|
||||
int sh = height;
|
||||
int arrowSize = UIScale.scale( ARROW_SIZE );
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT: sx += arrowSize; sw -= arrowSize; break;
|
||||
case SwingConstants.TOP: sy += arrowSize; sh -= arrowSize; break;
|
||||
case SwingConstants.RIGHT: sw -= arrowSize; break;
|
||||
case SwingConstants.BOTTOM: sh -= arrowSize; break;
|
||||
}
|
||||
|
||||
// paint shadow
|
||||
if( shadowBorder != null )
|
||||
shadowBorder.paintBorder( c, g2, sx, sy, sw, sh );
|
||||
|
||||
// create balloon shape
|
||||
int bx = UIScale.scale( SHADOW_SIZE );
|
||||
int by = UIScale.scale( SHADOW_TOP_SIZE );
|
||||
int bw = width - UIScale.scale( SHADOW_SIZE + SHADOW_SIZE );
|
||||
int bh = height - UIScale.scale( SHADOW_TOP_SIZE + SHADOW_SIZE );
|
||||
g2.translate( bx, by );
|
||||
Shape shape = createBalloonShape( bw, bh );
|
||||
|
||||
// fill balloon background
|
||||
g2.setColor( c.getBackground() );
|
||||
g2.fill( shape );
|
||||
|
||||
// paint balloon border
|
||||
g2.setColor( borderColor );
|
||||
g2.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
||||
g2.draw( shape );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private Shape createBalloonShape( int width, int height ) {
|
||||
int arc = UIScale.scale( ARC );
|
||||
int xy = UIScale.scale( ARROW_XY );
|
||||
int awh = UIScale.scale( ARROW_SIZE );
|
||||
|
||||
Shape rect;
|
||||
Shape arrow;
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT:
|
||||
rect = new RoundRectangle2D.Float( awh, 0, width - 1 - awh, height - 1, arc, arc );
|
||||
arrow = FlatUIUtils.createPath( awh,xy, 0,xy+awh, awh,xy+awh+awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.TOP:
|
||||
rect = new RoundRectangle2D.Float( 0, awh, width - 1, height - 1 - awh, arc, arc );
|
||||
arrow = FlatUIUtils.createPath( xy,awh, xy+awh,0, xy+awh+awh,awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.RIGHT:
|
||||
rect = new RoundRectangle2D.Float( 0, 0, width - 1 - awh, height - 1, arc, arc );
|
||||
int x = width - 1 - awh;
|
||||
arrow = FlatUIUtils.createPath( x,xy, x+awh,xy+awh, x,xy+awh+awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.BOTTOM:
|
||||
rect = new RoundRectangle2D.Float( 0, 0, width - 1, height - 1 - awh, arc, arc );
|
||||
int y = height - 1 - awh;
|
||||
arrow = FlatUIUtils.createPath( xy,y, xy+awh,y+awh, xy+awh+awh,y );
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
Area area = new Area( rect );
|
||||
area.add( new Area( arrow ) );
|
||||
return area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -44,6 +45,29 @@ class OptionPanePanel
|
||||
"OK",
|
||||
"Cancel",
|
||||
} );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
||||
updateShowTitleBarIcon();
|
||||
|
||||
UIManager.getDefaults().addPropertyChangeListener( e -> {
|
||||
switch( e.getPropertyName() ) {
|
||||
case "TitlePane.showIcon":
|
||||
case "TitlePane.useWindowDecorations":
|
||||
updateShowTitleBarIcon();
|
||||
break;
|
||||
}
|
||||
} );
|
||||
} else
|
||||
showTitleBarIconCheckBox.setEnabled( false );
|
||||
}
|
||||
|
||||
private void updateShowTitleBarIcon() {
|
||||
showTitleBarIconCheckBox.setEnabled( UIManager.getBoolean( "TitlePane.showIcon" ) &&
|
||||
FlatLaf.isUseNativeWindowDecorations() );
|
||||
}
|
||||
|
||||
private void showTitleBarIcon() {
|
||||
UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
@@ -54,6 +78,7 @@ class OptionPanePanel
|
||||
JPanel panel1 = new JPanel();
|
||||
JOptionPane plainOptionPane = new JOptionPane();
|
||||
plainShowDialogLabel = new OptionPanePanel.ShowDialogLinkLabel();
|
||||
showTitleBarIconCheckBox = new JCheckBox();
|
||||
JLabel errorLabel = new JLabel();
|
||||
JPanel panel2 = new JPanel();
|
||||
JOptionPane errorOptionPane = new JOptionPane();
|
||||
@@ -93,7 +118,7 @@ class OptionPanePanel
|
||||
//======== panel9 ========
|
||||
{
|
||||
panel9.setLayout(new MigLayout(
|
||||
"flowy,insets dialog,hidemode 3",
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
@@ -126,7 +151,12 @@ class OptionPanePanel
|
||||
//---- plainShowDialogLabel ----
|
||||
plainShowDialogLabel.setOptionPane(plainOptionPane);
|
||||
plainShowDialogLabel.setTitleLabel(plainLabel);
|
||||
panel9.add(plainShowDialogLabel, "cell 2 0");
|
||||
panel9.add(plainShowDialogLabel, "cell 1 0");
|
||||
|
||||
//---- showTitleBarIconCheckBox ----
|
||||
showTitleBarIconCheckBox.setText("Show window title bar icon");
|
||||
showTitleBarIconCheckBox.addActionListener(e -> showTitleBarIcon());
|
||||
panel9.add(showTitleBarIconCheckBox, "cell 2 0");
|
||||
|
||||
//---- errorLabel ----
|
||||
errorLabel.setText("Error");
|
||||
@@ -148,7 +178,7 @@ class OptionPanePanel
|
||||
//---- errorShowDialogLabel ----
|
||||
errorShowDialogLabel.setTitleLabel(errorLabel);
|
||||
errorShowDialogLabel.setOptionPane(errorOptionPane);
|
||||
panel9.add(errorShowDialogLabel, "cell 2 1");
|
||||
panel9.add(errorShowDialogLabel, "cell 1 1");
|
||||
|
||||
//---- informationLabel ----
|
||||
informationLabel.setText("Information");
|
||||
@@ -170,7 +200,7 @@ class OptionPanePanel
|
||||
//---- informationShowDialogLabel ----
|
||||
informationShowDialogLabel.setOptionPane(informationOptionPane);
|
||||
informationShowDialogLabel.setTitleLabel(informationLabel);
|
||||
panel9.add(informationShowDialogLabel, "cell 2 2");
|
||||
panel9.add(informationShowDialogLabel, "cell 1 2");
|
||||
|
||||
//---- questionLabel ----
|
||||
questionLabel.setText("Question");
|
||||
@@ -214,7 +244,7 @@ class OptionPanePanel
|
||||
//---- warningShowDialogLabel ----
|
||||
warningShowDialogLabel.setOptionPane(warningOptionPane);
|
||||
warningShowDialogLabel.setTitleLabel(warningLabel);
|
||||
panel9.add(warningShowDialogLabel, "cell 2 4");
|
||||
panel9.add(warningShowDialogLabel, "cell 1 4");
|
||||
|
||||
//---- inputLabel ----
|
||||
inputLabel.setText("Input");
|
||||
@@ -236,7 +266,7 @@ class OptionPanePanel
|
||||
//---- inputShowDialogLabel ----
|
||||
inputShowDialogLabel.setOptionPane(inputOptionPane);
|
||||
inputShowDialogLabel.setTitleLabel(inputLabel);
|
||||
panel9.add(inputShowDialogLabel, "cell 2 5");
|
||||
panel9.add(inputShowDialogLabel, "cell 1 5");
|
||||
|
||||
//---- inputIconLabel ----
|
||||
inputIconLabel.setText("Input + icon");
|
||||
@@ -259,7 +289,7 @@ class OptionPanePanel
|
||||
//---- inputIconShowDialogLabel ----
|
||||
inputIconShowDialogLabel.setTitleLabel(inputIconLabel);
|
||||
inputIconShowDialogLabel.setOptionPane(inputIconOptionPane);
|
||||
panel9.add(inputIconShowDialogLabel, "cell 2 6");
|
||||
panel9.add(inputIconShowDialogLabel, "cell 1 6");
|
||||
|
||||
//---- customLabel ----
|
||||
customLabel.setText("Custom");
|
||||
@@ -279,7 +309,7 @@ class OptionPanePanel
|
||||
//---- customShowDialogLabel ----
|
||||
customShowDialogLabel.setOptionPane(customOptionPane);
|
||||
customShowDialogLabel.setTitleLabel(customLabel);
|
||||
panel9.add(customShowDialogLabel, "cell 2 7");
|
||||
panel9.add(customShowDialogLabel, "cell 1 7");
|
||||
}
|
||||
scrollPane1.setViewportView(panel9);
|
||||
}
|
||||
@@ -289,6 +319,7 @@ class OptionPanePanel
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private OptionPanePanel.ShowDialogLinkLabel plainShowDialogLabel;
|
||||
private JCheckBox showTitleBarIconCheckBox;
|
||||
private OptionPanePanel.ShowDialogLinkLabel errorShowDialogLabel;
|
||||
private OptionPanePanel.ShowDialogLinkLabel informationShowDialogLabel;
|
||||
private JOptionPane customOptionPane;
|
||||
@@ -304,6 +335,7 @@ class OptionPanePanel
|
||||
|
||||
ShowDialogLinkLabel() {
|
||||
setText( "<html><a href=\"#\">Show dialog</a></html>" );
|
||||
setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );
|
||||
|
||||
addMouseListener( new MouseAdapter() {
|
||||
@Override
|
||||
|
||||
@@ -12,7 +12,7 @@ new FormModel {
|
||||
name: "scrollPane1"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "flowy,insets dialog,hidemode 3"
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][][fill]"
|
||||
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
|
||||
} ) {
|
||||
@@ -42,6 +42,16 @@ new FormModel {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTitleBarIconCheckBox"
|
||||
"text": "Show window title bar icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
@@ -73,7 +83,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "informationLabel"
|
||||
@@ -103,7 +113,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "questionLabel"
|
||||
@@ -157,7 +167,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "warningOptionPane" )
|
||||
"titleLabel": new FormReference( "warningLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputLabel"
|
||||
@@ -184,7 +194,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "inputOptionPane" )
|
||||
"titleLabel": new FormReference( "inputLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputIconLabel"
|
||||
@@ -212,7 +222,7 @@ new FormModel {
|
||||
"titleLabel": new FormReference( "inputIconLabel" )
|
||||
"optionPane": new FormReference( "inputIconOptionPane" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "customLabel"
|
||||
@@ -240,7 +250,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "customOptionPane" )
|
||||
"titleLabel": new FormReference( "customLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
@@ -248,7 +258,7 @@ new FormModel {
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 840, 900 )
|
||||
"size": new java.awt.Dimension( 955, 900 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +303,11 @@ class TabsPanel
|
||||
putTabbedPanesClientProperty( TABBED_PANE_SCROLL_BUTTONS_PLACEMENT, scrollButtonsPlacement );
|
||||
}
|
||||
|
||||
private void tabTypeChanged() {
|
||||
String tabType = cardTabTypeButton.isSelected() ? TABBED_PANE_TAB_TYPE_CARD : null;
|
||||
putTabbedPanesClientProperty( TABBED_PANE_TAB_TYPE, tabType );
|
||||
}
|
||||
|
||||
private void showTabSeparatorsChanged() {
|
||||
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
|
||||
putTabbedPanesClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
|
||||
@@ -396,11 +401,15 @@ class TabsPanel
|
||||
scrollButtonsPlacementToolBar = new JToolBar();
|
||||
scrollBothButton = new JToggleButton();
|
||||
scrollTrailingButton = new JToggleButton();
|
||||
showTabSeparatorsCheckBox = new JCheckBox();
|
||||
tabsPopupPolicyLabel = new JLabel();
|
||||
tabsPopupPolicyToolBar = new JToolBar();
|
||||
popupAsNeededButton = new JToggleButton();
|
||||
popupNeverButton = new JToggleButton();
|
||||
showTabSeparatorsCheckBox = new JCheckBox();
|
||||
tabTypeLabel = new JLabel();
|
||||
tabTypeToolBar = new JToolBar();
|
||||
underlinedTabTypeButton = new JToggleButton();
|
||||
cardTabTypeButton = new JToggleButton();
|
||||
|
||||
//======== this ========
|
||||
setName("this");
|
||||
@@ -435,7 +444,7 @@ class TabsPanel
|
||||
|
||||
//---- tabPlacementLabel ----
|
||||
tabPlacementLabel.setText("Tab placement");
|
||||
tabPlacementLabel.setFont(tabPlacementLabel.getFont().deriveFont(tabPlacementLabel.getFont().getSize() + 4f));
|
||||
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabPlacementLabel.setName("tabPlacementLabel");
|
||||
panel1.add(tabPlacementLabel, "cell 0 0");
|
||||
|
||||
@@ -448,28 +457,28 @@ class TabsPanel
|
||||
//---- topPlacementButton ----
|
||||
topPlacementButton.setText("top");
|
||||
topPlacementButton.setSelected(true);
|
||||
topPlacementButton.setFont(topPlacementButton.getFont().deriveFont(topPlacementButton.getFont().getSize() - 2f));
|
||||
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
topPlacementButton.setName("topPlacementButton");
|
||||
topPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(topPlacementButton);
|
||||
|
||||
//---- bottomPlacementButton ----
|
||||
bottomPlacementButton.setText("bottom");
|
||||
bottomPlacementButton.setFont(bottomPlacementButton.getFont().deriveFont(bottomPlacementButton.getFont().getSize() - 2f));
|
||||
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
bottomPlacementButton.setName("bottomPlacementButton");
|
||||
bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(bottomPlacementButton);
|
||||
|
||||
//---- leftPlacementButton ----
|
||||
leftPlacementButton.setText("left");
|
||||
leftPlacementButton.setFont(leftPlacementButton.getFont().deriveFont(leftPlacementButton.getFont().getSize() - 2f));
|
||||
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leftPlacementButton.setName("leftPlacementButton");
|
||||
leftPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(leftPlacementButton);
|
||||
|
||||
//---- rightPlacementButton ----
|
||||
rightPlacementButton.setText("right");
|
||||
rightPlacementButton.setFont(rightPlacementButton.getFont().deriveFont(rightPlacementButton.getFont().getSize() - 2f));
|
||||
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
rightPlacementButton.setName("rightPlacementButton");
|
||||
rightPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(rightPlacementButton);
|
||||
@@ -477,14 +486,14 @@ class TabsPanel
|
||||
|
||||
//---- scrollButton ----
|
||||
scrollButton.setText("scroll");
|
||||
scrollButton.setFont(scrollButton.getFont().deriveFont(scrollButton.getFont().getSize() - 2f));
|
||||
scrollButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollButton.setName("scrollButton");
|
||||
scrollButton.addActionListener(e -> scrollChanged());
|
||||
tabPlacementToolBar.add(scrollButton);
|
||||
|
||||
//---- borderButton ----
|
||||
borderButton.setText("border");
|
||||
borderButton.setFont(borderButton.getFont().deriveFont(borderButton.getFont().getSize() - 2f));
|
||||
borderButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
borderButton.setName("borderButton");
|
||||
borderButton.addActionListener(e -> borderChanged());
|
||||
tabPlacementToolBar.add(borderButton);
|
||||
@@ -499,7 +508,7 @@ class TabsPanel
|
||||
|
||||
//---- tabLayoutLabel ----
|
||||
tabLayoutLabel.setText("Tab layout");
|
||||
tabLayoutLabel.setFont(tabLayoutLabel.getFont().deriveFont(tabLayoutLabel.getFont().getSize() + 4f));
|
||||
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabLayoutLabel.setName("tabLayoutLabel");
|
||||
panel1.add(tabLayoutLabel, "cell 0 2");
|
||||
|
||||
@@ -511,15 +520,15 @@ class TabsPanel
|
||||
|
||||
//---- scrollTabLayoutButton ----
|
||||
scrollTabLayoutButton.setText("scroll");
|
||||
scrollTabLayoutButton.setFont(scrollTabLayoutButton.getFont().deriveFont(scrollTabLayoutButton.getFont().getSize() - 2f));
|
||||
scrollTabLayoutButton.setSelected(true);
|
||||
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTabLayoutButton.setName("scrollTabLayoutButton");
|
||||
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(scrollTabLayoutButton);
|
||||
|
||||
//---- wrapTabLayoutButton ----
|
||||
wrapTabLayoutButton.setText("wrap");
|
||||
wrapTabLayoutButton.setFont(wrapTabLayoutButton.getFont().deriveFont(wrapTabLayoutButton.getFont().getSize() - 2f));
|
||||
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapTabLayoutButton.setName("wrapTabLayoutButton");
|
||||
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(wrapTabLayoutButton);
|
||||
@@ -529,14 +538,14 @@ class TabsPanel
|
||||
//---- scrollLayoutNoteLabel ----
|
||||
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
|
||||
scrollLayoutNoteLabel.setEnabled(false);
|
||||
scrollLayoutNoteLabel.setFont(scrollLayoutNoteLabel.getFont().deriveFont(scrollLayoutNoteLabel.getFont().getSize() - 2f));
|
||||
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollLayoutNoteLabel.setName("scrollLayoutNoteLabel");
|
||||
panel1.add(scrollLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
//---- wrapLayoutNoteLabel ----
|
||||
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
|
||||
wrapLayoutNoteLabel.setEnabled(false);
|
||||
wrapLayoutNoteLabel.setFont(wrapLayoutNoteLabel.getFont().deriveFont(wrapLayoutNoteLabel.getFont().getSize() - 2f));
|
||||
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapLayoutNoteLabel.setName("wrapLayoutNoteLabel");
|
||||
panel1.add(wrapLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
@@ -554,7 +563,7 @@ class TabsPanel
|
||||
|
||||
//---- closableTabsLabel ----
|
||||
closableTabsLabel.setText("Closable tabs");
|
||||
closableTabsLabel.setFont(closableTabsLabel.getFont().deriveFont(closableTabsLabel.getFont().getSize() + 4f));
|
||||
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
closableTabsLabel.setName("closableTabsLabel");
|
||||
panel1.add(closableTabsLabel, "cell 0 5");
|
||||
|
||||
@@ -566,22 +575,22 @@ class TabsPanel
|
||||
|
||||
//---- squareCloseButton ----
|
||||
squareCloseButton.setText("square");
|
||||
squareCloseButton.setFont(squareCloseButton.getFont().deriveFont(squareCloseButton.getFont().getSize() - 2f));
|
||||
squareCloseButton.setSelected(true);
|
||||
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
squareCloseButton.setName("squareCloseButton");
|
||||
squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(squareCloseButton);
|
||||
|
||||
//---- circleCloseButton ----
|
||||
circleCloseButton.setText("circle");
|
||||
circleCloseButton.setFont(circleCloseButton.getFont().deriveFont(circleCloseButton.getFont().getSize() - 2f));
|
||||
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
circleCloseButton.setName("circleCloseButton");
|
||||
circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(circleCloseButton);
|
||||
|
||||
//---- redCrossCloseButton ----
|
||||
redCrossCloseButton.setText("red cross");
|
||||
redCrossCloseButton.setFont(redCrossCloseButton.getFont().deriveFont(redCrossCloseButton.getFont().getSize() - 2f));
|
||||
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
redCrossCloseButton.setName("redCrossCloseButton");
|
||||
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(redCrossCloseButton);
|
||||
@@ -596,7 +605,7 @@ class TabsPanel
|
||||
|
||||
//---- tabAreaComponentsLabel ----
|
||||
tabAreaComponentsLabel.setText("Custom tab area components");
|
||||
tabAreaComponentsLabel.setFont(tabAreaComponentsLabel.getFont().deriveFont(tabAreaComponentsLabel.getFont().getSize() + 4f));
|
||||
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaComponentsLabel.setName("tabAreaComponentsLabel");
|
||||
panel1.add(tabAreaComponentsLabel, "cell 0 7");
|
||||
|
||||
@@ -608,16 +617,16 @@ class TabsPanel
|
||||
|
||||
//---- leadingComponentButton ----
|
||||
leadingComponentButton.setText("leading");
|
||||
leadingComponentButton.setFont(leadingComponentButton.getFont().deriveFont(leadingComponentButton.getFont().getSize() - 2f));
|
||||
leadingComponentButton.setSelected(true);
|
||||
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leadingComponentButton.setName("leadingComponentButton");
|
||||
leadingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(leadingComponentButton);
|
||||
|
||||
//---- trailingComponentButton ----
|
||||
trailingComponentButton.setText("trailing");
|
||||
trailingComponentButton.setFont(trailingComponentButton.getFont().deriveFont(trailingComponentButton.getFont().getSize() - 2f));
|
||||
trailingComponentButton.setSelected(true);
|
||||
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
trailingComponentButton.setName("trailingComponentButton");
|
||||
trailingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(trailingComponentButton);
|
||||
@@ -655,14 +664,14 @@ class TabsPanel
|
||||
|
||||
//---- tabIconPlacementLabel ----
|
||||
tabIconPlacementLabel.setText("Tab icon placement");
|
||||
tabIconPlacementLabel.setFont(tabIconPlacementLabel.getFont().deriveFont(tabIconPlacementLabel.getFont().getSize() + 4f));
|
||||
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabIconPlacementLabel.setName("tabIconPlacementLabel");
|
||||
panel2.add(tabIconPlacementLabel, "cell 0 0");
|
||||
|
||||
//---- tabIconPlacementNodeLabel ----
|
||||
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
|
||||
tabIconPlacementNodeLabel.setEnabled(false);
|
||||
tabIconPlacementNodeLabel.setFont(tabIconPlacementNodeLabel.getFont().deriveFont(tabIconPlacementNodeLabel.getFont().getSize() - 2f));
|
||||
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabIconPlacementNodeLabel.setName("tabIconPlacementNodeLabel");
|
||||
panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
|
||||
|
||||
@@ -692,14 +701,14 @@ class TabsPanel
|
||||
|
||||
//---- tabAreaAlignmentLabel ----
|
||||
tabAreaAlignmentLabel.setText("Tab area alignment");
|
||||
tabAreaAlignmentLabel.setFont(tabAreaAlignmentLabel.getFont().deriveFont(tabAreaAlignmentLabel.getFont().getSize() + 4f));
|
||||
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaAlignmentLabel.setName("tabAreaAlignmentLabel");
|
||||
panel2.add(tabAreaAlignmentLabel, "cell 0 6");
|
||||
|
||||
//---- tabAreaAlignmentNoteLabel ----
|
||||
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
|
||||
tabAreaAlignmentNoteLabel.setEnabled(false);
|
||||
tabAreaAlignmentNoteLabel.setFont(tabAreaAlignmentNoteLabel.getFont().deriveFont(tabAreaAlignmentNoteLabel.getFont().getSize() - 2f));
|
||||
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAreaAlignmentNoteLabel.setName("tabAreaAlignmentNoteLabel");
|
||||
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
|
||||
|
||||
@@ -750,14 +759,14 @@ class TabsPanel
|
||||
|
||||
//---- tabWidthModeLabel ----
|
||||
tabWidthModeLabel.setText("Tab width mode");
|
||||
tabWidthModeLabel.setFont(tabWidthModeLabel.getFont().deriveFont(tabWidthModeLabel.getFont().getSize() + 4f));
|
||||
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabWidthModeLabel.setName("tabWidthModeLabel");
|
||||
panel3.add(tabWidthModeLabel, "cell 0 0");
|
||||
|
||||
//---- tabWidthModeNoteLabel ----
|
||||
tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
|
||||
tabWidthModeNoteLabel.setFont(tabWidthModeNoteLabel.getFont().deriveFont(tabWidthModeNoteLabel.getFont().getSize() - 2f));
|
||||
tabWidthModeNoteLabel.setEnabled(false);
|
||||
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabWidthModeNoteLabel.setName("tabWidthModeNoteLabel");
|
||||
panel3.add(tabWidthModeNoteLabel, "cell 0 1");
|
||||
|
||||
@@ -781,7 +790,7 @@ class TabsPanel
|
||||
|
||||
//---- minMaxTabWidthLabel ----
|
||||
minMaxTabWidthLabel.setText("Minimum/maximum tab width");
|
||||
minMaxTabWidthLabel.setFont(minMaxTabWidthLabel.getFont().deriveFont(minMaxTabWidthLabel.getFont().getSize() + 4f));
|
||||
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
minMaxTabWidthLabel.setName("minMaxTabWidthLabel");
|
||||
panel3.add(minMaxTabWidthLabel, "cell 0 5");
|
||||
|
||||
@@ -799,7 +808,7 @@ class TabsPanel
|
||||
|
||||
//---- tabAlignmentLabel ----
|
||||
tabAlignmentLabel.setText("Tab title alignment");
|
||||
tabAlignmentLabel.setFont(tabAlignmentLabel.getFont().deriveFont(tabAlignmentLabel.getFont().getSize() + 4f));
|
||||
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAlignmentLabel.setName("tabAlignmentLabel");
|
||||
panel3.add(tabAlignmentLabel, "cell 0 8");
|
||||
|
||||
@@ -820,14 +829,14 @@ class TabsPanel
|
||||
//---- tabAlignmentNoteLabel ----
|
||||
tabAlignmentNoteLabel.setText("(leading/center/trailing)");
|
||||
tabAlignmentNoteLabel.setEnabled(false);
|
||||
tabAlignmentNoteLabel.setFont(tabAlignmentNoteLabel.getFont().deriveFont(tabAlignmentNoteLabel.getFont().getSize() - 2f));
|
||||
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel.setName("tabAlignmentNoteLabel");
|
||||
panel5.add(tabAlignmentNoteLabel, "cell 0 0");
|
||||
|
||||
//---- tabAlignmentNoteLabel2 ----
|
||||
tabAlignmentNoteLabel2.setText("(trailing)");
|
||||
tabAlignmentNoteLabel2.setEnabled(false);
|
||||
tabAlignmentNoteLabel2.setFont(tabAlignmentNoteLabel2.getFont().deriveFont(tabAlignmentNoteLabel2.getFont().getSize() - 2f));
|
||||
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel2.setName("tabAlignmentNoteLabel2");
|
||||
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
|
||||
|
||||
@@ -873,7 +882,8 @@ class TabsPanel
|
||||
"[]" +
|
||||
"[fill]para" +
|
||||
"[fill]" +
|
||||
"[fill]para",
|
||||
"[fill]para" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[center]"));
|
||||
@@ -891,22 +901,22 @@ class TabsPanel
|
||||
|
||||
//---- scrollAsNeededSingleButton ----
|
||||
scrollAsNeededSingleButton.setText("asNeededSingle");
|
||||
scrollAsNeededSingleButton.setFont(scrollAsNeededSingleButton.getFont().deriveFont(scrollAsNeededSingleButton.getFont().getSize() - 2f));
|
||||
scrollAsNeededSingleButton.setSelected(true);
|
||||
scrollAsNeededSingleButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededSingleButton.setName("scrollAsNeededSingleButton");
|
||||
scrollAsNeededSingleButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededSingleButton);
|
||||
|
||||
//---- scrollAsNeededButton ----
|
||||
scrollAsNeededButton.setText("asNeeded");
|
||||
scrollAsNeededButton.setFont(scrollAsNeededButton.getFont().deriveFont(scrollAsNeededButton.getFont().getSize() - 2f));
|
||||
scrollAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededButton.setName("scrollAsNeededButton");
|
||||
scrollAsNeededButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededButton);
|
||||
|
||||
//---- scrollNeverButton ----
|
||||
scrollNeverButton.setText("never");
|
||||
scrollNeverButton.setFont(scrollNeverButton.getFont().deriveFont(scrollNeverButton.getFont().getSize() - 2f));
|
||||
scrollNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollNeverButton.setName("scrollNeverButton");
|
||||
scrollNeverButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollNeverButton);
|
||||
@@ -926,21 +936,27 @@ class TabsPanel
|
||||
|
||||
//---- scrollBothButton ----
|
||||
scrollBothButton.setText("both");
|
||||
scrollBothButton.setFont(scrollBothButton.getFont().deriveFont(scrollBothButton.getFont().getSize() - 2f));
|
||||
scrollBothButton.setSelected(true);
|
||||
scrollBothButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollBothButton.setName("scrollBothButton");
|
||||
scrollBothButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollBothButton);
|
||||
|
||||
//---- scrollTrailingButton ----
|
||||
scrollTrailingButton.setText("trailing");
|
||||
scrollTrailingButton.setFont(scrollTrailingButton.getFont().deriveFont(scrollTrailingButton.getFont().getSize() - 2f));
|
||||
scrollTrailingButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTrailingButton.setName("scrollTrailingButton");
|
||||
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollTrailingButton);
|
||||
}
|
||||
panel4.add(scrollButtonsPlacementToolBar, "cell 3 0");
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.setName("showTabSeparatorsCheckBox");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
panel4.add(showTabSeparatorsCheckBox, "cell 4 0");
|
||||
|
||||
//---- tabsPopupPolicyLabel ----
|
||||
tabsPopupPolicyLabel.setText("Tabs popup policy:");
|
||||
tabsPopupPolicyLabel.setName("tabsPopupPolicyLabel");
|
||||
@@ -954,26 +970,47 @@ class TabsPanel
|
||||
|
||||
//---- popupAsNeededButton ----
|
||||
popupAsNeededButton.setText("asNeeded");
|
||||
popupAsNeededButton.setFont(popupAsNeededButton.getFont().deriveFont(popupAsNeededButton.getFont().getSize() - 2f));
|
||||
popupAsNeededButton.setSelected(true);
|
||||
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupAsNeededButton.setName("popupAsNeededButton");
|
||||
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupAsNeededButton);
|
||||
|
||||
//---- popupNeverButton ----
|
||||
popupNeverButton.setText("never");
|
||||
popupNeverButton.setFont(popupNeverButton.getFont().deriveFont(popupNeverButton.getFont().getSize() - 2f));
|
||||
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupNeverButton.setName("popupNeverButton");
|
||||
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupNeverButton);
|
||||
}
|
||||
panel4.add(tabsPopupPolicyToolBar, "cell 1 1");
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.setName("showTabSeparatorsCheckBox");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
panel4.add(showTabSeparatorsCheckBox, "cell 2 1 2 1");
|
||||
//---- tabTypeLabel ----
|
||||
tabTypeLabel.setText("Tab type:");
|
||||
tabTypeLabel.setName("tabTypeLabel");
|
||||
panel4.add(tabTypeLabel, "cell 2 1");
|
||||
|
||||
//======== tabTypeToolBar ========
|
||||
{
|
||||
tabTypeToolBar.setFloatable(false);
|
||||
tabTypeToolBar.setName("tabTypeToolBar");
|
||||
|
||||
//---- underlinedTabTypeButton ----
|
||||
underlinedTabTypeButton.setText("underlined");
|
||||
underlinedTabTypeButton.setSelected(true);
|
||||
underlinedTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
underlinedTabTypeButton.setName("underlinedTabTypeButton");
|
||||
underlinedTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(underlinedTabTypeButton);
|
||||
|
||||
//---- cardTabTypeButton ----
|
||||
cardTabTypeButton.setText("card");
|
||||
cardTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
cardTabTypeButton.setName("cardTabTypeButton");
|
||||
cardTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(cardTabTypeButton);
|
||||
}
|
||||
panel4.add(tabTypeToolBar, "cell 3 1");
|
||||
}
|
||||
add(panel4, "cell 0 2 3 1");
|
||||
|
||||
@@ -1010,6 +1047,11 @@ class TabsPanel
|
||||
ButtonGroup tabsPopupPolicyButtonGroup = new ButtonGroup();
|
||||
tabsPopupPolicyButtonGroup.add(popupAsNeededButton);
|
||||
tabsPopupPolicyButtonGroup.add(popupNeverButton);
|
||||
|
||||
//---- tabTypeButtonGroup ----
|
||||
ButtonGroup tabTypeButtonGroup = new ButtonGroup();
|
||||
tabTypeButtonGroup.add(underlinedTabTypeButton);
|
||||
tabTypeButtonGroup.add(cardTabTypeButton);
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
@@ -1089,10 +1131,14 @@ class TabsPanel
|
||||
private JToolBar scrollButtonsPlacementToolBar;
|
||||
private JToggleButton scrollBothButton;
|
||||
private JToggleButton scrollTrailingButton;
|
||||
private JCheckBox showTabSeparatorsCheckBox;
|
||||
private JLabel tabsPopupPolicyLabel;
|
||||
private JToolBar tabsPopupPolicyToolBar;
|
||||
private JToggleButton popupAsNeededButton;
|
||||
private JToggleButton popupNeverButton;
|
||||
private JCheckBox showTabSeparatorsCheckBox;
|
||||
private JLabel tabTypeLabel;
|
||||
private JToolBar tabTypeToolBar;
|
||||
private JToggleButton underlinedTabTypeButton;
|
||||
private JToggleButton cardTabTypeButton;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -22,7 +22,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabPlacementLabel"
|
||||
"text": "Tab placement"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -38,28 +38,28 @@ new FormModel {
|
||||
"text": "top"
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": &SwingDerivedFont0 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "bottomPlacementButton"
|
||||
"text": "bottom"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "leftPlacementButton"
|
||||
"text": "left"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "rightPlacementButton"
|
||||
"text": "right"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
@@ -68,13 +68,13 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollButton"
|
||||
"text": "scroll"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "borderButton"
|
||||
"text": "border"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -88,7 +88,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabLayoutLabel"
|
||||
"text": "Tab layout"
|
||||
"font": &SwingDerivedFont1 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -103,15 +103,15 @@ new FormModel {
|
||||
name: "scrollTabLayoutButton"
|
||||
"text": "scroll"
|
||||
"$buttonGroup": new FormReference( "tabLayoutButtonGroup" )
|
||||
"font": &SwingDerivedFont2 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "wrapTabLayoutButton"
|
||||
"text": "wrap"
|
||||
"$buttonGroup": new FormReference( "tabLayoutButtonGroup" )
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -121,7 +121,7 @@ new FormModel {
|
||||
name: "scrollLayoutNoteLabel"
|
||||
"text": "(use mouse wheel to scroll; arrow button shows hidden tabs)"
|
||||
"enabled": false
|
||||
"font": &SwingDerivedFont3 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
@@ -129,7 +129,7 @@ new FormModel {
|
||||
name: "wrapLayoutNoteLabel"
|
||||
"text": "(probably better to use scroll layout?)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont3
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
@@ -146,7 +146,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "closableTabsLabel"
|
||||
"text": "Closable tabs"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -160,23 +160,23 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "squareCloseButton"
|
||||
"text": "square"
|
||||
"font": &SwingDerivedFont4 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "circleCloseButton"
|
||||
"text": "circle"
|
||||
"font": #SwingDerivedFont4
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "redCrossCloseButton"
|
||||
"text": "red cross"
|
||||
"font": #SwingDerivedFont4
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -190,7 +190,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAreaComponentsLabel"
|
||||
"text": "Custom tab area components"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -204,15 +204,15 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "leadingComponentButton"
|
||||
"text": "leading"
|
||||
"font": &SwingDerivedFont5 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customComponentsChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "trailingComponentButton"
|
||||
"text": "trailing"
|
||||
"font": #SwingDerivedFont5
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customComponentsChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -238,7 +238,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabIconPlacementLabel"
|
||||
"text": "Tab icon placement"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -249,7 +249,7 @@ new FormModel {
|
||||
name: "tabIconPlacementNodeLabel"
|
||||
"text": "(top/bottom/leading/trailing)"
|
||||
"enabled": false
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -279,7 +279,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAreaAlignmentLabel"
|
||||
"text": "Tab area alignment"
|
||||
"font": &SwingDerivedFont6 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -290,7 +290,7 @@ new FormModel {
|
||||
name: "tabAreaAlignmentNoteLabel"
|
||||
"text": "(leading/center/trailing/fill)"
|
||||
"enabled": false
|
||||
"font": &SwingDerivedFont7 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -332,7 +332,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabWidthModeLabel"
|
||||
"text": "Tab width mode"
|
||||
"font": #SwingDerivedFont6
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -342,8 +342,8 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabWidthModeNoteLabel"
|
||||
"text": "(preferred/equal/compact)"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"enabled": false
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -368,7 +368,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "minMaxTabWidthLabel"
|
||||
"text": "Minimum/maximum tab width"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -388,7 +388,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAlignmentLabel"
|
||||
"text": "Tab title alignment"
|
||||
"font": #SwingDerivedFont6
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -405,7 +405,7 @@ new FormModel {
|
||||
name: "tabAlignmentNoteLabel"
|
||||
"text": "(leading/center/trailing)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont7
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -416,7 +416,7 @@ new FormModel {
|
||||
name: "tabAlignmentNoteLabel2"
|
||||
"text": "(trailing)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont7
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -457,7 +457,7 @@ new FormModel {
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3"
|
||||
"$columnConstraints": "[][fill]para[fill][fill]para"
|
||||
"$columnConstraints": "[][fill]para[fill][fill]para[fill]"
|
||||
"$rowConstraints": "[][center]"
|
||||
} ) {
|
||||
name: "panel4"
|
||||
@@ -477,23 +477,23 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollAsNeededSingleButton"
|
||||
"text": "asNeededSingle"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollAsNeededButton"
|
||||
"text": "asNeeded"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollNeverButton"
|
||||
"text": "never"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -512,21 +512,31 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollBothButton"
|
||||
"text": "both"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPlacementButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollTrailingButton"
|
||||
"text": "trailing"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPlacementButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPlacementChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTabSeparatorsCheckBox"
|
||||
"text": "Show tab separators"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabsPopupPolicyLabel"
|
||||
"text": "Tabs popup policy:"
|
||||
@@ -540,37 +550,54 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "popupAsNeededButton"
|
||||
"text": "asNeeded"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabsPopupPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsPopupPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "popupNeverButton"
|
||||
"text": "never"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "tabsPopupPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsPopupPolicyChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTabSeparatorsCheckBox"
|
||||
"text": "Show tab separators"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabTypeLabel"
|
||||
"text": "Tab type:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1 2 1"
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
|
||||
name: "tabTypeToolBar"
|
||||
"floatable": false
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "underlinedTabTypeButton"
|
||||
"text": "underlined"
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabTypeButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabTypeChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "cardTabTypeButton"
|
||||
"text": "card"
|
||||
"$buttonGroup": new FormReference( "tabTypeButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabTypeChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 1075, 895 )
|
||||
"size": new java.awt.Dimension( 1145, 895 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "tabPlacementButtonGroup"
|
||||
@@ -602,5 +629,10 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 200, 1020 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "tabTypeButtonGroup"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 1072 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,9 +474,9 @@ public class FlatInspector
|
||||
if( c instanceof JComponent )
|
||||
appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) );
|
||||
|
||||
appendRow( buf, "Background", toString( c.getBackground() ) );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) );
|
||||
appendRow( buf, "Font", toString( c.getFont() ) );
|
||||
appendRow( buf, "Background", toString( c.getBackground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Font", toString( c.getFont() ) + (c.isFontSet() ? "" : " NOT SET") );
|
||||
|
||||
if( c instanceof JComponent ) {
|
||||
try {
|
||||
|
||||
@@ -27,6 +27,10 @@ import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RGBImageFilter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
@@ -44,6 +48,7 @@ import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.SoftCache;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import com.kitfox.svg.SVGDiagram;
|
||||
import com.kitfox.svg.SVGException;
|
||||
@@ -58,8 +63,12 @@ public class FlatSVGIcon
|
||||
extends ImageIcon
|
||||
implements DisabledIconProvider
|
||||
{
|
||||
// cache that uses soft references for values, which allows freeing SVG diagrams if no longer used
|
||||
private static final SoftCache<URI, SVGDiagram> svgCache = new SoftCache<>();
|
||||
|
||||
// use own SVG universe so that it can not be cleared from anywhere
|
||||
private static final SVGUniverse svgUniverse = new SVGUniverse();
|
||||
private static int streamNumber;
|
||||
|
||||
private final String name;
|
||||
private final int width;
|
||||
@@ -67,23 +76,30 @@ public class FlatSVGIcon
|
||||
private final float scale;
|
||||
private final boolean disabled;
|
||||
private final ClassLoader classLoader;
|
||||
private final URI uri;
|
||||
|
||||
private ColorFilter colorFilter;
|
||||
|
||||
private SVGDiagram diagram;
|
||||
private boolean dark;
|
||||
private boolean loadFailed;
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given resource name.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name ) {
|
||||
this( name, -1, -1, 1, false, null );
|
||||
this( name, -1, -1, 1, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,27 +108,37 @@ public class FlatSVGIcon
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, ClassLoader classLoader ) {
|
||||
this( name, -1, -1, 1, false, classLoader );
|
||||
this( name, -1, -1, 1, false, classLoader, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given resource name with the given width and height.
|
||||
* <p>
|
||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param width the width of the icon
|
||||
* @param height the height of the icon
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, int width, int height ) {
|
||||
this( name, width, height, 1, false, null );
|
||||
this( name, width, height, 1, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,15 +146,20 @@ public class FlatSVGIcon
|
||||
* The SVG file is loaded from the given class loader.
|
||||
* <p>
|
||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param width the width of the icon
|
||||
* @param height the height of the icon
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, int width, int height, ClassLoader classLoader ) {
|
||||
this( name, width, height, 1, false, classLoader );
|
||||
this( name, width, height, 1, false, classLoader, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,13 +168,18 @@ public class FlatSVGIcon
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as base icon size, which is multiplied
|
||||
* by the given scale factor.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param scale the amount by which the icon size is scaled
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, float scale ) {
|
||||
this( name, -1, -1, scale, false, null );
|
||||
this( name, -1, -1, scale, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,23 +189,107 @@ public class FlatSVGIcon
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as base icon size, which is multiplied
|
||||
* by the given scale factor.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param scale the amount by which the icon size is scaled
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, float scale, ClassLoader classLoader ) {
|
||||
this( name, -1, -1, scale, false, classLoader );
|
||||
this( name, -1, -1, scale, false, classLoader, null );
|
||||
}
|
||||
|
||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader ) {
|
||||
/**
|
||||
* Creates an SVG icon from the given URL.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the icon
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code new FlatSVGIcon( getClass().getResource( "/com/myapp/myicon.svg" ) )}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param url the URL of the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( URL url ) {
|
||||
this( null, -1, -1, 1, false, null, url2uri( url ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given URI.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param uri the URI of the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( URI uri ) {
|
||||
this( null, -1, -1, 1, false, null, uri );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given file.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param file the SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( File file ) {
|
||||
this( null, -1, -1, 1, false, null, file.toURI() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given input stream.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* The input stream is loaded, parsed and closed immediately.
|
||||
*
|
||||
* @param in the input stream for reading a SVG resource
|
||||
* @throws IOException if an I/O exception occurs
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( InputStream in ) throws IOException {
|
||||
this( null, -1, -1, 1, false, null, loadFromStream( in ) );
|
||||
|
||||
// since the input stream is already loaded and parsed,
|
||||
// get diagram here and remove it from cache
|
||||
update();
|
||||
svgCache.remove( uri );
|
||||
}
|
||||
|
||||
private static URI loadFromStream( InputStream in ) throws IOException {
|
||||
try( InputStream in2 = in ) {
|
||||
return svgUniverse.loadSVG( in2, "/flatlaf-stream-" + (streamNumber++) );
|
||||
}
|
||||
}
|
||||
|
||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader, URI uri ) {
|
||||
this.name = name;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.scale = scale;
|
||||
this.disabled = disabled;
|
||||
this.classLoader = classLoader;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +368,7 @@ public class FlatSVGIcon
|
||||
if( width == this.width && height == this.height )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -267,7 +387,7 @@ public class FlatSVGIcon
|
||||
if( scale == this.scale )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -286,7 +406,7 @@ public class FlatSVGIcon
|
||||
if( disabled )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -324,20 +444,56 @@ public class FlatSVGIcon
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if( loadFailed )
|
||||
return;
|
||||
|
||||
if( dark == isDarkLaf() && diagram != null )
|
||||
return;
|
||||
|
||||
dark = isDarkLaf();
|
||||
URL url = getIconURL( name, dark );
|
||||
if( url == null & dark )
|
||||
url = getIconURL( name, false );
|
||||
|
||||
// load/get image
|
||||
try {
|
||||
diagram = svgUniverse.getDiagram( url.toURI() );
|
||||
} catch( URISyntaxException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load SVG icon '" + url + "'.", ex );
|
||||
// SVGs already loaded via url or input stream can not have light/dark variants
|
||||
if( uri != null && diagram != null )
|
||||
return;
|
||||
|
||||
URI uri = this.uri;
|
||||
if( uri == null ) {
|
||||
URL url = getIconURL( name, dark );
|
||||
if( url == null & dark )
|
||||
url = getIconURL( name, false );
|
||||
|
||||
if( url == null ) {
|
||||
loadFailed = true;
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
||||
return;
|
||||
}
|
||||
|
||||
uri = url2uri( url );
|
||||
}
|
||||
|
||||
diagram = loadSVG( uri );
|
||||
loadFailed = (diagram == null);
|
||||
}
|
||||
|
||||
static SVGDiagram loadSVG( URI uri ) {
|
||||
// get from our cache
|
||||
SVGDiagram diagram = svgCache.get( uri );
|
||||
if( diagram != null )
|
||||
return diagram;
|
||||
|
||||
// load/get SVG diagram
|
||||
diagram = svgUniverse.getDiagram( uri );
|
||||
|
||||
if( diagram == null ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: failed to load '" + uri + "'", null );
|
||||
return null;
|
||||
}
|
||||
|
||||
// add to our (soft) cache and remove from SVGUniverse (hard) cache
|
||||
svgCache.put( uri, diagram );
|
||||
svgUniverse.removeDocument( uri );
|
||||
|
||||
return diagram;
|
||||
}
|
||||
|
||||
private URL getIconURL( String name, boolean dark ) {
|
||||
@@ -487,6 +643,14 @@ public class FlatSVGIcon
|
||||
return MultiResolutionImageSupport.create( 0, dimensions, producer );
|
||||
}
|
||||
|
||||
static URI url2uri( URL url ) {
|
||||
try {
|
||||
return url.toURI();
|
||||
} catch( URISyntaxException ex ) {
|
||||
throw new IllegalArgumentException( ex );
|
||||
}
|
||||
}
|
||||
|
||||
private static Boolean darkLaf;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -29,7 +28,6 @@ import java.util.List;
|
||||
import javax.swing.JWindow;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.kitfox.svg.SVGCache;
|
||||
import com.kitfox.svg.SVGDiagram;
|
||||
import com.kitfox.svg.SVGException;
|
||||
|
||||
@@ -50,6 +48,9 @@ public class FlatSVGUtils
|
||||
* for requested sizes from SVG.
|
||||
* This has the advantage that only images for used sizes are created.
|
||||
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #createWindowIconImages(URL)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
||||
@@ -57,7 +58,32 @@ public class FlatSVGUtils
|
||||
* @see JWindow#setIconImages(List)
|
||||
*/
|
||||
public static List<Image> createWindowIconImages( String svgName ) {
|
||||
SVGDiagram diagram = loadSVG( svgName );
|
||||
return createWindowIconImages( getResource( svgName ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates from the given SVG a list of icon images with different sizes that
|
||||
* can be used for windows headers. The SVG should have a size of 16x16,
|
||||
* otherwise it is scaled.
|
||||
* <p>
|
||||
* If running on Windows in Java 9 or later and multi-resolution image support is available,
|
||||
* then a single multi-resolution image is returned that creates images on demand
|
||||
* for requested sizes from SVG.
|
||||
* This has the advantage that only images for used sizes are created.
|
||||
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code createWindowIconImages( getClass().getResource( "/com/myapp/myicon.svg" ) )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @see JWindow#setIconImages(List)
|
||||
* @since 2
|
||||
*/
|
||||
public static List<Image> createWindowIconImages( URL svgUrl ) {
|
||||
SVGDiagram diagram = loadSVG( svgUrl );
|
||||
|
||||
if( SystemInfo.isWindows && MultiResolutionImageSupport.isAvailable() ) {
|
||||
// use a multi-resolution image that creates images on demand for requested sizes
|
||||
@@ -93,6 +119,9 @@ public class FlatSVGUtils
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #svg2image(URL, int, int)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @param width the width of the image
|
||||
@@ -101,11 +130,32 @@ public class FlatSVGUtils
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
*/
|
||||
public static BufferedImage svg2image( String svgName, int width, int height ) {
|
||||
return svg2image( loadSVG( svgName ), width, height );
|
||||
return svg2image( getResource( svgName ), width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code svg2image( getClass().getResource( "/com/myapp/myicon.svg" ), 24, 24 )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @param width the width of the image
|
||||
* @param height the height of the image
|
||||
* @return the image
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public static BufferedImage svg2image( URL svgUrl, int width, int height ) {
|
||||
return svg2image( loadSVG( svgUrl ), width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #svg2image(URL, float)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @param scaleFactor the amount by which the SVG size is scaled
|
||||
@@ -113,7 +163,24 @@ public class FlatSVGUtils
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
*/
|
||||
public static BufferedImage svg2image( String svgName, float scaleFactor ) {
|
||||
SVGDiagram diagram = loadSVG( svgName );
|
||||
return svg2image( getResource( svgName ), scaleFactor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code svg2image( getClass().getResource( "/com/myapp/myicon.svg" ), 1.5f )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @param scaleFactor the amount by which the SVG size is scaled
|
||||
* @return the image
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public static BufferedImage svg2image( URL svgUrl, float scaleFactor ) {
|
||||
SVGDiagram diagram = loadSVG( svgUrl );
|
||||
int width = (int) (diagram.getWidth() * scaleFactor);
|
||||
int height = (int) (diagram.getHeight() * scaleFactor);
|
||||
return svg2image( diagram, width, height );
|
||||
@@ -155,19 +222,11 @@ public class FlatSVGUtils
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a SVG file.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @return the SVG diagram
|
||||
* @throws RuntimeException if failed to load SVG file
|
||||
*/
|
||||
private static SVGDiagram loadSVG( String svgName ) {
|
||||
try {
|
||||
URL url = FlatSVGUtils.class.getResource( svgName );
|
||||
return SVGCache.getSVGUniverse().getDiagram( url.toURI() );
|
||||
} catch( URISyntaxException ex ) {
|
||||
throw new RuntimeException( ex );
|
||||
}
|
||||
private static URL getResource( String svgName ) {
|
||||
return FlatSVGUtils.class.getResource( svgName );
|
||||
}
|
||||
|
||||
private static SVGDiagram loadSVG( URL url ) {
|
||||
return FlatSVGIcon.loadSVG( FlatSVGIcon.url2uri( url ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,6 +1000,9 @@ public class FlatUIDefaultsInspector
|
||||
{
|
||||
private Item item;
|
||||
|
||||
// used instead of getBackground() because this did not work in some 3rd party Lafs
|
||||
private Color valueColor;
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent( JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column )
|
||||
@@ -1023,7 +1026,7 @@ public class FlatUIDefaultsInspector
|
||||
if( item.value instanceof Color ) {
|
||||
Color color = (item.info instanceof Color[]) ? ((Color[])item.info)[0] : (Color) item.value;
|
||||
boolean isDark = new HSLColor( color ).getLuminance() < 70 && color.getAlpha() >= 128;
|
||||
setBackground( color );
|
||||
valueColor = color;
|
||||
setForeground( isDark ? Color.white : Color.black );
|
||||
} else if( item.value instanceof Icon ) {
|
||||
Icon icon = (Icon) item.value;
|
||||
@@ -1048,7 +1051,7 @@ public class FlatUIDefaultsInspector
|
||||
if( item.value instanceof Color ) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color background = getBackground();
|
||||
Color background = valueColor;
|
||||
|
||||
// paint color
|
||||
fillRect( g, background, 0, 0, width, height );
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.extras.components;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.STYLE_CLASS;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,24 @@ import javax.swing.JLabel;
|
||||
*/
|
||||
public class FlatLabel
|
||||
extends JLabel
|
||||
implements FlatStyleableComponent
|
||||
implements FlatComponentExtension, FlatStyleableComponent
|
||||
{
|
||||
// NOTE: enum names must be equal to typography/font styles
|
||||
public enum LabelType { h00, h0, h1, h2, h3, h4, large, regular, medium, small, mini, monospaced }
|
||||
|
||||
/**
|
||||
* Returns type of the label.
|
||||
*/
|
||||
public LabelType getLabelType() {
|
||||
return getClientPropertyEnumString( STYLE_CLASS, LabelType.class, null, LabelType.regular );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies type of the label.
|
||||
*/
|
||||
public void setLabelType( LabelType labelType ) {
|
||||
if( labelType == LabelType.regular )
|
||||
labelType = null;
|
||||
putClientPropertyEnumString( STYLE_CLASS, labelType );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +363,29 @@ public class FlatTabbedPane
|
||||
}
|
||||
|
||||
|
||||
// NOTE: enum names must be equal to allowed strings
|
||||
/** @since 2 */ public enum TabType { underlined, card };
|
||||
|
||||
/**
|
||||
* Returns type of selected tab.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public TabType getTabType() {
|
||||
return getClientPropertyEnumString( TABBED_PANE_TAB_TYPE, TabType.class,
|
||||
"TabbedPane.tabType", TabType.underlined );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies type of selected tab.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setTabType( TabType tabType ) {
|
||||
putClientPropertyEnumString( TABBED_PANE_TAB_TYPE, tabType );
|
||||
}
|
||||
|
||||
|
||||
// NOTE: enum names must be equal to allowed strings
|
||||
public enum TabsPopupPolicy { never, asNeeded };
|
||||
|
||||
|
||||
@@ -20,6 +20,6 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( "net.java.dev.jna:jna:5.7.0" )
|
||||
implementation( "net.java.dev.jna:jna-platform:5.7.0" )
|
||||
implementation( "net.java.dev.jna:jna:5.10.0" )
|
||||
implementation( "net.java.dev.jna:jna-platform:5.10.0" )
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.Structure.FieldOrder;
|
||||
import com.sun.jna.platform.win32.Advapi32Util;
|
||||
import com.sun.jna.platform.win32.BaseTSD;
|
||||
import com.sun.jna.platform.win32.BaseTSD.LONG_PTR;
|
||||
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
|
||||
import com.sun.jna.platform.win32.GDI32;
|
||||
import com.sun.jna.platform.win32.Shell32;
|
||||
@@ -77,6 +77,10 @@ import com.sun.jna.win32.W32APIOptions;
|
||||
// https://github.com/oberth/custom-chrome
|
||||
// https://github.com/rossy/borderless-window
|
||||
//
|
||||
// Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
// https://github.com/dotnet/wpf/issues/4825#issuecomment-930442736
|
||||
//
|
||||
|
||||
/**
|
||||
* Native window border support for Windows 10 when using custom decorations.
|
||||
@@ -160,30 +164,24 @@ public class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHeight( Window window, int titleBarHeight ) {
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds )
|
||||
{
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.titleBarHeight = titleBarHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||
wndProc.closeButtonBounds = cloneRectange( closeButtonBounds );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
|
||||
private static Rectangle cloneRectange( Rectangle rect ) {
|
||||
return (rect != null) ? new Rectangle( rect ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -293,7 +291,16 @@ public class FlatWindowsNativeWindowBorder
|
||||
WM_ERASEBKGND = 0x0014,
|
||||
WM_NCCALCSIZE = 0x0083,
|
||||
WM_NCHITTEST = 0x0084,
|
||||
|
||||
WM_NCMOUSEMOVE = 0x00A0,
|
||||
WM_NCLBUTTONDOWN = 0x00A1,
|
||||
WM_NCLBUTTONUP = 0x00A2,
|
||||
WM_NCRBUTTONUP = 0x00A5,
|
||||
|
||||
WM_MOUSEMOVE= 0x0200,
|
||||
WM_LBUTTONDOWN = 0x0201,
|
||||
WM_LBUTTONUP = 0x0202,
|
||||
|
||||
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;
|
||||
|
||||
// WM_SIZE wParam
|
||||
@@ -306,7 +313,10 @@ public class FlatWindowsNativeWindowBorder
|
||||
HTCLIENT = 1,
|
||||
HTCAPTION = 2,
|
||||
HTSYSMENU = 3,
|
||||
HTTOP = 12;
|
||||
HTMINBUTTON = 8,
|
||||
HTMAXBUTTON = 9,
|
||||
HTTOP = 12,
|
||||
HTCLOSE = 20;
|
||||
|
||||
private static final int ABS_AUTOHIDE = 0x0000001;
|
||||
private static final int ABM_GETAUTOHIDEBAREX = 0x0000000b;
|
||||
@@ -328,13 +338,17 @@ public class FlatWindowsNativeWindowBorder
|
||||
|
||||
private Window window;
|
||||
private final HWND hwnd;
|
||||
private final BaseTSD.LONG_PTR defaultWndProc;
|
||||
private final LONG_PTR defaultWndProc;
|
||||
private int wmSizeWParam = -1;
|
||||
private HBRUSH background;
|
||||
|
||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||
private int titleBarHeight;
|
||||
private Rectangle[] hitTestSpots;
|
||||
private Rectangle appIconBounds;
|
||||
private Rectangle minimizeButtonBounds;
|
||||
private Rectangle maximizeButtonBounds;
|
||||
private Rectangle closeButtonBounds;
|
||||
|
||||
WndProc( Window window ) {
|
||||
this.window = window;
|
||||
@@ -420,6 +434,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
*/
|
||||
@Override
|
||||
public LRESULT callback( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||
long wparam = wParam.longValue();
|
||||
switch( uMsg ) {
|
||||
case WM_NCCALCSIZE:
|
||||
return WmNcCalcSize( hwnd, uMsg, wParam, lParam );
|
||||
@@ -427,8 +442,29 @@ public class FlatWindowsNativeWindowBorder
|
||||
case WM_NCHITTEST:
|
||||
return WmNcHitTest( hwnd, uMsg, wParam, lParam );
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
// if mouse is moved over some non-client areas,
|
||||
// send it also to the client area to allow Swing to process it
|
||||
// (required for Windows 11 maximize button)
|
||||
if( wparam == HTMINBUTTON || wparam == HTMAXBUTTON || wparam == HTCLOSE ||
|
||||
wparam == HTCAPTION || wparam == HTSYSMENU )
|
||||
sendMessageToClientArea( hwnd, WM_MOUSEMOVE, lParam );
|
||||
break;
|
||||
|
||||
case WM_NCLBUTTONDOWN:
|
||||
case WM_NCLBUTTONUP:
|
||||
// if left mouse was pressed/released over minimize/maximize/close button,
|
||||
// send it also to the client area to allow Swing to process it
|
||||
// (required for Windows 11 maximize button)
|
||||
if( wparam == HTMINBUTTON || wparam == HTMAXBUTTON || wparam == HTCLOSE ) {
|
||||
int uClientMsg = (uMsg == WM_NCLBUTTONDOWN) ? WM_LBUTTONDOWN : WM_LBUTTONUP;
|
||||
sendMessageToClientArea( hwnd, uClientMsg, lParam );
|
||||
return new LRESULT( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCRBUTTONUP:
|
||||
if( wParam.longValue() == HTCAPTION || wParam.longValue() == HTSYSMENU )
|
||||
if( wparam == HTCAPTION || wparam == HTSYSMENU )
|
||||
openSystemMenu( hwnd, GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
|
||||
break;
|
||||
|
||||
@@ -522,7 +558,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
|
||||
boolean isMaximized = User32Ex.INSTANCE.IsZoomed( hwnd );
|
||||
if( isMaximized && !isFullscreen() ) {
|
||||
// When a window is maximized, its size is actually a little bit more
|
||||
// When a window is maximized, its size is actually a little bit larger
|
||||
// than the monitor's work area. The window is positioned and sized in
|
||||
// such a way that the resize handles are outside of the monitor and
|
||||
// then the window is clipped to the monitor so that the resize handle
|
||||
@@ -574,15 +610,12 @@ public class FlatWindowsNativeWindowBorder
|
||||
if( lResult.longValue() != HTCLIENT )
|
||||
return lResult;
|
||||
|
||||
// get window rectangle needed to convert mouse x/y from screen to window coordinates
|
||||
RECT rcWindow = new RECT();
|
||||
User32.INSTANCE.GetWindowRect( hwnd, rcWindow );
|
||||
|
||||
// get mouse x/y in window coordinates
|
||||
int x = GET_X_LPARAM( lParam ) - rcWindow.left;
|
||||
int y = GET_Y_LPARAM( lParam ) - rcWindow.top;
|
||||
LRESULT xy = screen2windowCoordinates( hwnd, lParam );
|
||||
int x = GET_X_LPARAM( xy );
|
||||
int y = GET_Y_LPARAM( xy );
|
||||
|
||||
// scale-down mouse x/y
|
||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||
Point pt = scaleDown( x, y );
|
||||
int sx = pt.x;
|
||||
int sy = pt.y;
|
||||
@@ -590,9 +623,26 @@ public class FlatWindowsNativeWindowBorder
|
||||
// return HTSYSMENU if mouse is over application icon
|
||||
// - left-click on HTSYSMENU area shows system menu
|
||||
// - double-left-click sends WM_CLOSE
|
||||
if( appIconBounds != null && appIconBounds.contains( sx, sy ) )
|
||||
if( contains( appIconBounds, sx, sy ) )
|
||||
return new LRESULT( HTSYSMENU );
|
||||
|
||||
// return HTMINBUTTON if mouse is over minimize button
|
||||
// - hovering mouse over HTMINBUTTON area shows tooltip on Windows 10/11
|
||||
if( contains( minimizeButtonBounds, sx, sy ) )
|
||||
return new LRESULT( HTMINBUTTON );
|
||||
|
||||
// return HTMAXBUTTON if mouse is over maximize/restore button
|
||||
// - hovering mouse over HTMAXBUTTON area shows tooltip on Windows 10
|
||||
// - hovering mouse over HTMAXBUTTON area shows snap layouts menu on Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
if( contains( maximizeButtonBounds, sx, sy ) )
|
||||
return new LRESULT( HTMAXBUTTON );
|
||||
|
||||
// return HTCLOSE if mouse is over close button
|
||||
// - hovering mouse over HTCLOSE area shows tooltip on Windows 10/11
|
||||
if( contains( closeButtonBounds, sx, sy ) )
|
||||
return new LRESULT( HTCLOSE );
|
||||
|
||||
int resizeBorderHeight = getResizeHandleHeight();
|
||||
boolean isOnResizeBorder = (y < resizeBorderHeight) &&
|
||||
(User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
||||
@@ -612,6 +662,25 @@ public class FlatWindowsNativeWindowBorder
|
||||
return new LRESULT( isOnResizeBorder ? HTTOP : HTCLIENT );
|
||||
}
|
||||
|
||||
private boolean contains( Rectangle rect, int x, int y ) {
|
||||
return (rect != null && rect.contains( x, y ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts screen coordinates to window coordinates.
|
||||
*/
|
||||
private LRESULT screen2windowCoordinates( HWND hwnd, LPARAM lParam ) {
|
||||
// get window rectangle needed to convert mouse x/y from screen to window coordinates
|
||||
RECT rcWindow = new RECT();
|
||||
User32.INSTANCE.GetWindowRect( hwnd, rcWindow );
|
||||
|
||||
// get mouse x/y in window coordinates
|
||||
int x = GET_X_LPARAM( lParam ) - rcWindow.left;
|
||||
int y = GET_Y_LPARAM( lParam ) - rcWindow.top;
|
||||
|
||||
return new LRESULT( MAKELONG( x, y ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the little space at the top of the window used to
|
||||
* resize the window.
|
||||
@@ -678,7 +747,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest#remarks
|
||||
*/
|
||||
private int GET_X_LPARAM( LPARAM lParam ) {
|
||||
private int GET_X_LPARAM( LONG_PTR lParam ) {
|
||||
return (short) (lParam.longValue() & 0xffff);
|
||||
}
|
||||
|
||||
@@ -688,10 +757,17 @@ public class FlatWindowsNativeWindowBorder
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest#remarks
|
||||
*/
|
||||
private int GET_Y_LPARAM( LPARAM lParam ) {
|
||||
private int GET_Y_LPARAM( LONG_PTR lParam ) {
|
||||
return (short) ((lParam.longValue() >> 16) & 0xffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same implementation as MAKELONG(wLow, wHigh) macro in windef.h.
|
||||
*/
|
||||
private long MAKELONG( int low, int high ) {
|
||||
return (low & 0xffff) | ((high & 0xffff) << 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same implementation as RGB(r,g,b) macro in wingdi.h.
|
||||
*/
|
||||
@@ -699,6 +775,14 @@ public class FlatWindowsNativeWindowBorder
|
||||
return new DWORD( (r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16) );
|
||||
}
|
||||
|
||||
private void sendMessageToClientArea( HWND hwnd, int uMsg, LPARAM lParam ) {
|
||||
// get mouse x/y in window coordinates
|
||||
LRESULT xy = screen2windowCoordinates( hwnd, lParam );
|
||||
|
||||
// send message
|
||||
User32.INSTANCE.SendMessage( hwnd, uMsg, new WPARAM(), new LPARAM( xy.longValue() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the window's system menu.
|
||||
* The system menu is the menu that opens when the user presses Alt+Space or
|
||||
|
||||
@@ -215,6 +215,27 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
|
||||
case WM_NCHITTEST:
|
||||
return WmNcHitTest( hwnd, uMsg, wParam, lParam );
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
// if mouse is moved over some non-client areas,
|
||||
// send it also to the client area to allow Swing to process it
|
||||
// (required for Windows 11 maximize button)
|
||||
if( wParam == HTMINBUTTON || wParam == HTMAXBUTTON || wParam == HTCLOSE ||
|
||||
wParam == HTCAPTION || wParam == HTSYSMENU )
|
||||
sendMessageToClientArea( hwnd, WM_MOUSEMOVE, lParam );
|
||||
break;
|
||||
|
||||
case WM_NCLBUTTONDOWN:
|
||||
case WM_NCLBUTTONUP:
|
||||
// if left mouse was pressed/released over minimize/maximize/close button,
|
||||
// send it also to the client area to allow Swing to process it
|
||||
// (required for Windows 11 maximize button)
|
||||
if( wParam == HTMINBUTTON || wParam == HTMAXBUTTON || wParam == HTCLOSE ) {
|
||||
int uClientMsg = (uMsg == WM_NCLBUTTONDOWN) ? WM_LBUTTONDOWN : WM_LBUTTONUP;
|
||||
sendMessageToClientArea( hwnd, uClientMsg, lParam );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCRBUTTONUP:
|
||||
if( wParam == HTCAPTION || wParam == HTSYSMENU )
|
||||
openSystemMenu( hwnd, GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
|
||||
@@ -305,7 +326,7 @@ LRESULT FlatWndProc::WmNcCalcSize( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lP
|
||||
|
||||
bool isMaximized = ::IsZoomed( hwnd );
|
||||
if( isMaximized && !isFullscreen() ) {
|
||||
// When a window is maximized, its size is actually a little bit more
|
||||
// When a window is maximized, its size is actually a little bit larger
|
||||
// than the monitor's work area. The window is positioned and sized in
|
||||
// such a way that the resize handles are outside of the monitor and
|
||||
// then the window is clipped to the monitor so that the resize handle
|
||||
@@ -354,6 +375,22 @@ LRESULT FlatWndProc::WmNcHitTest( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPa
|
||||
if( lResult != HTCLIENT )
|
||||
return lResult;
|
||||
|
||||
// get mouse x/y in window coordinates
|
||||
LRESULT xy = screen2windowCoordinates( hwnd, lParam );
|
||||
int x = GET_X_LPARAM( xy );
|
||||
int y = GET_Y_LPARAM( xy );
|
||||
|
||||
int resizeBorderHeight = getResizeHandleHeight();
|
||||
bool isOnResizeBorder = (y < resizeBorderHeight) &&
|
||||
(::GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
||||
|
||||
return onNcHitTest( x, y, isOnResizeBorder );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts screen coordinates to window coordinates.
|
||||
*/
|
||||
LRESULT FlatWndProc::screen2windowCoordinates( HWND hwnd, LPARAM lParam ) {
|
||||
// get window rectangle needed to convert mouse x/y from screen to window coordinates
|
||||
RECT rcWindow;
|
||||
::GetWindowRect( hwnd, &rcWindow );
|
||||
@@ -362,11 +399,7 @@ LRESULT FlatWndProc::WmNcHitTest( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPa
|
||||
int x = GET_X_LPARAM( lParam ) - rcWindow.left;
|
||||
int y = GET_Y_LPARAM( lParam ) - rcWindow.top;
|
||||
|
||||
int resizeBorderHeight = getResizeHandleHeight();
|
||||
bool isOnResizeBorder = (y < resizeBorderHeight) &&
|
||||
(::GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
||||
|
||||
return onNcHitTest( x, y, isOnResizeBorder );
|
||||
return MAKELONG( x, y );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,6 +462,14 @@ JNIEnv* FlatWndProc::getEnv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
void FlatWndProc::sendMessageToClientArea( HWND hwnd, int uMsg, LPARAM lParam ) {
|
||||
// get mouse x/y in window coordinates
|
||||
LRESULT xy = screen2windowCoordinates( hwnd, lParam );
|
||||
|
||||
// send message
|
||||
::SendMessage( hwnd, uMsg, 0, xy );
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the window's system menu.
|
||||
* The system menu is the menu that opens when the user presses Alt+Space or
|
||||
|
||||
@@ -54,6 +54,7 @@ private:
|
||||
LRESULT WmNcCalcSize( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );
|
||||
LRESULT WmNcHitTest( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
LRESULT screen2windowCoordinates( HWND hwnd, LPARAM lParam );
|
||||
int getResizeHandleHeight();
|
||||
bool hasAutohideTaskbar( UINT edge, RECT rcMonitor );
|
||||
BOOL isFullscreen();
|
||||
@@ -61,6 +62,7 @@ private:
|
||||
void fireStateChangedLaterOnce();
|
||||
JNIEnv* getEnv();
|
||||
|
||||
void sendMessageToClientArea( HWND hwnd, int uMsg, LPARAM lParam );
|
||||
void openSystemMenu( HWND hwnd, int x, int y );
|
||||
void setMenuItemState( HMENU systemMenu, int item, bool enabled );
|
||||
|
||||
|
||||
@@ -13,8 +13,14 @@ extern "C" {
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTCAPTION 2L
|
||||
#undef com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTSYSMENU
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTSYSMENU 3L
|
||||
#undef com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTMINBUTTON
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTMINBUTTON 8L
|
||||
#undef com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTMAXBUTTON
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTMAXBUTTON 9L
|
||||
#undef com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTTOP
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTTOP 12L
|
||||
#undef com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTCLOSE
|
||||
#define com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc_HTCLOSE 20L
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
|
||||
* Method: installImpl
|
||||
|
||||
@@ -1,20 +1,46 @@
|
||||
- Java 1.8.0_202
|
||||
+ Java 1.8.0_292
|
||||
|
||||
- OS Windows 10
|
||||
+ OS Mac OS X
|
||||
|
||||
#---- ComboBox ----
|
||||
|
||||
+ ComboBox.showPopupOnNavigation true
|
||||
|
||||
|
||||
#---- FileChooser ----
|
||||
|
||||
- FileChooser.useSystemExtensionHiding true
|
||||
+ FileChooser.useSystemExtensionHiding false
|
||||
|
||||
|
||||
#---- Menu ----
|
||||
|
||||
- Menu.shortcutKeys length=1 [I
|
||||
[0] 8
|
||||
+ Menu.shortcutKeys length=1 [I
|
||||
[0] 10
|
||||
|
||||
|
||||
#---- MenuItem ----
|
||||
|
||||
- MenuItem.acceleratorDelimiter -
|
||||
+ MenuItem.acceleratorDelimiter
|
||||
|
||||
|
||||
#---- OptionPane ----
|
||||
|
||||
+ OptionPane.isYesLast true
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
|
||||
- ProgressBar.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
+ ProgressBar.font [active] .SF NS Text plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
+ ProgressBar.font [active] Helvetica Neue plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
- ScrollBar.hoverThumbWithTrack false
|
||||
+ ScrollBar.hoverThumbWithTrack true
|
||||
@@ -27,7 +53,93 @@
|
||||
|
||||
- ScrollBar.thumbInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
|
||||
+ ScrollBar.thumbInsets 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||
|
||||
- defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ defaultFont .SF NS Text plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
+ defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
|
||||
#---- h0 ----
|
||||
|
||||
- h0.font [active] Segoe UI plain 30 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h0.font [active] Helvetica Neue plain 31 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h00 ----
|
||||
|
||||
- h00.font [active] Segoe UI plain 36 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h00.font [active] Helvetica Neue plain 37 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h1 ----
|
||||
|
||||
- h1.font [active] Segoe UI Semibold plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h1.font [active] HelveticaNeue-Medium plain 25 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h1.regular.font [active] Segoe UI plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h1.regular.font [active] Helvetica Neue plain 25 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h2 ----
|
||||
|
||||
- h2.font [active] Segoe UI Semibold plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h2.font [active] HelveticaNeue-Medium plain 19 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h2.regular.font [active] Segoe UI plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h2.regular.font [active] Helvetica Neue plain 19 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h3 ----
|
||||
|
||||
- h3.font [active] Segoe UI Semibold plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h3.font [active] HelveticaNeue-Medium plain 16 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h3.regular.font [active] Segoe UI plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h3.regular.font [active] Helvetica Neue plain 16 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h4 ----
|
||||
|
||||
- h4.font [active] Segoe UI bold 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h4.font [active] Helvetica Neue bold 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- large ----
|
||||
|
||||
- large.font [active] Segoe UI plain 14 javax.swing.plaf.FontUIResource [UI]
|
||||
+ large.font [active] Helvetica Neue plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- light ----
|
||||
|
||||
- light.font [active] Segoe UI Light plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ light.font [active] HelveticaNeue-Thin plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- medium ----
|
||||
|
||||
- medium.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
+ medium.font [active] Helvetica Neue plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- mini ----
|
||||
|
||||
- mini.font [active] Segoe UI plain 9 javax.swing.plaf.FontUIResource [UI]
|
||||
+ mini.font [active] Helvetica Neue plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- monospaced ----
|
||||
|
||||
- monospaced.font [active] Consolas plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ monospaced.font [active] Menlo plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- semibold ----
|
||||
|
||||
- semibold.font [active] Segoe UI Semibold plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ semibold.font [active] HelveticaNeue-Medium plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- small ----
|
||||
|
||||
- small.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
+ small.font [active] Helvetica Neue plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
@@ -671,6 +671,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U
|
||||
OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI]
|
||||
OptionPane.sameSizeButtons true
|
||||
OptionPane.setButtonMargin false
|
||||
OptionPane.showIcon false
|
||||
OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI]
|
||||
OptionPane.windowBindings length=2 [Ljava.lang.Object;
|
||||
[0] ESCAPE
|
||||
@@ -818,6 +819,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor #4d5154 HSL 206 4 32 com.formdev.flatlaf.util.DerivedColor [UI] lighten(7% autoInverse)
|
||||
RootPane.background #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI]
|
||||
RootPane.borderDragThickness 5
|
||||
RootPane.cornerDragWidth 16
|
||||
@@ -830,6 +832,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object;
|
||||
[5] press
|
||||
[6] ctrl released ENTER
|
||||
[7] release
|
||||
RootPane.font [active] $defaultFont [UI]
|
||||
RootPane.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.honorDialogMinimumSizeOnResize true
|
||||
RootPane.honorFrameMinimumSizeOnResize false
|
||||
RootPane.inactiveBorderColor #484c4e HSL 200 4 29 com.formdev.flatlaf.util.DerivedColor [UI] lighten(5% autoInverse)
|
||||
@@ -1001,6 +1005,7 @@ TabbedPane.buttonArc 6
|
||||
TabbedPane.buttonHoverBackground #303234 HSL 210 4 20 com.formdev.flatlaf.util.DerivedColor [UI] darken(5%)
|
||||
TabbedPane.buttonInsets 2,1,2,1 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TabbedPane.buttonPressedBackground #282a2c HSL 210 5 16 com.formdev.flatlaf.util.DerivedColor [UI] darken(8%)
|
||||
TabbedPane.cardTabSelectionHeight 2
|
||||
TabbedPane.closeArc 4
|
||||
TabbedPane.closeCrossFilledSize 7.5
|
||||
TabbedPane.closeCrossLineWidth 1
|
||||
@@ -1043,6 +1048,7 @@ TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [U
|
||||
TabbedPane.tabRunOverlay 0
|
||||
TabbedPane.tabSelectionHeight 3
|
||||
TabbedPane.tabSeparatorsFullHeight false
|
||||
TabbedPane.tabType underlined
|
||||
TabbedPane.tabWidthMode preferred
|
||||
TabbedPane.tabsOpaque true
|
||||
TabbedPane.tabsOverlapBorder false
|
||||
@@ -1213,9 +1219,11 @@ TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.Colo
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarTitleGap 20
|
||||
TitlePane.noIconLeftGap 8
|
||||
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
|
||||
TitlePane.showIcon true
|
||||
TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TitlePane.unifiedBackground false
|
||||
TitlePane.unifiedBackground true
|
||||
TitlePane.useWindowDecorations true
|
||||
|
||||
|
||||
@@ -1384,6 +1392,26 @@ Viewport.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.Colo
|
||||
ViewportUI com.formdev.flatlaf.ui.FlatViewportUI
|
||||
|
||||
|
||||
#---- [style] ----
|
||||
|
||||
[style].h00 font: $h00.font
|
||||
[style].h0 font: $h0.font
|
||||
[style].h1.regular font: $h1.regular.font
|
||||
[style].h1 font: $h1.font
|
||||
[style].h2.regular font: $h2.regular.font
|
||||
[style].h2 font: $h2.font
|
||||
[style].h3.regular font: $h3.regular.font
|
||||
[style].h3 font: $h3.font
|
||||
[style].h4 font: $h4.font
|
||||
[style].large font: $large.font
|
||||
[style].light font: $light.font
|
||||
[style].medium font: $medium.font
|
||||
[style].mini font: $mini.font
|
||||
[style].monospaced font: $monospaced.font
|
||||
[style].semibold font: $semibold.font
|
||||
[style].small font: $small.font
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
activeCaption #434e60 HSL 217 18 32 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1399,6 +1427,39 @@ defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResou
|
||||
desktop #46494b HSL 204 3 28 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- h0 ----
|
||||
|
||||
h0.font [active] Segoe UI plain 30 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h00 ----
|
||||
|
||||
h00.font [active] Segoe UI plain 36 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h1 ----
|
||||
|
||||
h1.font [active] Segoe UI Semibold plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
h1.regular.font [active] Segoe UI plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h2 ----
|
||||
|
||||
h2.font [active] Segoe UI Semibold plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
h2.regular.font [active] Segoe UI plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h3 ----
|
||||
|
||||
h3.font [active] Segoe UI Semibold plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
h3.regular.font [active] Segoe UI plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h4 ----
|
||||
|
||||
h4.font [active] Segoe UI bold 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- html ----
|
||||
|
||||
html.missingImage [lazy] 38,38 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
|
||||
@@ -1420,13 +1481,52 @@ laf.dark true
|
||||
laf.scaleFactor [active] 1.0
|
||||
|
||||
|
||||
#---- large ----
|
||||
|
||||
large.font [active] Segoe UI plain 14 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- light ----
|
||||
|
||||
light.font [active] Segoe UI Light plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- medium ----
|
||||
|
||||
medium.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
menu #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI]
|
||||
menuText #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- mini ----
|
||||
|
||||
mini.font [active] Segoe UI plain 9 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- monospaced ----
|
||||
|
||||
monospaced.font [active] Consolas plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
scrollbar #3e4244 HSL 200 5 25 com.formdev.flatlaf.util.DerivedColor [UI] lighten(1%)
|
||||
|
||||
|
||||
#---- semibold ----
|
||||
|
||||
semibold.font [active] Segoe UI Semibold plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- small ----
|
||||
|
||||
small.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- swingx/TaskPane ----
|
||||
|
||||
swingx/TaskPaneUI com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI
|
||||
|
||||
@@ -1,20 +1,46 @@
|
||||
- Java 1.8.0_202
|
||||
+ Java 1.8.0_292
|
||||
|
||||
- OS Windows 10
|
||||
+ OS Mac OS X
|
||||
|
||||
#---- ComboBox ----
|
||||
|
||||
+ ComboBox.showPopupOnNavigation true
|
||||
|
||||
|
||||
#---- FileChooser ----
|
||||
|
||||
- FileChooser.useSystemExtensionHiding true
|
||||
+ FileChooser.useSystemExtensionHiding false
|
||||
|
||||
|
||||
#---- Menu ----
|
||||
|
||||
- Menu.shortcutKeys length=1 [I
|
||||
[0] 8
|
||||
+ Menu.shortcutKeys length=1 [I
|
||||
[0] 10
|
||||
|
||||
|
||||
#---- MenuItem ----
|
||||
|
||||
- MenuItem.acceleratorDelimiter -
|
||||
+ MenuItem.acceleratorDelimiter
|
||||
|
||||
|
||||
#---- OptionPane ----
|
||||
|
||||
+ OptionPane.isYesLast true
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
|
||||
- ProgressBar.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
+ ProgressBar.font [active] .SF NS Text plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
+ ProgressBar.font [active] Helvetica Neue plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
- ScrollBar.hoverThumbWithTrack false
|
||||
+ ScrollBar.hoverThumbWithTrack true
|
||||
@@ -27,7 +53,93 @@
|
||||
|
||||
- ScrollBar.thumbInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
|
||||
+ ScrollBar.thumbInsets 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||
|
||||
- defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ defaultFont .SF NS Text plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
+ defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
|
||||
#---- h0 ----
|
||||
|
||||
- h0.font [active] Segoe UI plain 30 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h0.font [active] Helvetica Neue plain 31 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h00 ----
|
||||
|
||||
- h00.font [active] Segoe UI plain 36 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h00.font [active] Helvetica Neue plain 37 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h1 ----
|
||||
|
||||
- h1.font [active] Segoe UI Semibold plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h1.font [active] HelveticaNeue-Medium plain 25 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h1.regular.font [active] Segoe UI plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h1.regular.font [active] Helvetica Neue plain 25 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h2 ----
|
||||
|
||||
- h2.font [active] Segoe UI Semibold plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h2.font [active] HelveticaNeue-Medium plain 19 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h2.regular.font [active] Segoe UI plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h2.regular.font [active] Helvetica Neue plain 19 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h3 ----
|
||||
|
||||
- h3.font [active] Segoe UI Semibold plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h3.font [active] HelveticaNeue-Medium plain 16 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
- h3.regular.font [active] Segoe UI plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h3.regular.font [active] Helvetica Neue plain 16 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h4 ----
|
||||
|
||||
- h4.font [active] Segoe UI bold 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ h4.font [active] Helvetica Neue bold 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- large ----
|
||||
|
||||
- large.font [active] Segoe UI plain 14 javax.swing.plaf.FontUIResource [UI]
|
||||
+ large.font [active] Helvetica Neue plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- light ----
|
||||
|
||||
- light.font [active] Segoe UI Light plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ light.font [active] HelveticaNeue-Thin plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- medium ----
|
||||
|
||||
- medium.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
+ medium.font [active] Helvetica Neue plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- mini ----
|
||||
|
||||
- mini.font [active] Segoe UI plain 9 javax.swing.plaf.FontUIResource [UI]
|
||||
+ mini.font [active] Helvetica Neue plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- monospaced ----
|
||||
|
||||
- monospaced.font [active] Consolas plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ monospaced.font [active] Menlo plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- semibold ----
|
||||
|
||||
- semibold.font [active] Segoe UI Semibold plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
+ semibold.font [active] HelveticaNeue-Medium plain 13 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- small ----
|
||||
|
||||
- small.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
+ small.font [active] Helvetica Neue plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
@@ -676,6 +676,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U
|
||||
OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI]
|
||||
OptionPane.sameSizeButtons true
|
||||
OptionPane.setButtonMargin false
|
||||
OptionPane.showIcon false
|
||||
OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI]
|
||||
OptionPane.windowBindings length=2 [Ljava.lang.Object;
|
||||
[0] ESCAPE
|
||||
@@ -823,6 +824,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor #737373 HSL 0 0 45 com.formdev.flatlaf.util.DerivedColor [UI] darken(50% autoInverse)
|
||||
RootPane.background #f2f2f2 HSL 0 0 95 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI]
|
||||
RootPane.borderDragThickness 5
|
||||
RootPane.cornerDragWidth 16
|
||||
@@ -835,6 +837,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object;
|
||||
[5] press
|
||||
[6] ctrl released ENTER
|
||||
[7] release
|
||||
RootPane.font [active] $defaultFont [UI]
|
||||
RootPane.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.honorDialogMinimumSizeOnResize true
|
||||
RootPane.honorFrameMinimumSizeOnResize false
|
||||
RootPane.inactiveBorderColor #a6a6a6 HSL 0 0 65 com.formdev.flatlaf.util.DerivedColor [UI] darken(30% autoInverse)
|
||||
@@ -1006,6 +1010,7 @@ TabbedPane.buttonArc 6
|
||||
TabbedPane.buttonHoverBackground #e0e0e0 HSL 0 0 88 com.formdev.flatlaf.util.DerivedColor [UI] darken(7% autoInverse)
|
||||
TabbedPane.buttonInsets 2,1,2,1 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TabbedPane.buttonPressedBackground #d9d9d9 HSL 0 0 85 com.formdev.flatlaf.util.DerivedColor [UI] darken(10% autoInverse)
|
||||
TabbedPane.cardTabSelectionHeight 2
|
||||
TabbedPane.closeArc 4
|
||||
TabbedPane.closeCrossFilledSize 7.5
|
||||
TabbedPane.closeCrossLineWidth 1
|
||||
@@ -1048,6 +1053,7 @@ TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [U
|
||||
TabbedPane.tabRunOverlay 0
|
||||
TabbedPane.tabSelectionHeight 3
|
||||
TabbedPane.tabSeparatorsFullHeight false
|
||||
TabbedPane.tabType underlined
|
||||
TabbedPane.tabWidthMode preferred
|
||||
TabbedPane.tabsOpaque true
|
||||
TabbedPane.tabsOverlapBorder false
|
||||
@@ -1218,9 +1224,11 @@ TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.Colo
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarTitleGap 20
|
||||
TitlePane.noIconLeftGap 8
|
||||
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
|
||||
TitlePane.showIcon true
|
||||
TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TitlePane.unifiedBackground false
|
||||
TitlePane.unifiedBackground true
|
||||
TitlePane.useWindowDecorations true
|
||||
|
||||
|
||||
@@ -1389,6 +1397,26 @@ Viewport.foreground #000000 HSL 0 0 0 javax.swing.plaf.Colo
|
||||
ViewportUI com.formdev.flatlaf.ui.FlatViewportUI
|
||||
|
||||
|
||||
#---- [style] ----
|
||||
|
||||
[style].h00 font: $h00.font
|
||||
[style].h0 font: $h0.font
|
||||
[style].h1.regular font: $h1.regular.font
|
||||
[style].h1 font: $h1.font
|
||||
[style].h2.regular font: $h2.regular.font
|
||||
[style].h2 font: $h2.font
|
||||
[style].h3.regular font: $h3.regular.font
|
||||
[style].h3 font: $h3.font
|
||||
[style].h4 font: $h4.font
|
||||
[style].large font: $large.font
|
||||
[style].light font: $light.font
|
||||
[style].medium font: $medium.font
|
||||
[style].mini font: $mini.font
|
||||
[style].monospaced font: $monospaced.font
|
||||
[style].semibold font: $semibold.font
|
||||
[style].small font: $small.font
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
activeCaption #99b4d1 HSL 211 38 71 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1404,6 +1432,39 @@ defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResou
|
||||
desktop #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- h0 ----
|
||||
|
||||
h0.font [active] Segoe UI plain 30 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h00 ----
|
||||
|
||||
h00.font [active] Segoe UI plain 36 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h1 ----
|
||||
|
||||
h1.font [active] Segoe UI Semibold plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
h1.regular.font [active] Segoe UI plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h2 ----
|
||||
|
||||
h2.font [active] Segoe UI Semibold plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
h2.regular.font [active] Segoe UI plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h3 ----
|
||||
|
||||
h3.font [active] Segoe UI Semibold plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
h3.regular.font [active] Segoe UI plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h4 ----
|
||||
|
||||
h4.font [active] Segoe UI bold 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- html ----
|
||||
|
||||
html.missingImage [lazy] 38,38 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
|
||||
@@ -1425,13 +1486,52 @@ laf.dark false
|
||||
laf.scaleFactor [active] 1.0
|
||||
|
||||
|
||||
#---- large ----
|
||||
|
||||
large.font [active] Segoe UI plain 14 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- light ----
|
||||
|
||||
light.font [active] Segoe UI Light plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- medium ----
|
||||
|
||||
medium.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
menu #f2f2f2 HSL 0 0 95 javax.swing.plaf.ColorUIResource [UI]
|
||||
menuText #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- mini ----
|
||||
|
||||
mini.font [active] Segoe UI plain 9 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- monospaced ----
|
||||
|
||||
monospaced.font [active] Consolas plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
scrollbar #f5f5f5 HSL 0 0 96 com.formdev.flatlaf.util.DerivedColor [UI] lighten(1%)
|
||||
|
||||
|
||||
#---- semibold ----
|
||||
|
||||
semibold.font [active] Segoe UI Semibold plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- small ----
|
||||
|
||||
small.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- swingx/TaskPane ----
|
||||
|
||||
swingx/TaskPaneUI com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI
|
||||
|
||||
@@ -687,6 +687,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U
|
||||
OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI]
|
||||
OptionPane.sameSizeButtons true
|
||||
OptionPane.setButtonMargin false
|
||||
OptionPane.showIcon false
|
||||
OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI]
|
||||
OptionPane.windowBindings length=2 [Ljava.lang.Object;
|
||||
[0] ESCAPE
|
||||
@@ -833,6 +834,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.background #ccffcc HSL 120 100 90 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI]
|
||||
RootPane.borderDragThickness 5
|
||||
RootPane.cornerDragWidth 16
|
||||
@@ -845,6 +847,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object;
|
||||
[5] press
|
||||
[6] ctrl released ENTER
|
||||
[7] release
|
||||
RootPane.font [active] $defaultFont [UI]
|
||||
RootPane.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.honorDialogMinimumSizeOnResize true
|
||||
RootPane.honorFrameMinimumSizeOnResize false
|
||||
RootPaneUI com.formdev.flatlaf.ui.FlatRootPaneUI
|
||||
@@ -1017,6 +1021,7 @@ TabbedPane.buttonArc 6
|
||||
TabbedPane.buttonHoverBackground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.buttonInsets 2,1,2,1 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TabbedPane.buttonPressedBackground #ffc800 HSL 47 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.cardTabSelectionHeight 2
|
||||
TabbedPane.closeArc 999
|
||||
TabbedPane.closeCrossFilledSize 6.5
|
||||
TabbedPane.closeCrossLineWidth 2
|
||||
@@ -1062,6 +1067,7 @@ TabbedPane.tabRunOverlay 0
|
||||
TabbedPane.tabSelectionHeight 3
|
||||
TabbedPane.tabSeparatorColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.tabSeparatorsFullHeight false
|
||||
TabbedPane.tabType underlined
|
||||
TabbedPane.tabWidthMode preferred
|
||||
TabbedPane.tabsOpaque true
|
||||
TabbedPane.tabsOverlapBorder false
|
||||
@@ -1233,9 +1239,11 @@ TitlePane.inactiveForeground #ffffff HSL 0 0 100 javax.swing.plaf.Colo
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarTitleGap 20
|
||||
TitlePane.noIconLeftGap 8
|
||||
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
|
||||
TitlePane.showIcon true
|
||||
TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
|
||||
TitlePane.unifiedBackground false
|
||||
TitlePane.unifiedBackground true
|
||||
TitlePane.useWindowDecorations true
|
||||
|
||||
|
||||
@@ -1403,6 +1411,26 @@ Viewport.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.Colo
|
||||
ViewportUI com.formdev.flatlaf.ui.FlatViewportUI
|
||||
|
||||
|
||||
#---- [style] ----
|
||||
|
||||
[style].h00 font: $h00.font
|
||||
[style].h0 font: $h0.font
|
||||
[style].h1.regular font: $h1.regular.font
|
||||
[style].h1 font: $h1.font
|
||||
[style].h2.regular font: $h2.regular.font
|
||||
[style].h2 font: $h2.font
|
||||
[style].h3.regular font: $h3.regular.font
|
||||
[style].h3 font: $h3.font
|
||||
[style].h4 font: $h4.font
|
||||
[style].large font: $large.font
|
||||
[style].light font: $light.font
|
||||
[style].medium font: $medium.font
|
||||
[style].mini font: $mini.font
|
||||
[style].monospaced font: $monospaced.font
|
||||
[style].semibold font: $semibold.font
|
||||
[style].small font: $small.font
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
activeCaption #99b4d1 HSL 211 38 71 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1418,6 +1446,39 @@ defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResou
|
||||
desktop #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- h0 ----
|
||||
|
||||
h0.font [active] Segoe UI plain 30 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h00 ----
|
||||
|
||||
h00.font [active] Segoe UI plain 36 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h1 ----
|
||||
|
||||
h1.font [active] Segoe UI Semibold plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
h1.regular.font [active] Segoe UI plain 24 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h2 ----
|
||||
|
||||
h2.font [active] Segoe UI Semibold plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
h2.regular.font [active] Segoe UI plain 18 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h3 ----
|
||||
|
||||
h3.font [active] Segoe UI Semibold plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
h3.regular.font [active] Segoe UI plain 15 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- h4 ----
|
||||
|
||||
h4.font [active] Segoe UI bold 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- html ----
|
||||
|
||||
html.missingImage [lazy] 38,38 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
|
||||
@@ -1439,13 +1500,52 @@ laf.dark false
|
||||
laf.scaleFactor [active] 1.0
|
||||
|
||||
|
||||
#---- large ----
|
||||
|
||||
large.font [active] Segoe UI plain 14 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- light ----
|
||||
|
||||
light.font [active] Segoe UI Light plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- medium ----
|
||||
|
||||
medium.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
menu #ccffcc HSL 120 100 90 javax.swing.plaf.ColorUIResource [UI]
|
||||
menuText #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- mini ----
|
||||
|
||||
mini.font [active] Segoe UI plain 9 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- monospaced ----
|
||||
|
||||
monospaced.font [active] Consolas plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- ----
|
||||
|
||||
scrollbar #88ff88 HSL 120 100 77 javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
|
||||
#---- semibold ----
|
||||
|
||||
semibold.font [active] Segoe UI Semibold plain 12 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- small ----
|
||||
|
||||
small.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
|
||||
|
||||
|
||||
#---- swingx/TaskPane ----
|
||||
|
||||
swingx/TaskPaneUI com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/flatlaf-testing-modular-app"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
|
||||
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-17/"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="-Ddummy=dummy"/>
|
||||
<listAttribute key="org.eclipse.jdt.launching.MODULEPATH">
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-17/" path="4" type="4"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/flatlaf-testing-modular-app/build/libs/flatlaf-testing-modular-app-2.0-SNAPSHOT.jar" path="4" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/flatlaf-core/build/libs/flatlaf-2.0-SNAPSHOT.jar" path="4" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/flatlaf-extras/build/libs/flatlaf-extras-2.0-SNAPSHOT.jar" path="4" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry externalArchive="C:/Users/charly/.gradle/caches/modules-2/files-2.1/com.formdev/svgSalamander/1.1.2.4/828c2ce815bf62031764f5219597948bd2587aa5/svgSalamander-1.1.2.4.jar" path="4" type="2"/> "/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="flatlaf-testing-modular-app"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-m com.formdev.flatlaf.testing.modular.app/com.formdev.flatlaf.testing.modular.app.FlatModularAppTest"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="flatlaf-testing-modular-app"/>
|
||||
</launchConfiguration>
|
||||
30
flatlaf-testing/flatlaf-testing-modular-app/build.gradle.kts
Normal file
30
flatlaf-testing/flatlaf-testing-modular-app/build.gradle.kts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`flatlaf-module-info`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( project( ":flatlaf-extras" ) )
|
||||
}
|
||||
|
||||
flatlafModuleInfo {
|
||||
dependsOn( ":flatlaf-core:jar" )
|
||||
dependsOn( ":flatlaf-extras:jar" )
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.testing.modular.app;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
import com.formdev.flatlaf.extras.FlatSVGUtils;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatModularAppTest
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatLaf.registerCustomDefaultsSource(
|
||||
FlatModularAppTest.class.getResource( "/com/formdev/flatlaf/testing/modular/app/themes/" ) );
|
||||
FlatLightLaf.setup();
|
||||
|
||||
JButton button1 = new JButton( "Hello" );
|
||||
JButton button2 = new JButton( "World" );
|
||||
|
||||
button1.setIcon( new FlatSVGIcon(
|
||||
FlatModularAppTest.class.getResource( "/com/formdev/flatlaf/testing/modular/app/icons/copy.svg" ) ) );
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.add( new JLabel( "Hello World" ) );
|
||||
panel.add( button1 );
|
||||
panel.add( button2 );
|
||||
|
||||
JFrame frame = new JFrame( "FlatModularAppTest" );
|
||||
frame.setIconImages( FlatSVGUtils.createWindowIconImages(
|
||||
FlatModularAppTest.class.getResource( "/com/formdev/flatlaf/testing/modular/app/icons/copy.svg" ) ) );
|
||||
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
||||
frame.getContentPane().add( panel );
|
||||
frame.pack();
|
||||
frame.setLocationRelativeTo( null );
|
||||
frame.setVisible( true );
|
||||
} );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.formdev.flatlaf.testing.modular.app.plaf;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class MyButtonUI
|
||||
extends FlatButtonUI
|
||||
{
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new MyButtonUI();
|
||||
}
|
||||
|
||||
protected MyButtonUI() {
|
||||
super( false );
|
||||
System.out.println( "MyButtonUI" );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
module com.formdev.flatlaf.testing.modular.app {
|
||||
requires java.desktop;
|
||||
requires com.formdev.flatlaf;
|
||||
requires com.formdev.flatlaf.extras;
|
||||
requires com.kitfox.svg;
|
||||
|
||||
exports com.formdev.flatlaf.testing.modular.app.plaf;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#6E6E6E" d="M11,3 L4,3 L4,11 L2,11 L2,1 L11,1 L11,3 Z"/>
|
||||
<path fill="#6E6E6E" d="M5,4 L14,4 L14,14 L5,14 L5,4 Z M7,6 L7,7 L12,7 L12,6 L7,6 Z M7,10 L7,11 L12,11 L12,10 L7,10 Z M7,8 L7,9 L12,9 L12,8 L7,8 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 510 B |
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright 2020 FormDev Software GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
@background = #fff
|
||||
@foreground = #f00
|
||||
|
||||
ButtonUI = com.formdev.flatlaf.testing.modular.app.plaf.MyButtonUI
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.testing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.AbstractBorder;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.AnimatedBorder;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatAnimatedBorderTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
private static final Color CHART_FADE_1 = Color.blue;
|
||||
private static final Color CHART_FADE_2 = Color.red;
|
||||
private static final Color CHART_MATERIAL_1 = Color.green;
|
||||
private static final Color CHART_MATERIAL_2 = Color.magenta;
|
||||
private static final Color CHART_MATERIAL_3 = Color.pink;
|
||||
private static final Color CHART_MATERIAL_4 = Color.cyan;
|
||||
private static final Color CHART_MINIMAL = Color.orange;
|
||||
|
||||
private static final String CHART_COLOR_KEY = "chartColor";
|
||||
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatAnimatedBorderTest" );
|
||||
frame.showFrame( FlatAnimatedBorderTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatAnimatedBorderTest() {
|
||||
initComponents();
|
||||
|
||||
fade1TextField.setBorder( new AnimatedFocusFadeBorder() );
|
||||
fade2TextField.setBorder( new AnimatedFocusFadeBorder() );
|
||||
|
||||
material1TextField.setBorder( new AnimatedMaterialBorder() );
|
||||
material2TextField.setBorder( new AnimatedMaterialBorder() );
|
||||
material3TextField.setBorder( new AnimatedMaterialLabeledBorder() );
|
||||
material4TextField.setBorder( new AnimatedMaterialLabeledBorder() );
|
||||
|
||||
minimalTextField.setBorder( new AnimatedMinimalTestBorder() );
|
||||
|
||||
fade1TextField.putClientProperty( CHART_COLOR_KEY, CHART_FADE_1 );
|
||||
fade2TextField.putClientProperty( CHART_COLOR_KEY, CHART_FADE_2 );
|
||||
material1TextField.putClientProperty( CHART_COLOR_KEY, CHART_MATERIAL_1 );
|
||||
material2TextField.putClientProperty( CHART_COLOR_KEY, CHART_MATERIAL_2 );
|
||||
material3TextField.putClientProperty( CHART_COLOR_KEY, CHART_MATERIAL_3 );
|
||||
material4TextField.putClientProperty( CHART_COLOR_KEY, CHART_MATERIAL_4 );
|
||||
minimalTextField.putClientProperty( CHART_COLOR_KEY, CHART_MINIMAL );
|
||||
|
||||
fade1ChartColor.setForeground( CHART_FADE_1 );
|
||||
fade2ChartColor.setForeground( CHART_FADE_2 );
|
||||
material1ChartColor.setForeground( CHART_MATERIAL_1 );
|
||||
material2ChartColor.setForeground( CHART_MATERIAL_2 );
|
||||
material3ChartColor.setForeground( CHART_MATERIAL_3 );
|
||||
material4ChartColor.setForeground( CHART_MATERIAL_4 );
|
||||
minimalChartColor.setForeground( CHART_MINIMAL );
|
||||
|
||||
material3TextField.putClientProperty( AnimatedMaterialLabeledBorder.LABEL_TEXT_KEY, "Label" );
|
||||
material4TextField.putClientProperty( AnimatedMaterialLabeledBorder.LABEL_TEXT_KEY, "Label" );
|
||||
material4TextField.setText( "Text" );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
label3 = new JLabel();
|
||||
lineChartPanel = new LineChartPanel();
|
||||
fade1TextField = new JTextField();
|
||||
fade1ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
fade2TextField = new JTextField();
|
||||
fade2ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
label2 = new JLabel();
|
||||
material1TextField = new JTextField();
|
||||
material1ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
material2TextField = new JTextField();
|
||||
material2ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
material3TextField = new JTextField();
|
||||
material3ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
material4TextField = new JTextField();
|
||||
material4ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
label1 = new JLabel();
|
||||
minimalTextField = new JTextField();
|
||||
minimalChartColor = new FlatAnimatorTest.JChartColor();
|
||||
durationLabel = new JLabel();
|
||||
durationField = new JSpinner();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[fill]" +
|
||||
"[fill]para" +
|
||||
"[grow,fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[grow]" +
|
||||
"[]"));
|
||||
|
||||
//---- label3 ----
|
||||
label3.setText("Fade:");
|
||||
add(label3, "cell 0 0");
|
||||
add(lineChartPanel, "cell 2 0 1 12,growy");
|
||||
add(fade1TextField, "cell 0 1");
|
||||
add(fade1ChartColor, "cell 1 1");
|
||||
add(fade2TextField, "cell 0 2");
|
||||
add(fade2ChartColor, "cell 1 2");
|
||||
|
||||
//---- label2 ----
|
||||
label2.setText("Material:");
|
||||
add(label2, "cell 0 3");
|
||||
add(material1TextField, "cell 0 4");
|
||||
add(material1ChartColor, "cell 1 4");
|
||||
add(material2TextField, "cell 0 5");
|
||||
add(material2ChartColor, "cell 1 5");
|
||||
|
||||
//---- material3TextField ----
|
||||
material3TextField.putClientProperty(FlatClientProperties.STYLE_CLASS, "large");
|
||||
add(material3TextField, "cell 0 6");
|
||||
add(material3ChartColor, "cell 1 6");
|
||||
|
||||
//---- material4TextField ----
|
||||
material4TextField.putClientProperty(FlatClientProperties.STYLE_CLASS, "large");
|
||||
add(material4TextField, "cell 0 7");
|
||||
add(material4ChartColor, "cell 1 7");
|
||||
|
||||
//---- label1 ----
|
||||
label1.setText("Minimal:");
|
||||
add(label1, "cell 0 8");
|
||||
add(minimalTextField, "cell 0 9");
|
||||
add(minimalChartColor, "cell 1 9");
|
||||
|
||||
//---- durationLabel ----
|
||||
durationLabel.setText("Duration:");
|
||||
add(durationLabel, "cell 0 11");
|
||||
|
||||
//---- durationField ----
|
||||
durationField.setModel(new SpinnerNumberModel(200, 0, null, 50));
|
||||
add(durationField, "cell 0 11");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel label3;
|
||||
private LineChartPanel lineChartPanel;
|
||||
private JTextField fade1TextField;
|
||||
private FlatAnimatorTest.JChartColor fade1ChartColor;
|
||||
private JTextField fade2TextField;
|
||||
private FlatAnimatorTest.JChartColor fade2ChartColor;
|
||||
private JLabel label2;
|
||||
private JTextField material1TextField;
|
||||
private FlatAnimatorTest.JChartColor material1ChartColor;
|
||||
private JTextField material2TextField;
|
||||
private FlatAnimatorTest.JChartColor material2ChartColor;
|
||||
private JTextField material3TextField;
|
||||
private FlatAnimatorTest.JChartColor material3ChartColor;
|
||||
private JTextField material4TextField;
|
||||
private FlatAnimatorTest.JChartColor material4ChartColor;
|
||||
private JLabel label1;
|
||||
private JTextField minimalTextField;
|
||||
private FlatAnimatorTest.JChartColor minimalChartColor;
|
||||
private JLabel durationLabel;
|
||||
private JSpinner durationField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class AnimatedMaterialBorder ---------------------------------------
|
||||
|
||||
/**
|
||||
* Experimental text field border that:
|
||||
* - animates focus indicator color and border width
|
||||
*/
|
||||
private class AnimatedFocusFadeBorder
|
||||
extends AbstractBorder
|
||||
implements AnimatedBorder
|
||||
{
|
||||
// needed because otherwise the empty paint method in superclass
|
||||
// javax.swing.border.AbstractBorder would be used
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
paintWithAnimation( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
FlatUIUtils.setRenderingHints( g );
|
||||
|
||||
// border width is 1 if not focused and 2 if focused
|
||||
float lw = UIScale.scale( 1 + animatedValue );
|
||||
|
||||
// paint border
|
||||
Color color = ColorFunctions.mix( Color.red, Color.lightGray, animatedValue );
|
||||
FlatUIUtils.paintOutlinedComponent( g, x, y, width, height, 0, 0, 0, lw, 0,
|
||||
null, color, null );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "fade" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
insets.top = insets.bottom = UIScale.scale( 3 );
|
||||
insets.left = insets.right = UIScale.scale( 7 );
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { FlatUIUtils.isPermanentFocusOwner( c ) ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnimationDuration() {
|
||||
return (Integer) durationField.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
//---- class AnimatedMaterialBorder ---------------------------------------
|
||||
|
||||
/**
|
||||
* Experimental text field border that:
|
||||
* - paint border only at bottom
|
||||
* - animates focus indicator at bottom
|
||||
*/
|
||||
private class AnimatedMaterialBorder
|
||||
extends AbstractBorder
|
||||
implements AnimatedBorder
|
||||
{
|
||||
// needed because otherwise the empty paint method in superclass
|
||||
// javax.swing.border.AbstractBorder would be used
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
paintWithAnimation( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
FlatUIUtils.setRenderingHints( g );
|
||||
|
||||
// use paintAtScale1x() for consistent line thickness when scaled
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||
float lh = (float) (UIScale.scale( 1f ) * scaleFactor);
|
||||
|
||||
g2d.setColor( Color.gray );
|
||||
g2d.fill( new Rectangle2D.Float( x2, y2 + height2 - lh, width2, lh ) );
|
||||
|
||||
if( animatedValue > 0 ) {
|
||||
lh = (float) (UIScale.scale( 2f ) * scaleFactor);
|
||||
int lw = Math.round( width2 * animatedValue );
|
||||
|
||||
g2d.setColor( Color.red );
|
||||
g2d.fill( new Rectangle2D.Float( x2 + (width2 - lw) / 2, y2 + height2 - lh, lw, lh ) );
|
||||
}
|
||||
} );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "material" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repaintDuringAnimation( Component c, int x, int y, int width, int height ) {
|
||||
// limit repaint to bottom border
|
||||
int lh = UIScale.scale( 2 );
|
||||
c.repaint( x, y + height - lh, width, lh );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
insets.top = insets.bottom = UIScale.scale( 3 );
|
||||
insets.left = insets.right = UIScale.scale( 7 );
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { FlatUIUtils.isPermanentFocusOwner( c ) ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnimationDuration() {
|
||||
return (Integer) durationField.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
//---- class AnimatedMaterialLabeledBorder --------------------------------
|
||||
|
||||
/**
|
||||
* Experimental text field border that:
|
||||
* - paints a label above the text, or in center if text field is empty
|
||||
* - paint border only at bottom
|
||||
* - animates focus indicator at bottom
|
||||
*/
|
||||
private class AnimatedMaterialLabeledBorder
|
||||
extends AnimatedMaterialBorder
|
||||
{
|
||||
static final String LABEL_TEXT_KEY = "JTextField.labelText";
|
||||
|
||||
private static final float LABEL_FONT_SCALE = 0.75f;
|
||||
|
||||
@Override
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
super.paintAnimated( c, g, x, y, width, height, animatedValues );
|
||||
|
||||
float animatedValue = animatedValues[0];
|
||||
JComponent jc = (JComponent) c;
|
||||
String label = (String) jc.getClientProperty( LABEL_TEXT_KEY );
|
||||
if( label == null )
|
||||
return;
|
||||
|
||||
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
||||
int labelFontHeight = Math.round( fm.getHeight() * LABEL_FONT_SCALE );
|
||||
|
||||
int tx = UIScale.scale( 7 );
|
||||
int ty = y + labelFontHeight - UIScale.scale( 2 );
|
||||
float sf = LABEL_FONT_SCALE;
|
||||
|
||||
if( ((JTextField)c).getDocument().getLength() == 0 ) {
|
||||
// paint label in center of text field if it is empty
|
||||
int ty2 = ((height - fm.getHeight()) / 2) + labelFontHeight;
|
||||
ty += (ty2 - ty) * (1 - animatedValue);
|
||||
sf += (1 - LABEL_FONT_SCALE) * (1 - animatedValue);
|
||||
}
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
g2.translate( tx, ty );
|
||||
g2.scale( sf, sf );
|
||||
g2.setColor( ColorFunctions.mix( Color.red, Color.gray, animatedValue ) );
|
||||
|
||||
FlatUIUtils.drawString( jc, g2, label, 0, 0 );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repaintDuringAnimation( Component c, int x, int y, int width, int height ) {
|
||||
c.repaint( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
super.getBorderInsets( c, insets );
|
||||
|
||||
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
||||
int labelFontHeight = Math.round( fm.getHeight() * LABEL_FONT_SCALE );
|
||||
insets.top = labelFontHeight;
|
||||
insets.bottom = UIScale.scale( 5 );
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class AnimatedMinimalTestBorder ------------------------------------
|
||||
|
||||
/**
|
||||
* Minimal example for an animated border.
|
||||
*/
|
||||
private class AnimatedMinimalTestBorder
|
||||
implements AnimatedBorder
|
||||
{
|
||||
@Override
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
int lh = UIScale.scale( 2 );
|
||||
|
||||
g.setColor( Color.blue );
|
||||
g.fillRect( x, y + height - lh, Math.round( width * animatedValue ), lh );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "minimal" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { FlatUIUtils.isPermanentFocusOwner( c ) ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnimationDuration() {
|
||||
return (Integer) durationField.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c ) {
|
||||
return UIScale.scale( new Insets( 3, 7, 3, 7 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBorderOpaque() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
JFDML JFormDesigner: "8.3" 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": "[fill][fill]para[grow,fill]"
|
||||
"$rowConstraints": "[][][]para[][][][][]para[][][grow][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"text": "Fade:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.LineChartPanel" ) {
|
||||
name: "lineChartPanel"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0 1 12,growy"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "fade1TextField"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "fade1ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "fade2TextField"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "fade2ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label2"
|
||||
"text": "Material:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "material1TextField"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "material1ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "material2TextField"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "material2ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "material3TextField"
|
||||
"$client.FlatLaf.styleClass": "large"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "material3ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "material4TextField"
|
||||
"$client.FlatLaf.styleClass": "large"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "material4ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label1"
|
||||
"text": "Minimal:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 8"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "minimalTextField"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "minimalChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "durationLabel"
|
||||
"text": "Duration:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 11"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JSpinner" ) {
|
||||
name: "durationField"
|
||||
"model": new javax.swing.SpinnerNumberModel {
|
||||
minimum: 0
|
||||
stepSize: 50
|
||||
value: 200
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 11"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 725, 465 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,14 @@ package com.formdev.flatlaf.testing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.icons.FlatAnimatedIcon;
|
||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -33,6 +34,15 @@ import net.miginfocom.swing.*;
|
||||
public class FlatAnimatedIconTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
private static final Color CHART_RADIO_BUTTON_1 = Color.blue;
|
||||
private static final Color CHART_RADIO_BUTTON_2 = Color.red;
|
||||
private static final Color CHART_RADIO_BUTTON_3 = Color.green;
|
||||
private static final Color CHART_CHECK_BOX_1 = Color.magenta;
|
||||
private static final Color CHART_CHECK_BOX_2 = Color.orange;
|
||||
private static final Color[] CHART_SWITCH_EX = { Color.red, Color.green, Color.blue };
|
||||
|
||||
private static final String CHART_COLOR_KEY = "chartColor";
|
||||
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatAnimatedIconTest" );
|
||||
@@ -49,16 +59,36 @@ public class FlatAnimatedIconTest
|
||||
radioButton3.setIcon( radioIcon );
|
||||
|
||||
checkBox1.setIcon( new AnimatedSwitchIcon() );
|
||||
checkBox3.setIcon( new AnimatedSwitchIconEx() );
|
||||
checkBox2.setIcon( new AnimatedMinimalTestIcon() );
|
||||
|
||||
radioButton1.putClientProperty( CHART_COLOR_KEY, CHART_RADIO_BUTTON_1 );
|
||||
radioButton2.putClientProperty( CHART_COLOR_KEY, CHART_RADIO_BUTTON_2 );
|
||||
radioButton3.putClientProperty( CHART_COLOR_KEY, CHART_RADIO_BUTTON_3 );
|
||||
checkBox1.putClientProperty( CHART_COLOR_KEY, CHART_CHECK_BOX_1 );
|
||||
checkBox2.putClientProperty( CHART_COLOR_KEY, CHART_CHECK_BOX_2 );
|
||||
|
||||
radioButton1ChartColor.setForeground( CHART_RADIO_BUTTON_1 );
|
||||
radioButton2ChartColor.setForeground( CHART_RADIO_BUTTON_2 );
|
||||
radioButton3ChartColor.setForeground( CHART_RADIO_BUTTON_3 );
|
||||
checkBox1ChartColor.setForeground( CHART_CHECK_BOX_1 );
|
||||
checkBox2ChartColor.setForeground( CHART_CHECK_BOX_2 );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
radioButton1 = new JRadioButton();
|
||||
radioButton1ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
lineChartPanel = new LineChartPanel();
|
||||
radioButton2 = new JRadioButton();
|
||||
radioButton2ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
radioButton3 = new JRadioButton();
|
||||
radioButton3ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
checkBox1 = new JCheckBox();
|
||||
checkBox1ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
checkBox3 = new JCheckBox();
|
||||
checkBox2 = new JCheckBox();
|
||||
checkBox2ChartColor = new FlatAnimatorTest.JChartColor();
|
||||
durationLabel = new JLabel();
|
||||
durationField = new JSpinner();
|
||||
|
||||
@@ -66,14 +96,16 @@ public class FlatAnimatedIconTest
|
||||
setLayout(new MigLayout(
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]para" +
|
||||
"[fill]",
|
||||
"[]" +
|
||||
"[fill]para" +
|
||||
"[grow,fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[grow]" +
|
||||
"[]"));
|
||||
|
||||
@@ -81,30 +113,40 @@ public class FlatAnimatedIconTest
|
||||
radioButton1.setText("radio 1");
|
||||
radioButton1.setSelected(true);
|
||||
add(radioButton1, "cell 0 0");
|
||||
add(radioButton1ChartColor, "cell 1 0");
|
||||
add(lineChartPanel, "cell 2 0 1 8,growy");
|
||||
|
||||
//---- radioButton2 ----
|
||||
radioButton2.setText("radio 2");
|
||||
add(radioButton2, "cell 0 1");
|
||||
add(radioButton2ChartColor, "cell 1 1");
|
||||
|
||||
//---- radioButton3 ----
|
||||
radioButton3.setText("radio 3");
|
||||
add(radioButton3, "cell 0 2");
|
||||
add(radioButton3ChartColor, "cell 1 2");
|
||||
|
||||
//---- checkBox1 ----
|
||||
checkBox1.setText("switch");
|
||||
add(checkBox1, "cell 0 3");
|
||||
add(checkBox1ChartColor, "cell 1 3");
|
||||
|
||||
//---- checkBox3 ----
|
||||
checkBox3.setText("switch ex");
|
||||
add(checkBox3, "cell 0 4");
|
||||
|
||||
//---- checkBox2 ----
|
||||
checkBox2.setText("minimal");
|
||||
add(checkBox2, "cell 0 4");
|
||||
add(checkBox2, "cell 0 5");
|
||||
add(checkBox2ChartColor, "cell 1 5");
|
||||
|
||||
//---- durationLabel ----
|
||||
durationLabel.setText("Duration:");
|
||||
add(durationLabel, "cell 0 6 2 1");
|
||||
add(durationLabel, "cell 0 7 2 1");
|
||||
|
||||
//---- durationField ----
|
||||
durationField.setModel(new SpinnerNumberModel(200, 100, null, 50));
|
||||
add(durationField, "cell 0 6 2 1");
|
||||
durationField.setModel(new SpinnerNumberModel(200, 0, null, 50));
|
||||
add(durationField, "cell 0 7 2 1");
|
||||
|
||||
//---- buttonGroup1 ----
|
||||
ButtonGroup buttonGroup1 = new ButtonGroup();
|
||||
@@ -116,10 +158,17 @@ public class FlatAnimatedIconTest
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JRadioButton radioButton1;
|
||||
private FlatAnimatorTest.JChartColor radioButton1ChartColor;
|
||||
private LineChartPanel lineChartPanel;
|
||||
private JRadioButton radioButton2;
|
||||
private FlatAnimatorTest.JChartColor radioButton2ChartColor;
|
||||
private JRadioButton radioButton3;
|
||||
private FlatAnimatorTest.JChartColor radioButton3ChartColor;
|
||||
private JCheckBox checkBox1;
|
||||
private FlatAnimatorTest.JChartColor checkBox1ChartColor;
|
||||
private JCheckBox checkBox3;
|
||||
private JCheckBox checkBox2;
|
||||
private FlatAnimatorTest.JChartColor checkBox2ChartColor;
|
||||
private JLabel durationLabel;
|
||||
private JSpinner durationField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
@@ -146,7 +195,8 @@ public class FlatAnimatedIconTest
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||
public void paintIconAnimated( Component c, Graphics2D g, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
Color color = ColorFunctions.mix( onColor, offColor, animatedValue );
|
||||
|
||||
// border
|
||||
@@ -162,12 +212,17 @@ public class FlatAnimatedIconTest
|
||||
float dotDiameter = DOT_SIZE * animatedValue;
|
||||
float xy = (SIZE - dotDiameter) / 2f;
|
||||
g.setColor( color );
|
||||
((Graphics2D)g).fill( new Ellipse2D.Float( xy, xy, dotDiameter, dotDiameter ) );
|
||||
g.fill( new Ellipse2D.Float( xy, xy, dotDiameter, dotDiameter ) );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "radio" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue( Component c ) {
|
||||
return ((JRadioButton)c).isSelected() ? 1 : 0;
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { ((JRadioButton)c).isSelected() ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,7 +233,7 @@ public class FlatAnimatedIconTest
|
||||
|
||||
//---- class AnimatedSwitchIcon -------------------------------------------
|
||||
|
||||
public class AnimatedSwitchIcon
|
||||
private class AnimatedSwitchIcon
|
||||
extends FlatAnimatedIcon
|
||||
{
|
||||
private final Color offColor = Color.lightGray;
|
||||
@@ -189,22 +244,113 @@ public class FlatAnimatedIconTest
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||
public void paintIconAnimated( Component c, Graphics2D g, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
Color color = ColorFunctions.mix( onColor, offColor, animatedValue );
|
||||
|
||||
// paint track
|
||||
g.setColor( color );
|
||||
g.fillRoundRect( x, y, width, height, height, height );
|
||||
g.fillRoundRect( 0, 0, width, height, height, height );
|
||||
|
||||
// paint thumb
|
||||
int thumbSize = height - 4;
|
||||
float thumbX = x + 2 + ((width - 4 - thumbSize) * animatedValue);
|
||||
int thumbY = y + 2;
|
||||
float thumbX = 2 + ((width - 4 - thumbSize) * animatedValue);
|
||||
int thumbY = 2;
|
||||
g.setColor( Color.white );
|
||||
((Graphics2D)g).fill( new Ellipse2D.Float( thumbX, thumbY, thumbSize, thumbSize ) );
|
||||
g.fill( new Ellipse2D.Float( thumbX, thumbY, thumbSize, thumbSize ) );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "switch" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue( Component c ) {
|
||||
return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { ((AbstractButton)c).isSelected() ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAnimationDuration() {
|
||||
return (Integer) durationField.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
//---- class AnimatedSwitchIconEx -----------------------------------------
|
||||
|
||||
private static final int HW = 8;
|
||||
|
||||
private class AnimatedSwitchIconEx
|
||||
extends FlatAnimatedIcon
|
||||
{
|
||||
private final Color offColor = Color.lightGray;
|
||||
private final Color onColor = Color.red;
|
||||
private final Color hoverColor = new Color( 0x4400cc00, true );
|
||||
private final Color pressedColor = new Color( 0x440000cc, true );
|
||||
|
||||
public AnimatedSwitchIconEx() {
|
||||
super( 28 + HW, 16 + HW, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIconAnimated( Component c, Graphics2D g, float[] animatedValues ) {
|
||||
Color color = ColorFunctions.mix( onColor, offColor, animatedValues[0] );
|
||||
|
||||
int hw2 = HW / 2;
|
||||
int x = hw2;
|
||||
int y = hw2;
|
||||
int width = this.width - HW;
|
||||
int height = this.height - HW;
|
||||
|
||||
// paint track
|
||||
g.setColor( color );
|
||||
g.fillRoundRect( x, y, width, height, height, height );
|
||||
|
||||
// paint thumb
|
||||
int thumbSize = height - 4;
|
||||
float thumbX = x + 2 + ((width - 4 - thumbSize) * animatedValues[0]);
|
||||
int thumbY = y + 2;
|
||||
g.setColor( Color.white );
|
||||
g.fill( new Ellipse2D.Float( thumbX, thumbY, thumbSize, thumbSize ) );
|
||||
|
||||
// paint hover
|
||||
if( animatedValues[1] > 0 ) {
|
||||
g.setColor( hoverColor );
|
||||
paintHoverOrPressed( g, thumbX, thumbY, thumbSize, animatedValues[1] );
|
||||
}
|
||||
|
||||
// paint pressed
|
||||
if( animatedValues[2] > 0 ) {
|
||||
g.setColor( pressedColor );
|
||||
paintHoverOrPressed( g, thumbX, thumbY, thumbSize, animatedValues[2] );
|
||||
}
|
||||
|
||||
for( int i = 0; i < animatedValues.length; i++ ) {
|
||||
float animatedValue = animatedValues[i];
|
||||
if( animatedValue != 0 && animatedValue != 1 )
|
||||
lineChartPanel.addValue( CHART_SWITCH_EX[i], animatedValue, Integer.MIN_VALUE, "switch ex" );
|
||||
}
|
||||
}
|
||||
|
||||
private void paintHoverOrPressed( Graphics2D g, float thumbX, int thumbY, int thumbSize, float animatedValue ) {
|
||||
float hw = (HW + 4) * animatedValue;
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Ellipse2D.Float( thumbX - (hw / 2), thumbY - (hw / 2),
|
||||
thumbSize + hw, thumbSize + hw ), false );
|
||||
path.append( new Ellipse2D.Float( thumbX, thumbY, thumbSize, thumbSize ), false );
|
||||
g.fill( path );
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
AbstractButton b = (AbstractButton) c;
|
||||
ButtonModel bm = b.getModel();
|
||||
|
||||
return new float[] {
|
||||
b.isSelected() ? 1 : 0,
|
||||
bm.isRollover() ? 1 : 0,
|
||||
bm.isPressed() ? 1 : 0,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,27 +369,31 @@ public class FlatAnimatedIconTest
|
||||
{
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return 100;
|
||||
return UIScale.scale( 50 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return 20;
|
||||
return UIScale.scale( 16 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
|
||||
int w = getIconWidth();
|
||||
int h = getIconHeight();
|
||||
public void paintAnimated( Component c, Graphics2D g, int x, int y, int width, int height, float[] animatedValues ) {
|
||||
float animatedValue = animatedValues[0];
|
||||
|
||||
g.setColor( Color.red );
|
||||
g.drawRect( x, y, w - 1, h - 1 );
|
||||
g.fillRect( x, y, Math.round( w * animatedValue ), h );
|
||||
g.drawRect( x, y, width - 1, height - 1 );
|
||||
g.fillRect( x, y, Math.round( width * animatedValue ), height );
|
||||
|
||||
if( animatedValue != 0 && animatedValue != 1 ) {
|
||||
Color chartColor = (Color) ((JComponent)c).getClientProperty( CHART_COLOR_KEY );
|
||||
lineChartPanel.addValue( chartColor, animatedValue, Integer.MIN_VALUE, "minimal" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue( Component c ) {
|
||||
return ((AbstractButton)c).isSelected() ? 1 : 0;
|
||||
public float[] getAnimatableValues( Component c ) {
|
||||
return new float[] { ((AbstractButton)c).isSelected() ? 1 : 0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[]para[fill]"
|
||||
"$rowConstraints": "[][][]para[][][grow][]"
|
||||
"$columnConstraints": "[][fill]para[grow,fill]"
|
||||
"$rowConstraints": "[][][]para[][][][grow][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
@@ -17,6 +17,16 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "radioButton1ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.LineChartPanel" ) {
|
||||
name: "lineChartPanel"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0 1 8,growy"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
name: "radioButton2"
|
||||
"text": "radio 2"
|
||||
@@ -24,6 +34,11 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "radioButton2ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
name: "radioButton3"
|
||||
"text": "radio 3"
|
||||
@@ -31,37 +46,58 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "radioButton3ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "checkBox1"
|
||||
"text": "switch"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "checkBox1ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "checkBox3"
|
||||
"text": "switch ex"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "checkBox2"
|
||||
"text": "minimal"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "checkBox2ChartColor"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "durationLabel"
|
||||
"text": "Duration:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6 2 1"
|
||||
"value": "cell 0 7 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JSpinner" ) {
|
||||
name: "durationField"
|
||||
"model": new javax.swing.SpinnerNumberModel {
|
||||
minimum: 100
|
||||
minimum: 0
|
||||
stepSize: 50
|
||||
value: 200
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6 2 1"
|
||||
"value": "cell 0 7 2 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 415, 350 )
|
||||
"size": new java.awt.Dimension( 810, 350 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "buttonGroup1"
|
||||
|
||||
@@ -20,6 +20,8 @@ import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.util.Animator;
|
||||
import com.formdev.flatlaf.util.CubicBezierEasing;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import com.formdev.flatlaf.util.Animator.Interpolator;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -28,8 +30,13 @@ import net.miginfocom.swing.*;
|
||||
public class FlatAnimatorTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
private static final Color CHART_LINEAR = Color.blue;
|
||||
private static final Color CHART_EASE_IN_OUT = Color.magenta;
|
||||
private static final Color CHART_STANDARD_EASING = Color.red;
|
||||
|
||||
private Animator linearAnimator;
|
||||
private Animator easeInOutAnimator;
|
||||
private Animator standardEasingAnimator;
|
||||
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
@@ -40,85 +47,132 @@ public class FlatAnimatorTest
|
||||
|
||||
FlatAnimatorTest() {
|
||||
initComponents();
|
||||
|
||||
linearChartColor.setForeground( CHART_LINEAR );
|
||||
easeInOutChartColor.setForeground( CHART_EASE_IN_OUT );
|
||||
standardEasingChartColor.setForeground( CHART_STANDARD_EASING );
|
||||
}
|
||||
|
||||
private void start() {
|
||||
startLinear();
|
||||
startEaseInOut();
|
||||
linearAnimator = start( linearAnimator, null, linearScrollBar, CHART_LINEAR );
|
||||
easeInOutAnimator = start( easeInOutAnimator, CubicBezierEasing.EASE_IN_OUT, easeInOutScrollBar, CHART_EASE_IN_OUT );
|
||||
standardEasingAnimator = start( standardEasingAnimator, CubicBezierEasing.STANDARD_EASING, standardEasingScrollBar, CHART_STANDARD_EASING );
|
||||
}
|
||||
|
||||
private void startLinear() {
|
||||
if( linearAnimator != null ) {
|
||||
linearAnimator.stop();
|
||||
linearAnimator.start();
|
||||
private Animator start( Animator animator, Interpolator interpolator, JScrollBar scrollBar, Color chartColor ) {
|
||||
if( animator != null ) {
|
||||
animator.stop();
|
||||
animator.start();
|
||||
} else {
|
||||
linearAnimator = new Animator( 1000, fraction -> {
|
||||
linearScrollBar.setValue( Math.round( fraction * linearScrollBar.getMaximum() ) );
|
||||
animator = new Animator( 1000, fraction -> {
|
||||
scrollBar.setValue( Math.round( fraction * scrollBar.getMaximum() ) );
|
||||
lineChartPanel.addValue( chartColor, fraction, Integer.MIN_VALUE, "animator" );
|
||||
} );
|
||||
linearAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void startEaseInOut() {
|
||||
if( easeInOutAnimator != null ) {
|
||||
easeInOutAnimator.stop();
|
||||
easeInOutAnimator.start();
|
||||
} else {
|
||||
easeInOutAnimator = new Animator( 1000, fraction -> {
|
||||
easeInOutScrollBar.setValue( Math.round( fraction * easeInOutScrollBar.getMaximum() ) );
|
||||
} );
|
||||
easeInOutAnimator.setInterpolator( CubicBezierEasing.EASE_IN_OUT );
|
||||
easeInOutAnimator.start();
|
||||
animator.setInterpolator( interpolator );
|
||||
animator.start();
|
||||
}
|
||||
return animator;
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel label1 = new JLabel();
|
||||
linearLabel = new JLabel();
|
||||
linearChartColor = new FlatAnimatorTest.JChartColor();
|
||||
linearScrollBar = new JScrollBar();
|
||||
JLabel label2 = new JLabel();
|
||||
easeInOutLabel = new JLabel();
|
||||
easeInOutChartColor = new FlatAnimatorTest.JChartColor();
|
||||
easeInOutScrollBar = new JScrollBar();
|
||||
standardEasingLabel = new JLabel();
|
||||
standardEasingChartColor = new FlatAnimatorTest.JChartColor();
|
||||
standardEasingScrollBar = new JScrollBar();
|
||||
startButton = new JButton();
|
||||
lineChartPanel = new LineChartPanel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[fill]" +
|
||||
"[fill]" +
|
||||
"[grow,fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[400,grow,fill]"));
|
||||
|
||||
//---- label1 ----
|
||||
label1.setText("Linear:");
|
||||
add(label1, "cell 0 0");
|
||||
//---- linearLabel ----
|
||||
linearLabel.setText("Linear:");
|
||||
add(linearLabel, "cell 0 0");
|
||||
add(linearChartColor, "cell 1 0");
|
||||
|
||||
//---- linearScrollBar ----
|
||||
linearScrollBar.setOrientation(Adjustable.HORIZONTAL);
|
||||
linearScrollBar.setBlockIncrement(1);
|
||||
add(linearScrollBar, "cell 1 0");
|
||||
add(linearScrollBar, "cell 2 0");
|
||||
|
||||
//---- label2 ----
|
||||
label2.setText("Ease in out:");
|
||||
add(label2, "cell 0 1");
|
||||
//---- easeInOutLabel ----
|
||||
easeInOutLabel.setText("Ease in out:");
|
||||
add(easeInOutLabel, "cell 0 1");
|
||||
add(easeInOutChartColor, "cell 1 1");
|
||||
|
||||
//---- easeInOutScrollBar ----
|
||||
easeInOutScrollBar.setOrientation(Adjustable.HORIZONTAL);
|
||||
easeInOutScrollBar.setBlockIncrement(1);
|
||||
add(easeInOutScrollBar, "cell 1 1");
|
||||
add(easeInOutScrollBar, "cell 2 1");
|
||||
|
||||
//---- standardEasingLabel ----
|
||||
standardEasingLabel.setText("Standard easing:");
|
||||
add(standardEasingLabel, "cell 0 2");
|
||||
add(standardEasingChartColor, "cell 1 2");
|
||||
|
||||
//---- standardEasingScrollBar ----
|
||||
standardEasingScrollBar.setOrientation(Adjustable.HORIZONTAL);
|
||||
standardEasingScrollBar.setBlockIncrement(1);
|
||||
add(standardEasingScrollBar, "cell 2 2");
|
||||
|
||||
//---- startButton ----
|
||||
startButton.setText("Start");
|
||||
startButton.addActionListener(e -> start());
|
||||
add(startButton, "cell 0 2");
|
||||
add(startButton, "cell 0 3");
|
||||
add(lineChartPanel, "cell 0 4 3 1");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel linearLabel;
|
||||
private FlatAnimatorTest.JChartColor linearChartColor;
|
||||
private JScrollBar linearScrollBar;
|
||||
private JLabel easeInOutLabel;
|
||||
private FlatAnimatorTest.JChartColor easeInOutChartColor;
|
||||
private JScrollBar easeInOutScrollBar;
|
||||
private JLabel standardEasingLabel;
|
||||
private FlatAnimatorTest.JChartColor standardEasingChartColor;
|
||||
private JScrollBar standardEasingScrollBar;
|
||||
private JButton startButton;
|
||||
private LineChartPanel lineChartPanel;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class JChartColor --------------------------------------------------
|
||||
|
||||
static class JChartColor
|
||||
extends JComponent
|
||||
{
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension( UIScale.scale( 24 ), UIScale.scale( 12 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
g.setColor( getForeground() );
|
||||
g.fillRect( 0, 0, UIScale.scale( 24 ), UIScale.scale( 12 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "14.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -8,16 +8,27 @@ new FormModel {
|
||||
}
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[fill][grow,fill]"
|
||||
"$rowConstraints": "[][][]"
|
||||
"$columnConstraints": "[fill][fill][grow,fill]"
|
||||
"$rowConstraints": "[][][][]para[400,grow,fill]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label1"
|
||||
name: "linearLabel"
|
||||
"text": "Linear:"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "linearChartColor"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JScrollBar" ) {
|
||||
name: "linearScrollBar"
|
||||
"orientation": 0
|
||||
@@ -26,14 +37,25 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label2"
|
||||
name: "easeInOutLabel"
|
||||
"text": "Ease in out:"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "easeInOutChartColor"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JScrollBar" ) {
|
||||
name: "easeInOutScrollBar"
|
||||
"orientation": 0
|
||||
@@ -42,7 +64,34 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "standardEasingLabel"
|
||||
"text": "Standard easing:"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatAnimatorTest$JChartColor" ) {
|
||||
name: "standardEasingChartColor"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JScrollBar" ) {
|
||||
name: "standardEasingScrollBar"
|
||||
"orientation": 0
|
||||
"blockIncrement": 1
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "startButton"
|
||||
@@ -52,11 +101,19 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "start", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.LineChartPanel" ) {
|
||||
name: "lineChartPanel"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 415, 350 )
|
||||
"size": new java.awt.Dimension( 625, 625 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,17 +198,17 @@ public class FlatComponentStateTest
|
||||
|
||||
//---- label11 ----
|
||||
label11.setText("JButton");
|
||||
label11.setFont(label11.getFont().deriveFont(label11.getFont().getSize() + 4f));
|
||||
label11.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label11, "cell 1 0 2 1");
|
||||
|
||||
//---- label12 ----
|
||||
label12.setText("JToggleButton");
|
||||
label12.setFont(label12.getFont().deriveFont(label12.getFont().getSize() + 4f));
|
||||
label12.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label12, "cell 5 0 3 1");
|
||||
|
||||
//---- label32 ----
|
||||
label32.setText("Help Button");
|
||||
label32.setFont(label32.getFont().deriveFont(label32.getFont().getSize() + 4f));
|
||||
label32.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label32, "cell 9 0 2 1");
|
||||
|
||||
//---- label5 ----
|
||||
@@ -513,12 +513,12 @@ public class FlatComponentStateTest
|
||||
|
||||
//---- label22 ----
|
||||
label22.setText("JCheckBox");
|
||||
label22.setFont(label22.getFont().deriveFont(label22.getFont().getSize() + 4f));
|
||||
label22.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label22, "cell 1 8 2 1");
|
||||
|
||||
//---- label27 ----
|
||||
label27.setText("JRadioButton");
|
||||
label27.setFont(label27.getFont().deriveFont(label27.getFont().getSize() + 4f));
|
||||
label27.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label27, "cell 5 8 2 1");
|
||||
|
||||
//---- label23 ----
|
||||
|
||||
@@ -12,21 +12,21 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label11"
|
||||
"text": "JButton"
|
||||
"font": &SwingDerivedFont0 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label12"
|
||||
"text": "JToggleButton"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 0 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label32"
|
||||
"text": "Help Button"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 9 0 2 1"
|
||||
} )
|
||||
@@ -447,14 +447,14 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label22"
|
||||
"text": "JCheckBox"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 8 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label27"
|
||||
"text": "JRadioButton"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 8 2 1"
|
||||
} )
|
||||
|
||||
@@ -1621,6 +1621,7 @@ public class FlatComponentsTest
|
||||
// customRenderer.setBorder( new LineBorder( Color.red ) );
|
||||
// comboBox1.setRenderer( customRenderer );
|
||||
// comboBox3.setRenderer( customRenderer );
|
||||
// comboBox5.setRenderer( new DefaultListCellRenderer() );
|
||||
|
||||
// for testing issue #382
|
||||
// spinner1.setModel( new SpinnerNumberModel( 0, null, 100, 1 ) );
|
||||
|
||||
@@ -50,6 +50,8 @@ public class FlatContainerTest
|
||||
public FlatContainerTest() {
|
||||
initComponents();
|
||||
|
||||
tabTypeComboBox.init( TabType.class, true );
|
||||
|
||||
tabPlacementField.init( TabPlacement.class, true );
|
||||
iconPlacementField.init( TabIconPlacement.class, true );
|
||||
tabsPopupPolicyField.init( TabsPopupPolicy.class, true );
|
||||
@@ -310,6 +312,12 @@ public class FlatContainerTest
|
||||
tabbedPane.setTabWidthMode( value );
|
||||
}
|
||||
|
||||
private void tabTypeChanged() {
|
||||
TabType value = tabTypeComboBox.getSelectedValue();
|
||||
for( FlatTabbedPane tabbedPane : allTabbedPanes )
|
||||
tabbedPane.setTabType( value );
|
||||
}
|
||||
|
||||
private void tabBackForegroundChanged() {
|
||||
for( JTabbedPane tabbedPane : allTabbedPanes )
|
||||
tabBackForegroundChanged( tabbedPane );
|
||||
@@ -491,6 +499,8 @@ public class FlatContainerTest
|
||||
tabAlignmentField = new FlatTestEnumComboBox<>();
|
||||
JLabel tabWidthModeLabel = new JLabel();
|
||||
tabWidthModeField = new FlatTestEnumComboBox<>();
|
||||
JLabel tabTypeLabel = new JLabel();
|
||||
tabTypeComboBox = new FlatTestEnumComboBox<>();
|
||||
leadingComponentCheckBox = new JCheckBox();
|
||||
customBorderCheckBox = new JCheckBox();
|
||||
tabAreaInsetsCheckBox = new JCheckBox();
|
||||
@@ -619,6 +629,7 @@ public class FlatContainerTest
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
@@ -739,75 +750,83 @@ public class FlatContainerTest
|
||||
tabWidthModeField.addActionListener(e -> tabWidthModeChanged());
|
||||
tabbedPaneControlPanel.add(tabWidthModeField, "cell 2 5");
|
||||
|
||||
//---- tabTypeLabel ----
|
||||
tabTypeLabel.setText("Tab type:");
|
||||
tabbedPaneControlPanel.add(tabTypeLabel, "cell 0 6");
|
||||
|
||||
//---- tabTypeComboBox ----
|
||||
tabTypeComboBox.addActionListener(e -> tabTypeChanged());
|
||||
tabbedPaneControlPanel.add(tabTypeComboBox, "cell 1 6");
|
||||
|
||||
//---- leadingComponentCheckBox ----
|
||||
leadingComponentCheckBox.setText("Leading component");
|
||||
leadingComponentCheckBox.addActionListener(e -> leadingComponentChanged());
|
||||
tabbedPaneControlPanel.add(leadingComponentCheckBox, "cell 0 6");
|
||||
tabbedPaneControlPanel.add(leadingComponentCheckBox, "cell 0 7");
|
||||
|
||||
//---- customBorderCheckBox ----
|
||||
customBorderCheckBox.setText("Custom border");
|
||||
customBorderCheckBox.addActionListener(e -> customBorderChanged());
|
||||
tabbedPaneControlPanel.add(customBorderCheckBox, "cell 1 6");
|
||||
tabbedPaneControlPanel.add(customBorderCheckBox, "cell 1 7");
|
||||
|
||||
//---- tabAreaInsetsCheckBox ----
|
||||
tabAreaInsetsCheckBox.setText("Tab area insets (5,5,10,10)");
|
||||
tabAreaInsetsCheckBox.addActionListener(e -> tabAreaInsetsChanged());
|
||||
tabbedPaneControlPanel.add(tabAreaInsetsCheckBox, "cell 2 6");
|
||||
tabbedPaneControlPanel.add(tabAreaInsetsCheckBox, "cell 2 7");
|
||||
|
||||
//---- trailingComponentCheckBox ----
|
||||
trailingComponentCheckBox.setText("Trailing component");
|
||||
trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged());
|
||||
tabbedPaneControlPanel.add(trailingComponentCheckBox, "cell 0 7");
|
||||
tabbedPaneControlPanel.add(trailingComponentCheckBox, "cell 0 8");
|
||||
|
||||
//---- hasFullBorderCheckBox ----
|
||||
hasFullBorderCheckBox.setText("Show content border");
|
||||
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
|
||||
tabbedPaneControlPanel.add(hasFullBorderCheckBox, "cell 1 7,alignx left,growx 0");
|
||||
tabbedPaneControlPanel.add(hasFullBorderCheckBox, "cell 1 8,alignx left,growx 0");
|
||||
|
||||
//---- smallerTabHeightCheckBox ----
|
||||
smallerTabHeightCheckBox.setText("Smaller tab height (26)");
|
||||
smallerTabHeightCheckBox.addActionListener(e -> smallerTabHeightChanged());
|
||||
tabbedPaneControlPanel.add(smallerTabHeightCheckBox, "cell 2 7");
|
||||
tabbedPaneControlPanel.add(smallerTabHeightCheckBox, "cell 2 8");
|
||||
|
||||
//---- minimumTabWidthCheckBox ----
|
||||
minimumTabWidthCheckBox.setText("Minimum tab width (100)");
|
||||
minimumTabWidthCheckBox.addActionListener(e -> minimumTabWidthChanged());
|
||||
tabbedPaneControlPanel.add(minimumTabWidthCheckBox, "cell 0 8");
|
||||
tabbedPaneControlPanel.add(minimumTabWidthCheckBox, "cell 0 9");
|
||||
|
||||
//---- hideContentSeparatorCheckBox ----
|
||||
hideContentSeparatorCheckBox.setText("Hide content separator");
|
||||
hideContentSeparatorCheckBox.addActionListener(e -> hideContentSeparatorChanged());
|
||||
tabbedPaneControlPanel.add(hideContentSeparatorCheckBox, "cell 1 8");
|
||||
tabbedPaneControlPanel.add(hideContentSeparatorCheckBox, "cell 1 9");
|
||||
|
||||
//---- smallerInsetsCheckBox ----
|
||||
smallerInsetsCheckBox.setText("Smaller tab insets (2,2,2,2)");
|
||||
smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged());
|
||||
tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 8");
|
||||
tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 9");
|
||||
|
||||
//---- maximumTabWidthCheckBox ----
|
||||
maximumTabWidthCheckBox.setText("Maximum tab width (60)");
|
||||
maximumTabWidthCheckBox.addActionListener(e -> maximumTabWidthChanged());
|
||||
tabbedPaneControlPanel.add(maximumTabWidthCheckBox, "cell 0 9");
|
||||
tabbedPaneControlPanel.add(maximumTabWidthCheckBox, "cell 0 10");
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 9");
|
||||
tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 10");
|
||||
|
||||
//---- secondTabWiderCheckBox ----
|
||||
secondTabWiderCheckBox.setText("Second Tab insets wider (4,20,4,20)");
|
||||
secondTabWiderCheckBox.addActionListener(e -> secondTabWiderChanged());
|
||||
tabbedPaneControlPanel.add(secondTabWiderCheckBox, "cell 2 9");
|
||||
tabbedPaneControlPanel.add(secondTabWiderCheckBox, "cell 2 10");
|
||||
|
||||
//---- hideTabAreaWithOneTabCheckBox ----
|
||||
hideTabAreaWithOneTabCheckBox.setText("Hide tab area with one tab");
|
||||
hideTabAreaWithOneTabCheckBox.addActionListener(e -> hideTabAreaWithOneTabChanged());
|
||||
tabbedPaneControlPanel.add(hideTabAreaWithOneTabCheckBox, "cell 1 10");
|
||||
tabbedPaneControlPanel.add(hideTabAreaWithOneTabCheckBox, "cell 1 11");
|
||||
|
||||
//---- customWheelScrollingCheckBox ----
|
||||
customWheelScrollingCheckBox.setText("Custom wheel scrolling");
|
||||
customWheelScrollingCheckBox.addActionListener(e -> customWheelScrollingChanged());
|
||||
tabbedPaneControlPanel.add(customWheelScrollingCheckBox, "cell 2 10");
|
||||
tabbedPaneControlPanel.add(customWheelScrollingCheckBox, "cell 2 11");
|
||||
}
|
||||
panel9.add(tabbedPaneControlPanel, cc.xywh(1, 11, 3, 1));
|
||||
}
|
||||
@@ -840,6 +859,7 @@ public class FlatContainerTest
|
||||
private FlatTestEnumComboBox<TabAreaAlignment> tabAreaAlignmentField;
|
||||
private FlatTestEnumComboBox<TabAlignment> tabAlignmentField;
|
||||
private FlatTestEnumComboBox<TabWidthMode> tabWidthModeField;
|
||||
private FlatTestEnumComboBox<TabType> tabTypeComboBox;
|
||||
private JCheckBox leadingComponentCheckBox;
|
||||
private JCheckBox customBorderCheckBox;
|
||||
private JCheckBox tabAreaInsetsCheckBox;
|
||||
|
||||
@@ -132,7 +132,7 @@ new FormModel {
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestFrame$NoRightToLeftPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3"
|
||||
"$columnConstraints": "[][fill][]"
|
||||
"$rowConstraints": "[center][][][][][]para[][]para[][][]"
|
||||
"$rowConstraints": "[center][][][][][][]para[][]para[][][]"
|
||||
} ) {
|
||||
name: "tabbedPaneControlPanel"
|
||||
"opaque": false
|
||||
@@ -372,6 +372,22 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabTypeLabel"
|
||||
"text": "Tab type:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumComboBox" ) {
|
||||
name: "tabTypeComboBox"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.typeParameters": "TabType"
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabTypeChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "leadingComponentCheckBox"
|
||||
"text": "Leading component"
|
||||
@@ -380,7 +396,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponentChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "customBorderCheckBox"
|
||||
@@ -390,7 +406,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customBorderChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6"
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "tabAreaInsetsCheckBox"
|
||||
@@ -400,7 +416,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAreaInsetsChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
"value": "cell 2 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "trailingComponentCheckBox"
|
||||
@@ -410,7 +426,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponentChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
"value": "cell 0 8"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "hasFullBorderCheckBox"
|
||||
@@ -420,7 +436,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7,alignx left,growx 0"
|
||||
"value": "cell 1 8,alignx left,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "smallerTabHeightCheckBox"
|
||||
@@ -430,7 +446,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerTabHeightChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
"value": "cell 2 8"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "minimumTabWidthCheckBox"
|
||||
@@ -440,7 +456,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "minimumTabWidthChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 8"
|
||||
"value": "cell 0 9"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "hideContentSeparatorCheckBox"
|
||||
@@ -450,7 +466,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideContentSeparatorChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 8"
|
||||
"value": "cell 1 9"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "smallerInsetsCheckBox"
|
||||
@@ -460,7 +476,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 8"
|
||||
"value": "cell 2 9"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "maximumTabWidthCheckBox"
|
||||
@@ -470,7 +486,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximumTabWidthChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9"
|
||||
"value": "cell 0 10"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTabSeparatorsCheckBox"
|
||||
@@ -480,7 +496,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9"
|
||||
"value": "cell 1 10"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "secondTabWiderCheckBox"
|
||||
@@ -490,7 +506,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabWiderChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 9"
|
||||
"value": "cell 2 10"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "hideTabAreaWithOneTabCheckBox"
|
||||
@@ -500,7 +516,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideTabAreaWithOneTabChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 10"
|
||||
"value": "cell 1 11"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "customWheelScrollingCheckBox"
|
||||
@@ -510,7 +526,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customWheelScrollingChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 10"
|
||||
"value": "cell 2 11"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
|
||||
"gridY": 11
|
||||
|
||||
@@ -34,7 +34,7 @@ public class FlatCustomBordersTest
|
||||
private static final Color RED = new Color( 0x60ff0000, true );
|
||||
private static final Color GREEN = new Color( 0x6000ff00, true );
|
||||
private static final Color MAGENTA = new Color( 0x60ff00ff, true );
|
||||
private static final Color ORANGE = new Color( 0x60ffc800, true );
|
||||
private static final Color BLUE = new Color( 0x300000ff, true );
|
||||
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
@@ -127,7 +127,7 @@ public class FlatCustomBordersTest
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private void applySpecialComboBoxRenderers() {
|
||||
BasicComboBoxRenderer sharedRenderer = new BasicComboBoxRenderer();
|
||||
sharedRenderer.setBorder( new LineBorder( ORANGE, UIScale.scale( 2 ) ) );
|
||||
sharedRenderer.setBorder( new LineBorder( BLUE, UIScale.scale( 2 ) ) );
|
||||
comboBox29.setRenderer( sharedRenderer );
|
||||
comboBox30.setRenderer( sharedRenderer );
|
||||
|
||||
@@ -160,7 +160,7 @@ public class FlatCustomBordersTest
|
||||
}
|
||||
|
||||
private void applyCustomComboBoxEditorBorder( JComboBox<String> comboBox ) {
|
||||
applyCustomComboBoxEditorBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
|
||||
applyCustomComboBoxEditorBorder( comboBox, new LineBorder( BLUE, UIScale.scale( 6 ) ) );
|
||||
}
|
||||
|
||||
private void applyCustomComboBoxEditorBorderWithIcon( JComboBox<String> comboBox ) {
|
||||
@@ -180,7 +180,7 @@ public class FlatCustomBordersTest
|
||||
}
|
||||
|
||||
private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox ) {
|
||||
applyCustomComboBoxRendererBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
|
||||
applyCustomComboBoxRendererBorder( comboBox, new LineBorder( BLUE, UIScale.scale( 6 ) ) );
|
||||
}
|
||||
|
||||
private void applyCustomComboBoxRendererBorderWithIcon( JComboBox<String> comboBox ) {
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.testing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatFontsTest
|
||||
extends JPanel
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatFontsTest" );
|
||||
frame.showFrame( FlatFontsTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatFontsTest() {
|
||||
initComponents();
|
||||
|
||||
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
|
||||
|
||||
TreeMap<String, TreeMap<String, Font>> familiesMap = new TreeMap<>();
|
||||
for( Font font : allFonts ) {
|
||||
TreeMap<String, Font> familyFontsMap = familiesMap.computeIfAbsent( font.getFamily(), key -> new TreeMap<>() );
|
||||
Font old = familyFontsMap.put( font.getName(), font );
|
||||
if( old != null ) {
|
||||
System.err.println( "Duplicate font name '" + font.getName() + "'" );
|
||||
System.err.println( " " + old );
|
||||
System.err.println( " " + font );
|
||||
}
|
||||
}
|
||||
|
||||
DefaultListModel<FontFamilyInfo> model = new DefaultListModel<>();
|
||||
for( Map.Entry<String, TreeMap<String, Font>> e : familiesMap.entrySet() ) {
|
||||
FontFamilyInfo info = new FontFamilyInfo();
|
||||
info.name = e.getKey();
|
||||
info.fonts = e.getValue();
|
||||
model.addElement( info );
|
||||
}
|
||||
familiesList.setModel( model );
|
||||
familiesList.setCellRenderer( new FontFamilyRenderer() );
|
||||
familiesList.setSelectedIndex( 0 );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
familiesList.requestFocusInWindow();
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
private void familyChanged() {
|
||||
previewFamilyNameLabel.setText( "" );
|
||||
previewPanel.removeAll();
|
||||
|
||||
FontFamilyInfo info = familiesList.getSelectedValue();
|
||||
if( info == null )
|
||||
return;
|
||||
|
||||
previewFamilyNameLabel.setText( info.name );
|
||||
|
||||
for( Map.Entry<String, Font> e : info.fonts.entrySet() ) {
|
||||
JLabel label = new JLabel( e.getKey() );
|
||||
label.setFont( e.getValue().deriveFont( (float) UIScale.scale( 36 ) ) );
|
||||
previewPanel.add( label, "wrap" );
|
||||
}
|
||||
|
||||
previewPanel.revalidate();
|
||||
previewPanel.repaint();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel familiesLabel = new JLabel();
|
||||
previewFamilyNameLabel = new JLabel();
|
||||
JScrollPane familiesScrollPane = new JScrollPane();
|
||||
familiesList = new JList<>();
|
||||
JSeparator separator1 = new JSeparator();
|
||||
JScrollPane scrollPane1 = new JScrollPane();
|
||||
previewPanel = new JPanel();
|
||||
|
||||
//======== this ========
|
||||
setBorder(null);
|
||||
setLayout(new MigLayout(
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[230:230,fill]para" +
|
||||
"[grow,fill]",
|
||||
// rows
|
||||
"[top]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[800,grow,fill]"));
|
||||
|
||||
//---- familiesLabel ----
|
||||
familiesLabel.setText("Families:");
|
||||
add(familiesLabel, "cell 0 0");
|
||||
|
||||
//---- previewFamilyNameLabel ----
|
||||
previewFamilyNameLabel.setText("name");
|
||||
previewFamilyNameLabel.putClientProperty("FlatLaf.styleClass", "h1");
|
||||
add(previewFamilyNameLabel, "cell 1 1");
|
||||
|
||||
//======== familiesScrollPane ========
|
||||
{
|
||||
|
||||
//---- familiesList ----
|
||||
familiesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
familiesList.addListSelectionListener(e -> familyChanged());
|
||||
familiesScrollPane.setViewportView(familiesList);
|
||||
}
|
||||
add(familiesScrollPane, "cell 0 1 1 3,growy");
|
||||
add(separator1, "cell 1 2");
|
||||
|
||||
//======== scrollPane1 ========
|
||||
{
|
||||
scrollPane1.setBorder(BorderFactory.createEmptyBorder());
|
||||
|
||||
//======== previewPanel ========
|
||||
{
|
||||
previewPanel.setLayout(new MigLayout(
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]"));
|
||||
}
|
||||
scrollPane1.setViewportView(previewPanel);
|
||||
}
|
||||
add(scrollPane1, "cell 1 3");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel previewFamilyNameLabel;
|
||||
private JList<FontFamilyInfo> familiesList;
|
||||
private JPanel previewPanel;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class FontFamilyInfo -----------------------------------------------
|
||||
|
||||
private static class FontFamilyInfo
|
||||
{
|
||||
String name;
|
||||
TreeMap<String, Font> fonts;
|
||||
}
|
||||
|
||||
//---- class FontFamilyRenderer -------------------------------------------
|
||||
|
||||
private static class FontFamilyRenderer
|
||||
extends JPanel
|
||||
implements ListCellRenderer<FontFamilyInfo>
|
||||
{
|
||||
private FontFamilyRenderer() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent( JList<? extends FontFamilyInfo> list,
|
||||
FontFamilyInfo value, int index, boolean isSelected, boolean cellHasFocus )
|
||||
{
|
||||
String family = value.name;
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for( String key : value.fonts.keySet() ) {
|
||||
if( key.startsWith( family ) ) {
|
||||
key = key.substring( family.length() ).trim();
|
||||
if( key.isEmpty() )
|
||||
key = "Regular";
|
||||
}
|
||||
if( buf.length() > 0 )
|
||||
buf.append( ", " );
|
||||
buf.append( key );
|
||||
}
|
||||
|
||||
familyNameLabel.setText( family );
|
||||
familyDescriptionLabel.setText( buf.toString() );
|
||||
|
||||
familyNameLabel.setFont( UIManager.getFont( "large.font" ) );
|
||||
familyDescriptionLabel.setFont( UIManager.getFont( "small.font" ) );
|
||||
familyDescriptionLabel.setEnabled( isSelected );
|
||||
|
||||
setBackground( isSelected ? list.getSelectionBackground() : list.getBackground() );
|
||||
Color fg = isSelected ? list.getSelectionForeground() : list.getForeground();
|
||||
familyNameLabel.setForeground( fg );
|
||||
familyDescriptionLabel.setForeground( fg );
|
||||
return this;
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
familyNameLabel = new JLabel();
|
||||
familyDescriptionLabel = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"insets 2 6 2 6,hidemode 3",
|
||||
// columns
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]0" +
|
||||
"[]"));
|
||||
|
||||
//---- familyNameLabel ----
|
||||
familyNameLabel.setText("text");
|
||||
add(familyNameLabel, "cell 0 0");
|
||||
|
||||
//---- familyDescriptionLabel ----
|
||||
familyDescriptionLabel.setText("text");
|
||||
add(familyDescriptionLabel, "cell 0 1");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel familyNameLabel;
|
||||
private JLabel familyDescriptionLabel;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[230:230,fill]para[grow,fill]"
|
||||
"$rowConstraints": "[top][][][800,grow,fill]"
|
||||
} ) {
|
||||
name: "this"
|
||||
"border": sfield com.jformdesigner.model.FormObject NULL_VALUE
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "familiesLabel"
|
||||
"text": "Families:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "previewFamilyNameLabel"
|
||||
"text": "name"
|
||||
"$client.FlatLaf.styleClass": "h1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "familiesScrollPane"
|
||||
add( new FormComponent( "javax.swing.JList" ) {
|
||||
name: "familiesList"
|
||||
"selectionMode": 0
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.typeParameters": "FontFamilyInfo"
|
||||
}
|
||||
addEvent( new FormEvent( "javax.swing.event.ListSelectionListener", "valueChanged", "familyChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1 1 3,growy"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JSeparator" ) {
|
||||
name: "separator1"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane1"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[fill]"
|
||||
"$rowConstraints": "[]"
|
||||
} ) {
|
||||
name: "previewPanel"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 450, 300 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 2 6 2 6,hidemode 3"
|
||||
"$columnConstraints": "[fill]"
|
||||
"$rowConstraints": "[]0[]"
|
||||
} ) {
|
||||
name: "panel1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.className": "FontFamilyRenderer"
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "familyNameLabel"
|
||||
"text": "text"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "familyDescriptionLabel"
|
||||
"text": "text"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 330 )
|
||||
"size": new java.awt.Dimension( 255, 105 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public class FlatOptionPaneTest
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" );
|
||||
frame.setIconImage( new ImageIcon( FlatOptionPaneTest.class.getResource( "/com/formdev/flatlaf/testing/test16.png" ) ).getImage() );
|
||||
frame.showFrame( FlatOptionPaneTest::new );
|
||||
} );
|
||||
}
|
||||
@@ -54,6 +55,10 @@ public class FlatOptionPaneTest
|
||||
} );
|
||||
}
|
||||
|
||||
private void showTitleBarIcon() {
|
||||
UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
ScrollablePanel panel9 = new ScrollablePanel();
|
||||
@@ -61,6 +66,7 @@ public class FlatOptionPaneTest
|
||||
JPanel panel1 = new JPanel();
|
||||
JOptionPane plainOptionPane = new JOptionPane();
|
||||
plainShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel();
|
||||
showTitleBarIconCheckBox = new JCheckBox();
|
||||
JLabel errorLabel = new JLabel();
|
||||
JPanel panel2 = new JPanel();
|
||||
JOptionPane errorOptionPane = new JOptionPane();
|
||||
@@ -100,7 +106,7 @@ public class FlatOptionPaneTest
|
||||
//======== panel9 ========
|
||||
{
|
||||
panel9.setLayout(new MigLayout(
|
||||
"flowy,ltr,insets dialog,hidemode 3",
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
@@ -134,7 +140,12 @@ public class FlatOptionPaneTest
|
||||
//---- plainShowDialogLabel ----
|
||||
plainShowDialogLabel.setOptionPane(plainOptionPane);
|
||||
plainShowDialogLabel.setTitleLabel(plainLabel);
|
||||
panel9.add(plainShowDialogLabel, "cell 2 0");
|
||||
panel9.add(plainShowDialogLabel, "cell 1 0");
|
||||
|
||||
//---- showTitleBarIconCheckBox ----
|
||||
showTitleBarIconCheckBox.setText("Show window title bar icon");
|
||||
showTitleBarIconCheckBox.addActionListener(e -> showTitleBarIcon());
|
||||
panel9.add(showTitleBarIconCheckBox, "cell 2 0");
|
||||
|
||||
//---- errorLabel ----
|
||||
errorLabel.setText("Error");
|
||||
@@ -156,7 +167,7 @@ public class FlatOptionPaneTest
|
||||
//---- errorShowDialogLabel ----
|
||||
errorShowDialogLabel.setTitleLabel(errorLabel);
|
||||
errorShowDialogLabel.setOptionPane(errorOptionPane);
|
||||
panel9.add(errorShowDialogLabel, "cell 2 1");
|
||||
panel9.add(errorShowDialogLabel, "cell 1 1");
|
||||
|
||||
//---- informationLabel ----
|
||||
informationLabel.setText("Information");
|
||||
@@ -178,7 +189,7 @@ public class FlatOptionPaneTest
|
||||
//---- informationShowDialogLabel ----
|
||||
informationShowDialogLabel.setOptionPane(informationOptionPane);
|
||||
informationShowDialogLabel.setTitleLabel(informationLabel);
|
||||
panel9.add(informationShowDialogLabel, "cell 2 2");
|
||||
panel9.add(informationShowDialogLabel, "cell 1 2");
|
||||
|
||||
//---- questionLabel ----
|
||||
questionLabel.setText("Question");
|
||||
@@ -222,7 +233,7 @@ public class FlatOptionPaneTest
|
||||
//---- warningShowDialogLabel ----
|
||||
warningShowDialogLabel.setOptionPane(warningOptionPane);
|
||||
warningShowDialogLabel.setTitleLabel(warningLabel);
|
||||
panel9.add(warningShowDialogLabel, "cell 2 4");
|
||||
panel9.add(warningShowDialogLabel, "cell 1 4");
|
||||
|
||||
//---- inputLabel ----
|
||||
inputLabel.setText("Input");
|
||||
@@ -244,7 +255,7 @@ public class FlatOptionPaneTest
|
||||
//---- inputShowDialogLabel ----
|
||||
inputShowDialogLabel.setOptionPane(inputOptionPane);
|
||||
inputShowDialogLabel.setTitleLabel(inputLabel);
|
||||
panel9.add(inputShowDialogLabel, "cell 2 5");
|
||||
panel9.add(inputShowDialogLabel, "cell 1 5");
|
||||
|
||||
//---- inputIconLabel ----
|
||||
inputIconLabel.setText("Input + icon");
|
||||
@@ -267,7 +278,7 @@ public class FlatOptionPaneTest
|
||||
//---- inputIconShowDialogLabel ----
|
||||
inputIconShowDialogLabel.setTitleLabel(inputIconLabel);
|
||||
inputIconShowDialogLabel.setOptionPane(inputIconOptionPane);
|
||||
panel9.add(inputIconShowDialogLabel, "cell 2 6");
|
||||
panel9.add(inputIconShowDialogLabel, "cell 1 6");
|
||||
|
||||
//---- customLabel ----
|
||||
customLabel.setText("Custom");
|
||||
@@ -287,7 +298,7 @@ public class FlatOptionPaneTest
|
||||
//---- customShowDialogLabel ----
|
||||
customShowDialogLabel.setOptionPane(customOptionPane);
|
||||
customShowDialogLabel.setTitleLabel(customLabel);
|
||||
panel9.add(customShowDialogLabel, "cell 2 7");
|
||||
panel9.add(customShowDialogLabel, "cell 1 7");
|
||||
|
||||
//---- rightToLeftLabel ----
|
||||
rightToLeftLabel.setText("Right-to-left:");
|
||||
@@ -317,6 +328,7 @@ public class FlatOptionPaneTest
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private FlatOptionPaneTest.ShowDialogLinkLabel plainShowDialogLabel;
|
||||
private JCheckBox showTitleBarIconCheckBox;
|
||||
private FlatOptionPaneTest.ShowDialogLinkLabel errorShowDialogLabel;
|
||||
private FlatOptionPaneTest.ShowDialogLinkLabel informationShowDialogLabel;
|
||||
private JOptionPane customOptionPane;
|
||||
@@ -333,6 +345,7 @@ public class FlatOptionPaneTest
|
||||
|
||||
ShowDialogLinkLabel() {
|
||||
setText( "<html><a href=\"#\">Show dialog</a></html>" );
|
||||
setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );
|
||||
|
||||
addMouseListener( new MouseAdapter() {
|
||||
@Override
|
||||
|
||||
@@ -10,7 +10,7 @@ new FormModel {
|
||||
name: "this"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "flowy,ltr,insets dialog,hidemode 3"
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][][fill]"
|
||||
"$rowConstraints": "[top][top][top][top][top][top][top][top][top]"
|
||||
} ) {
|
||||
@@ -40,6 +40,16 @@ new FormModel {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTitleBarIconCheckBox"
|
||||
"text": "Show window title bar icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
@@ -71,7 +81,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "informationLabel"
|
||||
@@ -101,7 +111,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "questionLabel"
|
||||
@@ -155,7 +165,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "warningOptionPane" )
|
||||
"titleLabel": new FormReference( "warningLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputLabel"
|
||||
@@ -182,7 +192,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "inputOptionPane" )
|
||||
"titleLabel": new FormReference( "inputLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputIconLabel"
|
||||
@@ -210,7 +220,7 @@ new FormModel {
|
||||
"titleLabel": new FormReference( "inputIconLabel" )
|
||||
"optionPane": new FormReference( "inputIconOptionPane" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "customLabel"
|
||||
@@ -238,7 +248,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "customOptionPane" )
|
||||
"titleLabel": new FormReference( "customLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "rightToLeftLabel"
|
||||
@@ -273,7 +283,7 @@ new FormModel {
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 895, 1080 )
|
||||
"size": new java.awt.Dimension( 995, 1080 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -73,6 +74,9 @@ public class FlatWindowDecorationsTest
|
||||
menuBarCheckBox.setSelected( window instanceof JFrame );
|
||||
maximizedBoundsCheckBox.setEnabled( window instanceof Frame );
|
||||
|
||||
menuBarEmbeddedCheckBox.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||
unifiedBackgroundCheckBox.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||
|
||||
addMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
|
||||
addGlueButton.setEnabled( menuBarCheckBox.isEnabled() );
|
||||
removeMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
|
||||
@@ -91,20 +95,35 @@ public class FlatWindowDecorationsTest
|
||||
|
||||
JRootPane rootPane = getWindowRootPane();
|
||||
if( rootPane != null ) {
|
||||
int style = rootPane.getWindowDecorationStyle();
|
||||
if( style == JRootPane.NONE )
|
||||
styleNoneRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.FRAME )
|
||||
styleFrameRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.PLAIN_DIALOG )
|
||||
stylePlainRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.INFORMATION_DIALOG )
|
||||
styleInfoRadioButton.setSelected( true );
|
||||
else
|
||||
throw new RuntimeException(); // not used
|
||||
updateDecorationStyleRadioButtons( rootPane );
|
||||
rootPane.addPropertyChangeListener( "windowDecorationStyle", e -> {
|
||||
updateDecorationStyleRadioButtons( rootPane );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDecorationStyleRadioButtons( JRootPane rootPane ) {
|
||||
int style = rootPane.getWindowDecorationStyle();
|
||||
if( style == JRootPane.NONE )
|
||||
styleNoneRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.FRAME )
|
||||
styleFrameRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.PLAIN_DIALOG )
|
||||
stylePlainRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.INFORMATION_DIALOG )
|
||||
styleInfoRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.ERROR_DIALOG )
|
||||
styleErrorRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.QUESTION_DIALOG )
|
||||
styleQuestionRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.WARNING_DIALOG )
|
||||
styleWarningRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.COLOR_CHOOSER_DIALOG )
|
||||
styleColorChooserRadioButton.setSelected( true );
|
||||
else if( style == JRootPane.FILE_CHOOSER_DIALOG )
|
||||
styleFileChooserRadioButton.setSelected( true );
|
||||
}
|
||||
|
||||
private void unifiedBackgroundChanged() {
|
||||
UIManager.put( "TitlePane.unifiedBackground", unifiedBackgroundCheckBox.isSelected() );
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
@@ -387,6 +406,12 @@ public class FlatWindowDecorationsTest
|
||||
}
|
||||
}
|
||||
|
||||
private void showIconChanged() {
|
||||
JRootPane rootPane = getWindowRootPane();
|
||||
if( rootPane != null )
|
||||
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, showIconCheckBox.getChecked() );
|
||||
}
|
||||
|
||||
private JRootPane getWindowRootPane() {
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
if( window instanceof JFrame )
|
||||
@@ -435,6 +460,7 @@ public class FlatWindowDecorationsTest
|
||||
iconTestRandomRadioButton = new JRadioButton();
|
||||
iconTestMRIRadioButton = new JRadioButton();
|
||||
iconTestDynMRIRadioButton = new JRadioButton();
|
||||
showIconCheckBox = new FlatTriStateCheckBox();
|
||||
JButton openDialogButton = new JButton();
|
||||
JButton openFrameButton = new JButton();
|
||||
menuBar = new JMenuBar();
|
||||
@@ -670,12 +696,13 @@ public class FlatWindowDecorationsTest
|
||||
panel2.setLayout(new MigLayout(
|
||||
"ltr,insets 0,hidemode 3,gap 0 0",
|
||||
// columns
|
||||
"[fill]",
|
||||
"[left]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]rel" +
|
||||
"[]"));
|
||||
|
||||
//---- iconNoneRadioButton ----
|
||||
@@ -703,6 +730,11 @@ public class FlatWindowDecorationsTest
|
||||
iconTestDynMRIRadioButton.setText("test dynamic multi-resolution (Java 9+)");
|
||||
iconTestDynMRIRadioButton.addActionListener(e -> iconChanged());
|
||||
panel2.add(iconTestDynMRIRadioButton, "cell 0 4");
|
||||
|
||||
//---- showIconCheckBox ----
|
||||
showIconCheckBox.setText("show icon");
|
||||
showIconCheckBox.addActionListener(e -> showIconChanged());
|
||||
panel2.add(showIconCheckBox, "cell 0 5");
|
||||
}
|
||||
add(panel2, "cell 1 8");
|
||||
|
||||
@@ -940,6 +972,7 @@ public class FlatWindowDecorationsTest
|
||||
private JRadioButton iconTestRandomRadioButton;
|
||||
private JRadioButton iconTestMRIRadioButton;
|
||||
private JRadioButton iconTestDynMRIRadioButton;
|
||||
private FlatTriStateCheckBox showIconCheckBox;
|
||||
private JMenuBar menuBar;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
@@ -327,8 +327,8 @@ new FormModel {
|
||||
"value": "cell 0 8"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$columnConstraints": "[fill]"
|
||||
"$rowConstraints": "[][][][][]"
|
||||
"$columnConstraints": "[left]"
|
||||
"$rowConstraints": "[][][][][]rel[]"
|
||||
"$layoutConstraints": "ltr,insets 0,hidemode 3,gap 0 0"
|
||||
} ) {
|
||||
name: "panel2"
|
||||
@@ -388,6 +388,16 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||
name: "showIconCheckBox"
|
||||
"text": "show icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showIconChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 8"
|
||||
} )
|
||||
|
||||
@@ -0,0 +1,883 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2023 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.testing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.HierarchyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class LineChartPanel
|
||||
extends JPanel
|
||||
{
|
||||
LineChartPanel() {
|
||||
initComponents();
|
||||
|
||||
lineChartScrollPane.putClientProperty( FlatClientProperties.SCROLL_PANE_SMOOTH_SCROLLING, false );
|
||||
|
||||
oneSecondWidthChanged();
|
||||
updateChartDelayedChanged();
|
||||
|
||||
// clear chart on startup
|
||||
addHierarchyListener( e -> {
|
||||
if( (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 && isShowing() )
|
||||
EventQueue.invokeLater( this::clearChart );
|
||||
} );
|
||||
|
||||
// show chart tooltips immediately and forever
|
||||
ToolTipManager.sharedInstance().setInitialDelay( 0 );
|
||||
ToolTipManager.sharedInstance().setDismissDelay( Integer.MAX_VALUE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
|
||||
// allow clearing chart with Alt+C without moving focus to button
|
||||
getRootPane().registerKeyboardAction(
|
||||
e -> clearChart(),
|
||||
KeyStroke.getKeyStroke( "alt " + (char) clearChartButton.getMnemonic() ),
|
||||
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
|
||||
}
|
||||
|
||||
public boolean isYZeroAtTop() {
|
||||
return lineChart.yZeroAtTop;
|
||||
}
|
||||
|
||||
public void setYZeroAtTop( boolean yZeroAtTop ) {
|
||||
lineChart.yZeroAtTop = yZeroAtTop;
|
||||
lineChart.repaint();
|
||||
}
|
||||
|
||||
public boolean isAsynchron() {
|
||||
return lineChart.asynchron;
|
||||
}
|
||||
|
||||
public void setAsynchron( boolean asynchron ) {
|
||||
lineChart.asynchron = asynchron;
|
||||
lineChart.repaint();
|
||||
}
|
||||
|
||||
public boolean isTemporaryValueDetection() {
|
||||
return lineChart.temporaryValueDetection;
|
||||
}
|
||||
|
||||
public void setTemporaryValueDetection( boolean temporaryValueDetection ) {
|
||||
lineChart.temporaryValueDetection = temporaryValueDetection;
|
||||
lineChart.repaint();
|
||||
}
|
||||
|
||||
public String getLegendYValueText() {
|
||||
return yValueLabel.getText();
|
||||
}
|
||||
|
||||
public void setLegendYValueText( String s ) {
|
||||
yValueLabel.setText( s );
|
||||
}
|
||||
|
||||
public String getLegend1Text() {
|
||||
return legend1Label.getText();
|
||||
}
|
||||
|
||||
public void setLegend1Text( String s ) {
|
||||
legend1Label.setText( s );
|
||||
}
|
||||
|
||||
public String getLegend2Text() {
|
||||
return legend2Label.getText();
|
||||
}
|
||||
|
||||
public void setLegend2Text( String s ) {
|
||||
legend2Label.setText( s );
|
||||
}
|
||||
|
||||
public int getOneSecondWidth() {
|
||||
return oneSecondWidthSlider.getValue();
|
||||
}
|
||||
|
||||
public void setOneSecondWidth( int oneSecondWidth ) {
|
||||
oneSecondWidthSlider.setValue( oneSecondWidth );
|
||||
}
|
||||
|
||||
public boolean isUpdateChartDelayed() {
|
||||
return updateChartDelayedCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public void setUpdateChartDelayed( boolean updateChartDelayed ) {
|
||||
updateChartDelayedCheckBox.setSelected( updateChartDelayed );
|
||||
updateChartDelayedChanged();
|
||||
}
|
||||
|
||||
void addValue( Color chartColor, double value, int ivalue, String name ) {
|
||||
lineChart.addValue( chartColor, value, ivalue, null, false, name );
|
||||
}
|
||||
|
||||
void addValueWithDot( Color chartColor, double value, int ivalue, Color dotColor, String name ) {
|
||||
if( dotColor == null )
|
||||
dotColor = chartColor;
|
||||
lineChart.addValue( chartColor, value, ivalue, dotColor, false, name );
|
||||
}
|
||||
|
||||
void addDot( Color chartColor, double value, int ivalue, Color dotColor, String name ) {
|
||||
if( dotColor == null )
|
||||
dotColor = chartColor;
|
||||
lineChart.addValue( chartColor, value, ivalue, dotColor, true, name );
|
||||
}
|
||||
|
||||
void addMethodHighlight( String classAndMethod, String highlightColor ) {
|
||||
lineChart.methodHighlightMap.put( classAndMethod, highlightColor );
|
||||
}
|
||||
|
||||
private void oneSecondWidthChanged() {
|
||||
int oneSecondWidth = oneSecondWidthSlider.getValue();
|
||||
int msPerLineX =
|
||||
oneSecondWidth <= 2000 ? 100 :
|
||||
oneSecondWidth <= 4000 ? 50 :
|
||||
oneSecondWidth <= 8000 ? 25 :
|
||||
10;
|
||||
|
||||
lineChart.oneSecondWidth = oneSecondWidth;
|
||||
lineChart.msPerLineX = msPerLineX;
|
||||
lineChart.revalidate();
|
||||
lineChart.repaint();
|
||||
|
||||
if( xLabelText == null )
|
||||
xLabelText = xLabel.getText();
|
||||
xLabel.setText( MessageFormat.format( xLabelText, msPerLineX ) );
|
||||
}
|
||||
private String xLabelText;
|
||||
|
||||
private void updateChartDelayedChanged() {
|
||||
lineChart.updateDelayed = updateChartDelayedCheckBox.isSelected();
|
||||
}
|
||||
|
||||
private void clearChart() {
|
||||
lineChart.clear();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents @formatter:off
|
||||
lineChartScrollPane = new JScrollPane();
|
||||
lineChart = new LineChartPanel.LineChart();
|
||||
JPanel legendPanel = new JPanel();
|
||||
xLabel = new JLabel();
|
||||
legend1Label = new JLabel();
|
||||
JLabel yLabel = new JLabel();
|
||||
yValueLabel = new JLabel();
|
||||
JLabel yLabel2 = new JLabel();
|
||||
JPanel hSpacer1 = new JPanel(null);
|
||||
legend2Label = new JLabel();
|
||||
JLabel oneSecondWidthLabel = new JLabel();
|
||||
oneSecondWidthSlider = new JSlider();
|
||||
updateChartDelayedCheckBox = new JCheckBox();
|
||||
clearChartButton = new JButton();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"hidemode 3",
|
||||
// columns
|
||||
"[grow,fill]",
|
||||
// rows
|
||||
"[100:300,grow,fill]" +
|
||||
"[]"));
|
||||
|
||||
//======== lineChartScrollPane ========
|
||||
{
|
||||
lineChartScrollPane.setViewportView(lineChart);
|
||||
}
|
||||
add(lineChartScrollPane, "cell 0 0");
|
||||
|
||||
//======== legendPanel ========
|
||||
{
|
||||
legendPanel.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3,gapy 0",
|
||||
// columns
|
||||
"[fill]para" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//---- xLabel ----
|
||||
xLabel.setText("X: time ({0}ms per line)");
|
||||
legendPanel.add(xLabel, "cell 0 0");
|
||||
legendPanel.add(legend1Label, "cell 1 0");
|
||||
|
||||
//---- yLabel ----
|
||||
yLabel.setText("Y: ");
|
||||
legendPanel.add(yLabel, "cell 0 1,gapx 0 0");
|
||||
|
||||
//---- yValueLabel ----
|
||||
yValueLabel.setText("value");
|
||||
legendPanel.add(yValueLabel, "cell 0 1,gapx 0 0");
|
||||
|
||||
//---- yLabel2 ----
|
||||
yLabel2.setText(" (10% per line)");
|
||||
legendPanel.add(yLabel2, "cell 0 1,gapx 0 0");
|
||||
legendPanel.add(hSpacer1, "cell 0 1,growx");
|
||||
legendPanel.add(legend2Label, "cell 1 1");
|
||||
}
|
||||
add(legendPanel, "cell 0 1");
|
||||
|
||||
//---- oneSecondWidthLabel ----
|
||||
oneSecondWidthLabel.setText("Scale X:");
|
||||
oneSecondWidthLabel.setDisplayedMnemonic('A');
|
||||
oneSecondWidthLabel.setLabelFor(oneSecondWidthSlider);
|
||||
add(oneSecondWidthLabel, "cell 0 1,alignx right,growx 0");
|
||||
|
||||
//---- oneSecondWidthSlider ----
|
||||
oneSecondWidthSlider.setMinimum(100);
|
||||
oneSecondWidthSlider.setMaximum(10000);
|
||||
oneSecondWidthSlider.setSnapToTicks(true);
|
||||
oneSecondWidthSlider.setMajorTickSpacing(100);
|
||||
oneSecondWidthSlider.setValue(500);
|
||||
oneSecondWidthSlider.addChangeListener(e -> oneSecondWidthChanged());
|
||||
add(oneSecondWidthSlider, "cell 0 1,alignx right,growx 0");
|
||||
|
||||
//---- updateChartDelayedCheckBox ----
|
||||
updateChartDelayedCheckBox.setText("Update chart delayed");
|
||||
updateChartDelayedCheckBox.setMnemonic('P');
|
||||
updateChartDelayedCheckBox.addActionListener(e -> updateChartDelayedChanged());
|
||||
add(updateChartDelayedCheckBox, "cell 0 1,alignx right,growx 0");
|
||||
|
||||
//---- clearChartButton ----
|
||||
clearChartButton.setText("Clear Chart");
|
||||
clearChartButton.setMnemonic('C');
|
||||
clearChartButton.addActionListener(e -> clearChart());
|
||||
add(clearChartButton, "cell 0 1,alignx right,growx 0");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents @formatter:on
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @formatter:off
|
||||
private JScrollPane lineChartScrollPane;
|
||||
private LineChartPanel.LineChart lineChart;
|
||||
private JLabel xLabel;
|
||||
private JLabel legend1Label;
|
||||
private JLabel yValueLabel;
|
||||
private JLabel legend2Label;
|
||||
private JSlider oneSecondWidthSlider;
|
||||
private JCheckBox updateChartDelayedCheckBox;
|
||||
private JButton clearChartButton;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
|
||||
|
||||
|
||||
//---- class LineChart ----------------------------------------------------
|
||||
|
||||
private static class LineChart
|
||||
extends JComponent
|
||||
implements Scrollable
|
||||
{
|
||||
private static final int UPDATE_DELAY_MS = 20;
|
||||
private static final int NEW_SEQUENCE_TIME_LAG_MS = 500;
|
||||
private static final int NEW_SEQUENCE_GAP_MS = 100;
|
||||
private static final int HIT_OFFSET = 4;
|
||||
|
||||
private static final boolean TEST = false;
|
||||
|
||||
// asynchron means that chart for each color starts at x=0
|
||||
private boolean asynchron;
|
||||
private boolean temporaryValueDetection;
|
||||
private boolean yZeroAtTop;
|
||||
private int oneSecondWidth = 500;
|
||||
private int msPerLineX = 100;
|
||||
private final HashMap<String, String> methodHighlightMap = new HashMap<>();
|
||||
|
||||
private static class Data {
|
||||
final double value;
|
||||
final int ivalue;
|
||||
final Color chartColor;
|
||||
final Color dotColor;
|
||||
final boolean dotOnly;
|
||||
final long time; // in milliseconds
|
||||
final String name;
|
||||
final Exception stack;
|
||||
|
||||
Data( double value, int ivalue, Color chartColor, Color dotColor,
|
||||
boolean dotOnly, long time, String name, Exception stack )
|
||||
{
|
||||
this.value = value;
|
||||
this.ivalue = ivalue;
|
||||
this.chartColor = chartColor;
|
||||
this.dotColor = dotColor;
|
||||
this.dotOnly = dotOnly;
|
||||
this.time = time;
|
||||
this.name = name;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// for debugging
|
||||
return "value=" + value + ", ivalue=" + ivalue + ", dotColor=" + dotColor
|
||||
+ ", dotOnly=" + dotOnly + ", time=" + time + ", name=" + name;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Data> syncChartData = new ArrayList<>();
|
||||
private final Map<Color, List<Data>> asyncColor2dataMap = new HashMap<>();
|
||||
private final Timer repaintTime;
|
||||
private Color lastUsedChartColor;
|
||||
private boolean updateDelayed;
|
||||
|
||||
private final List<Point> lastPoints = new ArrayList<>();
|
||||
private final List<Data> lastDatas = new ArrayList<>();
|
||||
private double lastSystemScaleFactor = 1;
|
||||
private String lastToolTipPrinted;
|
||||
|
||||
LineChart() {
|
||||
repaintTime = new Timer( UPDATE_DELAY_MS, e -> repaintAndRevalidate() );
|
||||
repaintTime.setRepeats( false );
|
||||
|
||||
ToolTipManager.sharedInstance().registerComponent( this );
|
||||
|
||||
if( TEST )
|
||||
initTestData();
|
||||
}
|
||||
|
||||
void addValue( Color chartColor, double value, int ivalue, Color dotColor, boolean dotOnly, String name ) {
|
||||
if( TEST )
|
||||
return;
|
||||
|
||||
List<Data> chartData = asyncColor2dataMap.computeIfAbsent( chartColor, k -> new ArrayList<>() );
|
||||
Data data = new Data( value, ivalue, chartColor, dotColor, dotOnly, System.nanoTime() / 1_000_000, name, new Exception() );
|
||||
if( asynchron )
|
||||
chartData.add( data );
|
||||
else
|
||||
syncChartData.add( data );
|
||||
|
||||
lastUsedChartColor = chartColor;
|
||||
|
||||
if( updateDelayed ) {
|
||||
repaintTime.stop();
|
||||
repaintTime.start();
|
||||
} else
|
||||
repaintAndRevalidate();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if( TEST ) {
|
||||
repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
syncChartData.clear();
|
||||
asyncColor2dataMap.clear();
|
||||
lastUsedChartColor = null;
|
||||
|
||||
repaint();
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void repaintAndRevalidate() {
|
||||
repaint();
|
||||
revalidate();
|
||||
|
||||
// scroll horizontally
|
||||
if( lastUsedChartColor != null ) {
|
||||
// compute chart width of last used color and start of last sequence
|
||||
int[] lastSeqX = new int[1];
|
||||
int cw = chartWidth( asynchron ? asyncColor2dataMap.get( lastUsedChartColor ) : syncChartData, lastSeqX );
|
||||
|
||||
// scroll to end of last sequence (of last used color)
|
||||
int lastSeqWidth = cw - lastSeqX[0];
|
||||
int width = Math.min( lastSeqWidth, getParent().getWidth() );
|
||||
int x = cw - width;
|
||||
scrollRectToVisible( new Rectangle( x, 0, width, getHeight() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
Graphics g2 = g.create();
|
||||
try {
|
||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g2, this, this::paintAt1x );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void paintAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
FlatUIUtils.setRenderingHints( g );
|
||||
|
||||
int oneSecondWidth = (int) (UIScale.scale( this.oneSecondWidth ) * scaleFactor);
|
||||
int seqGapWidth = (oneSecondWidth * NEW_SEQUENCE_GAP_MS) / 1000;
|
||||
int hitOffset = (int) Math.round( UIScale.scale( HIT_OFFSET ) * scaleFactor );
|
||||
|
||||
Color lineColor = FlatUIUtils.getUIColor( "Component.borderColor", Color.lightGray );
|
||||
Color lineColor2 = FlatLaf.isLafDark()
|
||||
? new HSLColor( lineColor ).adjustTone( 30 )
|
||||
: new HSLColor( lineColor ).adjustShade( 30 );
|
||||
|
||||
g.translate( x, y );
|
||||
|
||||
// fill background
|
||||
g.setColor( UIManager.getColor( "Table.background" ) );
|
||||
g.fillRect( x, y, width, height );
|
||||
|
||||
// paint horizontal lines
|
||||
for( int i = 1; i < 10; i++ ) {
|
||||
int hy = (height * i) / 10;
|
||||
g.setColor( (i != 5) ? lineColor : lineColor2 );
|
||||
g.drawLine( 0, hy, width, hy );
|
||||
}
|
||||
|
||||
// paint vertical lines
|
||||
int perLineXWidth = Math.round( (oneSecondWidth / 1000f) * msPerLineX );
|
||||
for( int i = 1, xv = perLineXWidth; xv < width; xv += perLineXWidth, i++ ) {
|
||||
g.setColor( (i % 5 != 0) ? lineColor : lineColor2 );
|
||||
g.drawLine( xv, 0, xv, height );
|
||||
}
|
||||
|
||||
lastPoints.clear();
|
||||
lastDatas.clear();
|
||||
lastSystemScaleFactor = scaleFactor;
|
||||
|
||||
// paint lines
|
||||
for( Map.Entry<Color, List<Data>> e : asyncColor2dataMap.entrySet() ) {
|
||||
List<Data> chartData = asynchron ? e.getValue() : syncChartData;
|
||||
Color chartColor = e.getKey();
|
||||
if( FlatLaf.isLafDark() )
|
||||
chartColor = new HSLColor( chartColor ).adjustTone( 50 );
|
||||
Color temporaryValueColor = fade( chartColor, FlatLaf.isLafDark() ? 0.7f : 0.3f );
|
||||
Color dataPointColor = fade( chartColor, FlatLaf.isLafDark() ? 0.6f : 0.2f );
|
||||
|
||||
// sequence start time and x coordinate
|
||||
long seqStartTime = 0;
|
||||
int seqStartX = 0;
|
||||
|
||||
// "previous" data point time and x coordinate (used for "new sequence" detection)
|
||||
long ptime = Long.MIN_VALUE;
|
||||
int px = 0;
|
||||
|
||||
// "line" data point x/y coordinates
|
||||
int lx = -1;
|
||||
int ly = -1;
|
||||
|
||||
boolean isTemporaryValue = false;
|
||||
int lastTemporaryValueIndex = -1;
|
||||
|
||||
int size = chartData.size();
|
||||
for( int i = 0; i < size; i++ ) {
|
||||
Data data = chartData.get( i );
|
||||
boolean useData = (data.chartColor == chartColor);
|
||||
|
||||
// start new sequence if there is a larger time gap to previous data point
|
||||
boolean newSeq = (data.time > ptime + NEW_SEQUENCE_TIME_LAG_MS);
|
||||
ptime = data.time;
|
||||
|
||||
if( newSeq ) {
|
||||
// start new sequence
|
||||
seqStartTime = data.time;
|
||||
seqStartX = (i > 0) ? px + seqGapWidth : 0;
|
||||
px = seqStartX;
|
||||
lx = -1;
|
||||
ly = -1;
|
||||
isTemporaryValue = false;
|
||||
}
|
||||
|
||||
// x/y coordinates of current data point
|
||||
int dx = (int) (seqStartX + (((data.time - seqStartTime) / 1000.) * oneSecondWidth));
|
||||
int dy = (int) ((height - 1) * data.value);
|
||||
if( !yZeroAtTop )
|
||||
dy = height - 1 - dy;
|
||||
|
||||
// remember x coordinate for "new sequence" detection
|
||||
px = dx;
|
||||
|
||||
if( !useData )
|
||||
continue;
|
||||
|
||||
// remember data point for tooltip
|
||||
lastPoints.add( new Point( dx, dy ) );
|
||||
lastDatas.add( data );
|
||||
|
||||
// paint rectangle to indicate data point
|
||||
g.setColor( dataPointColor );
|
||||
g.drawRect( dx - hitOffset, dy - hitOffset, hitOffset * 2, hitOffset * 2 );
|
||||
|
||||
// paint dot
|
||||
if( data.dotColor != null ) {
|
||||
int s1 = (int) Math.round( UIScale.scale( 1 ) * scaleFactor );
|
||||
int s3 = (int) Math.round( UIScale.scale( 3 ) * scaleFactor );
|
||||
g.setColor( data.dotColor );
|
||||
g.fillRect( dx - s1, dy - s1, s3, s3 );
|
||||
|
||||
if( data.dotOnly )
|
||||
continue;
|
||||
}
|
||||
|
||||
// start of line?
|
||||
if( lx < 0 ) {
|
||||
// remember x/y coordinates for first line
|
||||
lx = dx;
|
||||
ly = dy;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( isTemporaryValue && i > lastTemporaryValueIndex )
|
||||
isTemporaryValue = false;
|
||||
|
||||
// draw line in sequence
|
||||
g.setColor( isTemporaryValue ? temporaryValueColor : chartColor );
|
||||
g.drawLine( lx, ly, dx, dy );
|
||||
|
||||
// remember x/y coordinates for next line
|
||||
lx = dx;
|
||||
ly = dy;
|
||||
|
||||
// check next data points for "temporary" value(s)
|
||||
if( temporaryValueDetection && !isTemporaryValue ) {
|
||||
// one or two values between two equal values are considered "temporary",
|
||||
// which means that they are the target value for the following scroll animation
|
||||
int stage = 0;
|
||||
for( int j = i + 1; j < size && stage <= 2 && !isTemporaryValue; j++ ) {
|
||||
Data nextData = chartData.get( j );
|
||||
if( nextData.dotOnly )
|
||||
continue; // ignore dots
|
||||
|
||||
// check whether next data point is within 10 milliseconds
|
||||
if( nextData.time > data.time + 10 )
|
||||
break;
|
||||
|
||||
if( stage >= 1 && stage <= 2 && nextData.value == data.value ) {
|
||||
isTemporaryValue = true;
|
||||
lastTemporaryValueIndex = j;
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int chartWidth() {
|
||||
int width = 0;
|
||||
if( asynchron ) {
|
||||
for( List<Data> chartData : asyncColor2dataMap.values() )
|
||||
width = Math.max( width, chartWidth( chartData, null ) );
|
||||
} else
|
||||
width = Math.max( width, chartWidth( syncChartData, null ) );
|
||||
return width;
|
||||
}
|
||||
|
||||
private int chartWidth( List<Data> chartData, int[] lastSeqX ) {
|
||||
long seqTime = 0;
|
||||
int seqX = 0;
|
||||
long ptime = 0;
|
||||
int px = 0;
|
||||
int oneSecondWidth = UIScale.scale( this.oneSecondWidth );
|
||||
int seqGapWidth = (oneSecondWidth * NEW_SEQUENCE_GAP_MS) / 1000;
|
||||
|
||||
int size = chartData.size();
|
||||
for( int i = 0; i < size; i++ ) {
|
||||
Data data = chartData.get( i );
|
||||
|
||||
if( data.time > ptime + NEW_SEQUENCE_TIME_LAG_MS ) {
|
||||
// start new sequence
|
||||
seqTime = data.time;
|
||||
seqX = (i > 0) ? px + seqGapWidth : 0;
|
||||
px = seqX;
|
||||
} else {
|
||||
// line in sequence
|
||||
int dx = (int) (seqX + (((data.time - seqTime) / 1000.) * oneSecondWidth ));
|
||||
px = dx;
|
||||
}
|
||||
|
||||
ptime = data.time;
|
||||
}
|
||||
|
||||
if( lastSeqX != null )
|
||||
lastSeqX[0] = seqX;
|
||||
|
||||
return px;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension( chartWidth(), 200 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return new Dimension( chartWidth(), 200 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||
return UIScale.scale( oneSecondWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||
JViewport viewport = (JViewport) SwingUtilities.getAncestorOfClass( JViewport.class, this );
|
||||
return (viewport != null) ? viewport.getWidth() : 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
JViewport viewport = (JViewport) SwingUtilities.getAncestorOfClass( JViewport.class, this );
|
||||
return (viewport != null) ? viewport.getWidth() > chartWidth() : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText( MouseEvent e ) {
|
||||
int x = (int) Math.round( e.getX() * lastSystemScaleFactor );
|
||||
int y = (int) Math.round( e.getY() * lastSystemScaleFactor );
|
||||
int hitOffset = (int) Math.round( UIScale.scale( HIT_OFFSET ) * lastSystemScaleFactor );
|
||||
StringBuilder buf = null;
|
||||
|
||||
int pointsCount = lastPoints.size();
|
||||
for( int i = 0; i < pointsCount; i++ ) {
|
||||
Point pt = lastPoints.get( i );
|
||||
|
||||
// check X/Y coordinates
|
||||
if( x < pt.x - hitOffset || x > pt.x + hitOffset ||
|
||||
y < pt.y - hitOffset || y > pt.y + hitOffset )
|
||||
continue;
|
||||
|
||||
if( buf == null ) {
|
||||
buf = new StringBuilder( 5000 );
|
||||
buf.append( "<html>" );
|
||||
}
|
||||
|
||||
Data data = lastDatas.get( i );
|
||||
buf.append( "<h2>" );
|
||||
if( data.dotOnly )
|
||||
buf.append( "DOT: " );
|
||||
buf.append( data.name );
|
||||
if( data.ivalue != Integer.MIN_VALUE )
|
||||
buf.append( ' ' ).append( data.ivalue );
|
||||
buf.append( " (" ).append( String.format( "%.3f", data.value ) ).append( ')' );
|
||||
buf.append( "</h2>" );
|
||||
|
||||
StackTraceElement[] stackTrace = data.stack.getStackTrace();
|
||||
for( int j = 0; j < stackTrace.length; j++ ) {
|
||||
StackTraceElement stackElement = stackTrace[j];
|
||||
String className = stackElement.getClassName();
|
||||
String methodName = stackElement.getMethodName();
|
||||
String classAndMethod = className + '.' + methodName;
|
||||
|
||||
// ignore methods from this class
|
||||
if( className.startsWith( LineChartPanel.class.getName() ) )
|
||||
continue;
|
||||
|
||||
int repeatCount = 0;
|
||||
for( int k = j + 1; k < stackTrace.length; k++ ) {
|
||||
if( !stackElement.equals( stackTrace[k] ) )
|
||||
break;
|
||||
repeatCount++;
|
||||
}
|
||||
j += repeatCount;
|
||||
|
||||
String highlight = methodHighlightMap.get( classAndMethod );
|
||||
if( highlight == null )
|
||||
highlight = methodHighlightMap.get( className );
|
||||
if( highlight == null )
|
||||
highlight = methodHighlightMap.get( methodName );
|
||||
if( highlight != null )
|
||||
buf.append( "<span color=\"" ).append( highlight ).append( "\">" );
|
||||
|
||||
// append method
|
||||
buf.append( className )
|
||||
.append( ".<b>" )
|
||||
.append( methodName )
|
||||
.append( "</b>" );
|
||||
if( highlight != null )
|
||||
buf.append( "</span>" );
|
||||
|
||||
// append source
|
||||
buf.append( " <span color=\"#888888\">" );
|
||||
if( stackElement.getFileName() != null ) {
|
||||
buf.append( '(' );
|
||||
buf.append( stackElement.getFileName() );
|
||||
if( stackElement.getLineNumber() >= 0 )
|
||||
buf.append( ':' ).append( stackElement.getLineNumber() );
|
||||
buf.append( ')' );
|
||||
} else
|
||||
buf.append( "(Unknown Source)" );
|
||||
buf.append( "</span>" );
|
||||
|
||||
// append repeat count
|
||||
if( repeatCount > 0 )
|
||||
buf.append( " <b>" ).append( repeatCount + 1 ).append( "x</b>" );
|
||||
buf.append( "<br>" );
|
||||
|
||||
// break at some methods to make stack smaller
|
||||
if( classAndMethod.equals( "java.awt.event.InvocationEvent.dispatch" ) ||
|
||||
classAndMethod.equals( "java.awt.Component.processMouseEvent" ) ||
|
||||
classAndMethod.equals( "java.awt.Component.processMouseWheelEvent" ) ||
|
||||
classAndMethod.equals( "java.awt.Component.processMouseMotionEvent" ) ||
|
||||
classAndMethod.equals( "javax.swing.JComponent.processKeyBinding" ) ||
|
||||
classAndMethod.equals( "javax.swing.JComponent.paintComponent" ) ||
|
||||
classAndMethod.equals( "com.formdev.flatlaf.util.Animator.timingEvent" ) )
|
||||
break;
|
||||
}
|
||||
buf.append( "..." );
|
||||
}
|
||||
|
||||
if( buf == null )
|
||||
return null;
|
||||
|
||||
buf.append( "<html>" );
|
||||
String toolTip = buf.toString();
|
||||
|
||||
// print to console
|
||||
if( !Objects.equals( toolTip, lastToolTipPrinted ) ) {
|
||||
lastToolTipPrinted = toolTip;
|
||||
|
||||
System.out.println( toolTip
|
||||
.replace( "<br>", "\n" )
|
||||
.replace( "<h2>", "\n---- " )
|
||||
.replace( "</h2>", " ----\n" )
|
||||
.replaceAll( "<[^>]+>", "" ) );
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void initTestData() {
|
||||
// asynchron = true;
|
||||
|
||||
addTestSimpleLine( Color.red, 0.0, "red" );
|
||||
addTestSimpleLine( Color.green, 0.1, "green" );
|
||||
addTestSimpleLine( Color.blue, 0.2, "blue" );
|
||||
addTestSimpleLine( Color.magenta, 0.3, "magenta" );
|
||||
|
||||
addTestMiddleDotOnly( Color.red, 0.0, "red" );
|
||||
addTestMiddleDotOnly( Color.green, 0.1, "green" );
|
||||
addTestMiddleDotOnly( Color.blue, 0.2, "blue" );
|
||||
addTestMiddleDotOnly( Color.magenta, 0.3, "magenta" );
|
||||
|
||||
addTestLeadingDotOnly( Color.red, 0.0, "red" );
|
||||
addTestLeadingDotOnly( Color.green, 0.1, "green" );
|
||||
addTestLeadingDotOnly( Color.blue, 0.2, "blue" );
|
||||
addTestLeadingDotOnly( Color.magenta, 0.3, "magenta" );
|
||||
|
||||
addTestTrailingDotOnly( Color.red, 0.0, "red" );
|
||||
addTestTrailingDotOnly( Color.green, 0.1, "green" );
|
||||
addTestTrailingDotOnly( Color.blue, 0.2, "blue" );
|
||||
addTestTrailingDotOnly( Color.magenta, 0.3, "magenta" );
|
||||
|
||||
addTestSingleData( Color.red, 0.0, "red" );
|
||||
addTestSingleData( Color.green, 0.1, "green" );
|
||||
addTestSingleData( Color.blue, 0.2, "blue" );
|
||||
addTestSingleData( Color.magenta, 0.3, "magenta" );
|
||||
|
||||
temporaryValueDetection = true;
|
||||
addTestWithTemporaryValues( Color.red, 0.0, "red" );
|
||||
addTestWithTemporaryValues( Color.green, 0.1, "green" );
|
||||
addTestWithTemporaryValues( Color.blue, 0.2, "blue" );
|
||||
addTestWithTemporaryValues( Color.magenta, 0.3, "magenta" );
|
||||
}
|
||||
|
||||
private void addTestSimpleLine( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.0, null, false, name );
|
||||
addTestValue( 50, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 50, chartColor, baseValue + 0.4, null, false, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestMiddleDotOnly( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.0, null, false, name );
|
||||
addTestValue( 20, chartColor, baseValue + 0.3, chartColor, true, name );
|
||||
addTestValue( 30, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 20, chartColor, baseValue + 0.05, chartColor, true, name );
|
||||
addTestValue( 30, chartColor, baseValue + 0.4, null, false, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestLeadingDotOnly( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.05, chartColor, true, name );
|
||||
addTestValue( 20, chartColor, baseValue + 0.0, null, false, name );
|
||||
addTestValue( 50, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 30, chartColor, baseValue + 0.4, null, false, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestTrailingDotOnly( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.0, null, false, name );
|
||||
addTestValue( 50, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 30, chartColor, baseValue + 0.4, null, false, name );
|
||||
addTestValue( 20, chartColor, baseValue + 0.05, chartColor, true, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestSingleData( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.15, chartColor, false, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestWithTemporaryValues( Color chartColor, double baseValue, String name ) {
|
||||
addTestValue( 0, chartColor, baseValue + 0.0, null, false, name );
|
||||
addTestValue( 50, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 5, chartColor, baseValue + 0.4, null, false, name );
|
||||
addTestValue( 5, chartColor, baseValue + 0.1, null, false, name );
|
||||
addTestValue( 40, chartColor, baseValue + 0.3, null, false, name );
|
||||
testTime += 1000;
|
||||
}
|
||||
|
||||
private void addTestValue( int timeDelta, Color chartColor, double value, Color dotColor, boolean dotOnly, String name ) {
|
||||
testTime += timeDelta;
|
||||
|
||||
List<Data> chartData = asyncColor2dataMap.computeIfAbsent( chartColor, k -> new ArrayList<>() );
|
||||
Data data = new Data( value, testIValue++, chartColor, dotColor, dotOnly, testTime, name, new Exception() );
|
||||
if( asynchron )
|
||||
chartData.add( data );
|
||||
else
|
||||
syncChartData.add( data );
|
||||
|
||||
lastUsedChartColor = chartColor;
|
||||
}
|
||||
|
||||
private int testIValue;
|
||||
private long testTime;
|
||||
|
||||
//TODO remove and use ColorFunctions.fade() when merging to main
|
||||
private static Color fade( Color color, float amount ) {
|
||||
int newAlpha = Math.round( 255 * amount );
|
||||
return new Color( (color.getRGB() & 0xffffff) | (newAlpha << 24), true );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[grow,fill]"
|
||||
"$rowConstraints": "[100:300,grow,fill][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "lineChartScrollPane"
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.LineChartPanel$LineChart" ) {
|
||||
name: "lineChart"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3,gapy 0"
|
||||
"$columnConstraints": "[fill]para[fill]"
|
||||
"$rowConstraints": "[][]"
|
||||
} ) {
|
||||
name: "legendPanel"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "xLabel"
|
||||
"text": "X: time ({0}ms per line)"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "legend1Label"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "yLabel"
|
||||
"text": "Y: "
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,gapx 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "yValueLabel"
|
||||
"text": "value"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,gapx 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "yLabel2"
|
||||
"text": " (10% per line)"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,gapx 0 0"
|
||||
} )
|
||||
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||
name: "hSpacer1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "legend2Label"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "oneSecondWidthLabel"
|
||||
"text": "Scale X:"
|
||||
"displayedMnemonic": 65
|
||||
"labelFor": new FormReference( "oneSecondWidthSlider" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,alignx right,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JSlider" ) {
|
||||
name: "oneSecondWidthSlider"
|
||||
"minimum": 100
|
||||
"maximum": 10000
|
||||
"snapToTicks": true
|
||||
"majorTickSpacing": 100
|
||||
"value": 500
|
||||
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "oneSecondWidthChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,alignx right,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "updateChartDelayedCheckBox"
|
||||
"text": "Update chart delayed"
|
||||
"mnemonic": 80
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "updateChartDelayedChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,alignx right,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "clearChartButton"
|
||||
"text": "Clear Chart"
|
||||
"mnemonic": 67
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "clearChart", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,alignx right,growx 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 880, 300 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import java.awt.Cursor;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
@@ -52,6 +51,7 @@ import java.util.prefs.Preferences;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.swing.*;
|
||||
import net.miginfocom.swing.*;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||
import com.formdev.flatlaf.FlatDarkLaf;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
@@ -754,8 +754,7 @@ class FlatThemeFileEditor
|
||||
|
||||
private void about() {
|
||||
JLabel titleLabel = new JLabel( "FlatLaf Theme Editor" );
|
||||
Font titleFont = titleLabel.getFont();
|
||||
titleLabel.setFont( titleFont.deriveFont( (float) titleFont.getSize() + UIScale.scale( 6 ) ) );
|
||||
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
|
||||
|
||||
String link = "https://www.formdev.com/flatlaf/";
|
||||
JLabel linkLabel = new JLabel( "<html><a href=\"#\">" + link + "</a></html>" );
|
||||
|
||||
@@ -46,6 +46,7 @@ class FlatThemePreview
|
||||
private final FlatThemePreviewAll allTab;
|
||||
private final FlatThemePreviewButtons buttonsTab;
|
||||
private final FlatThemePreviewSwitches switchesTab;
|
||||
private final FlatThemePreviewFonts fontsTab;
|
||||
|
||||
private final Map<LazyValue, Object> lazyValueCache = new WeakHashMap<>();
|
||||
private int runWithUIDefaultsGetterLevel;
|
||||
@@ -61,9 +62,11 @@ class FlatThemePreview
|
||||
allTab = new FlatThemePreviewAll( this );
|
||||
buttonsTab = new FlatThemePreviewButtons( this );
|
||||
switchesTab = new FlatThemePreviewSwitches( this );
|
||||
fontsTab = new FlatThemePreviewFonts();
|
||||
tabbedPane.addTab( "All", createPreviewTab( allTab ) );
|
||||
tabbedPane.addTab( "Buttons", createPreviewTab( buttonsTab ) );
|
||||
tabbedPane.addTab( "Switches", createPreviewTab( switchesTab ) );
|
||||
tabbedPane.addTab( "Fonts", createPreviewTab( fontsTab ) );
|
||||
selectRecentTab();
|
||||
tabbedPane.addChangeListener( e -> selectedTabChanged() );
|
||||
|
||||
@@ -175,7 +178,8 @@ class FlatThemePreview
|
||||
|
||||
Object value = textArea.propertiesSupport.getParsedProperty( (String) key );
|
||||
|
||||
inGetDefaultFont = "defaultFont".equals( key );
|
||||
boolean isDefaultFont = "defaultFont".equals( key );
|
||||
inGetDefaultFont = isDefaultFont;
|
||||
try {
|
||||
if( value instanceof LazyValue ) {
|
||||
value = lazyValueCache.computeIfAbsent( (LazyValue) value, k -> {
|
||||
@@ -189,6 +193,12 @@ class FlatThemePreview
|
||||
|
||||
// System.out.println( key + " = " + value );
|
||||
|
||||
// for "defaultFont" never return a value that is not a font
|
||||
// (e.g. a color for "defaultFont = #fff") to avoid StackOverflowError
|
||||
// in Active.createValue()
|
||||
if( isDefaultFont && !(value instanceof Font) )
|
||||
return null;
|
||||
|
||||
// If value is null and is a property that is defined in a core theme,
|
||||
// then force the value to null.
|
||||
// This is necessary for cases where the current application Laf defines a property
|
||||
@@ -196,7 +206,7 @@ class FlatThemePreview
|
||||
// E.g. FlatLightLaf defines Button.focusedBackground, but in FlatDarkLaf
|
||||
// it is not defined. Without this code, the preview for FlatDarkLaf would use
|
||||
// Button.focusedBackground from FlatLightLaf if FlatLightLaf is the current application Laf.
|
||||
if( value == null && FlatThemePropertiesBaseManager.getDefindedCoreKeys().contains( key ) && !"defaultFont".equals( key ) )
|
||||
if( value == null && FlatThemePropertiesBaseManager.getDefindedCoreKeys().contains( key ) && !isDefaultFont )
|
||||
return FlatLaf.NULL_VALUE;
|
||||
|
||||
return value;
|
||||
@@ -215,6 +225,7 @@ class FlatThemePreview
|
||||
{
|
||||
tabbedPane.setLeadingComponent(previewLabel);
|
||||
tabbedPane.setTabAreaAlignment(FlatTabbedPane.TabAreaAlignment.trailing);
|
||||
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
||||
}
|
||||
add(tabbedPane, BorderLayout.CENTER);
|
||||
|
||||
@@ -223,8 +234,8 @@ class FlatThemePreview
|
||||
add(previewSeparator, BorderLayout.LINE_START);
|
||||
|
||||
//---- previewLabel ----
|
||||
previewLabel.setText(" Preview ");
|
||||
previewLabel.setFont(previewLabel.getFont().deriveFont(previewLabel.getFont().getSize() + 6f));
|
||||
previewLabel.setText(" Preview ");
|
||||
previewLabel.putClientProperty("FlatLaf.styleClass", "h2");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ new FormModel {
|
||||
name: "tabbedPane"
|
||||
"leadingComponent": new FormReference( "previewLabel" )
|
||||
"tabAreaAlignment": enum com.formdev.flatlaf.extras.components.FlatTabbedPane$TabAreaAlignment trailing
|
||||
"tabLayoutPolicy": 1
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
@@ -24,8 +25,8 @@ new FormModel {
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "previewLabel"
|
||||
"text": " Preview "
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 6, false )
|
||||
"text": " Preview "
|
||||
"$client.FlatLaf.styleClass": "h2"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 235 )
|
||||
"size": new java.awt.Dimension( 176, 24 )
|
||||
|
||||
@@ -560,7 +560,7 @@ class FlatThemePreviewAll
|
||||
menuUnderlineSelectionButton.setButtonType(FlatButton.ButtonType.toolBarButton);
|
||||
menuUnderlineSelectionButton.setToolTipText("menu underline selection");
|
||||
menuUnderlineSelectionButton.setFocusable(false);
|
||||
menuUnderlineSelectionButton.setFont(menuUnderlineSelectionButton.getFont().deriveFont(menuUnderlineSelectionButton.getFont().getSize() - 2f));
|
||||
menuUnderlineSelectionButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
menuUnderlineSelectionButton.addActionListener(e -> menuUnderlineSelectionChanged());
|
||||
add(menuUnderlineSelectionButton, "cell 0 11");
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ new FormModel {
|
||||
"buttonType": enum com.formdev.flatlaf.extras.components.FlatButton$ButtonType toolBarButton
|
||||
"toolTipText": "menu underline selection"
|
||||
"focusable": false
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
|
||||
@@ -232,25 +232,25 @@ class FlatThemePreviewButtons
|
||||
//---- noneButton ----
|
||||
noneButton.setText("none");
|
||||
noneButton.setSelected(true);
|
||||
noneButton.setFont(noneButton.getFont().deriveFont(noneButton.getFont().getSize() - 2f));
|
||||
noneButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
noneButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar1.add(noneButton);
|
||||
|
||||
//---- squareButton ----
|
||||
squareButton.setText("square");
|
||||
squareButton.setFont(squareButton.getFont().deriveFont(squareButton.getFont().getSize() - 2f));
|
||||
squareButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
squareButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar1.add(squareButton);
|
||||
|
||||
//---- roundRectButton ----
|
||||
roundRectButton.setText("roundRect");
|
||||
roundRectButton.setFont(roundRectButton.getFont().deriveFont(roundRectButton.getFont().getSize() - 2f));
|
||||
roundRectButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
roundRectButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar1.add(roundRectButton);
|
||||
|
||||
//---- tabButton ----
|
||||
tabButton.setText("tab");
|
||||
tabButton.setFont(tabButton.getFont().deriveFont(tabButton.getFont().getSize() - 2f));
|
||||
tabButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar1.add(tabButton);
|
||||
}
|
||||
@@ -263,13 +263,13 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- toolBarButtonButton ----
|
||||
toolBarButtonButton.setText("toolBarButton");
|
||||
toolBarButtonButton.setFont(toolBarButtonButton.getFont().deriveFont(toolBarButtonButton.getFont().getSize() - 2f));
|
||||
toolBarButtonButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
toolBarButtonButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar2.add(toolBarButtonButton);
|
||||
|
||||
//---- borderlessButton ----
|
||||
borderlessButton.setText("borderless");
|
||||
borderlessButton.setFont(borderlessButton.getFont().deriveFont(borderlessButton.getFont().getSize() - 2f));
|
||||
borderlessButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
borderlessButton.addActionListener(e -> buttonTypeChanged());
|
||||
buttonTypeToolBar2.add(borderlessButton);
|
||||
}
|
||||
@@ -279,7 +279,7 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- label11 ----
|
||||
label11.setText("JButton");
|
||||
label11.setFont(label11.getFont().deriveFont(label11.getFont().getSize() + 4f));
|
||||
label11.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label11, "cell 0 1 3 1");
|
||||
|
||||
//---- label27 ----
|
||||
@@ -292,22 +292,22 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- label5 ----
|
||||
label5.setText("regular");
|
||||
label5.setFont(label5.getFont().deriveFont(label5.getFont().getSize() - 2f));
|
||||
label5.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label5, "cell 1 3,alignx center,growx 0");
|
||||
|
||||
//---- label7 ----
|
||||
label7.setText("default");
|
||||
label7.setFont(label7.getFont().deriveFont(label7.getFont().getSize() - 2f));
|
||||
label7.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label7, "cell 2 3,alignx center,growx 0");
|
||||
|
||||
//---- label6 ----
|
||||
label6.setText("regular");
|
||||
label6.setFont(label6.getFont().deriveFont(label6.getFont().getSize() - 2f));
|
||||
label6.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label6, "cell 3 3,alignx center,growx 0");
|
||||
|
||||
//---- label8 ----
|
||||
label8.setText("default");
|
||||
label8.setFont(label8.getFont().deriveFont(label8.getFont().getSize() - 2f));
|
||||
label8.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label8, "cell 4 3,alignx center,growx 0");
|
||||
|
||||
//---- label1 ----
|
||||
@@ -435,7 +435,7 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- label12 ----
|
||||
label12.setText("JToggleButton");
|
||||
label12.setFont(label12.getFont().deriveFont(label12.getFont().getSize() + 4f));
|
||||
label12.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label12, "cell 0 9 3 1");
|
||||
|
||||
//---- label29 ----
|
||||
@@ -448,22 +448,22 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- label13 ----
|
||||
label13.setText("unsel.");
|
||||
label13.setFont(label13.getFont().deriveFont(label13.getFont().getSize() - 2f));
|
||||
label13.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label13, "cell 1 11,alignx center,growx 0");
|
||||
|
||||
//---- label14 ----
|
||||
label14.setText("selected");
|
||||
label14.setFont(label14.getFont().deriveFont(label14.getFont().getSize() - 2f));
|
||||
label14.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label14, "cell 2 11,alignx center,growx 0");
|
||||
|
||||
//---- label15 ----
|
||||
label15.setText("unsel.");
|
||||
label15.setFont(label15.getFont().deriveFont(label15.getFont().getSize() - 2f));
|
||||
label15.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label15, "cell 3 11,alignx center,growx 0");
|
||||
|
||||
//---- label16 ----
|
||||
label16.setText("selected");
|
||||
label16.setFont(label16.getFont().deriveFont(label16.getFont().getSize() - 2f));
|
||||
label16.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label16, "cell 4 11,alignx center,growx 0");
|
||||
|
||||
//---- label17 ----
|
||||
@@ -576,7 +576,7 @@ class FlatThemePreviewButtons
|
||||
|
||||
//---- label32 ----
|
||||
label32.setText("Help Button");
|
||||
label32.setFont(label32.getFont().deriveFont(label32.getFont().getSize() + 4f));
|
||||
label32.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label32, "cell 0 17 2 1");
|
||||
|
||||
//---- label9 ----
|
||||
|
||||
@@ -33,7 +33,7 @@ new FormModel {
|
||||
"text": "none"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"selected": true
|
||||
"font": &SwingDerivedFont0 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -43,7 +43,7 @@ new FormModel {
|
||||
name: "squareButton"
|
||||
"text": "square"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -53,7 +53,7 @@ new FormModel {
|
||||
name: "roundRectButton"
|
||||
"text": "roundRect"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -63,7 +63,7 @@ new FormModel {
|
||||
name: "tabButton"
|
||||
"text": "tab"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -80,7 +80,7 @@ new FormModel {
|
||||
name: "toolBarButtonButton"
|
||||
"text": "toolBarButton"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -90,7 +90,7 @@ new FormModel {
|
||||
name: "borderlessButton"
|
||||
"text": "borderless"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -105,7 +105,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label11"
|
||||
"text": "JButton"
|
||||
"font": &SwingDerivedFont1 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1 3 1"
|
||||
} )
|
||||
@@ -124,28 +124,28 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label5"
|
||||
"text": "regular"
|
||||
"font": &SwingDerivedFont2 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label7"
|
||||
"text": "default"
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label6"
|
||||
"text": "regular"
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label8"
|
||||
"text": "default"
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 3,alignx center,growx 0"
|
||||
} )
|
||||
@@ -317,7 +317,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label12"
|
||||
"text": "JToggleButton"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9 3 1"
|
||||
} )
|
||||
@@ -336,28 +336,28 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label13"
|
||||
"text": "unsel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label14"
|
||||
"text": "selected"
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label15"
|
||||
"text": "unsel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label16"
|
||||
"text": "selected"
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 11,alignx center,growx 0"
|
||||
} )
|
||||
@@ -514,7 +514,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label32"
|
||||
"text": "Help Button"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 17 2 1"
|
||||
} )
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.themeeditor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.text.DecimalFormat;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatThemePreviewFonts
|
||||
extends JPanel
|
||||
{
|
||||
private static final DecimalFormat SCALE_FORMAT = new DecimalFormat( "0.##x" );
|
||||
|
||||
public FlatThemePreviewFonts() {
|
||||
initComponents();
|
||||
|
||||
scaleValueLabel.setText( SCALE_FORMAT.format( UIScale.getUserScaleFactor() ) );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel headingsLabel = new JLabel();
|
||||
FlatThemePreviewFonts.FontPreview h00Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview h0Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview h1Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview h2Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview h3Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview h4Preview = new FlatThemePreviewFonts.FontPreview();
|
||||
JLabel textLabel = new JLabel();
|
||||
FlatThemePreviewFonts.FontPreview largePreview = new FlatThemePreviewFonts.FontPreview();
|
||||
defaultPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview mediumPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview smallPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview miniPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview lightPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview semiboldPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
FlatThemePreviewFonts.FontPreview monospacedPreview = new FlatThemePreviewFonts.FontPreview();
|
||||
JLabel scaleLabel = new JLabel();
|
||||
scaleValueLabel = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[left]unrel",
|
||||
// rows
|
||||
"[]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]para" +
|
||||
"[]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]" +
|
||||
"[bottom]para" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]para" +
|
||||
"[]"));
|
||||
|
||||
//---- headingsLabel ----
|
||||
headingsLabel.setText("Headings");
|
||||
headingsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(headingsLabel, "cell 0 0");
|
||||
|
||||
//---- h00Preview ----
|
||||
h00Preview.setFontType("H00");
|
||||
h00Preview.setFontStyle("h00");
|
||||
add(h00Preview, "cell 0 1,gapx 12");
|
||||
|
||||
//---- h0Preview ----
|
||||
h0Preview.setFontType("H0");
|
||||
h0Preview.setFontStyle("h0");
|
||||
add(h0Preview, "cell 0 2,gapx 12");
|
||||
|
||||
//---- h1Preview ----
|
||||
h1Preview.setFontType("H1");
|
||||
h1Preview.setFontStyle("h1");
|
||||
h1Preview.setFontStyleRegular("h1.regular");
|
||||
add(h1Preview, "cell 0 3,gapx 12");
|
||||
|
||||
//---- h2Preview ----
|
||||
h2Preview.setFontType("H2");
|
||||
h2Preview.setFontStyle("h2");
|
||||
h2Preview.setFontStyleRegular("h2.regular");
|
||||
add(h2Preview, "cell 0 4,gapx 12");
|
||||
|
||||
//---- h3Preview ----
|
||||
h3Preview.setFontType("H3");
|
||||
h3Preview.setFontStyle("h3");
|
||||
h3Preview.setFontStyleRegular("h3.regular");
|
||||
add(h3Preview, "cell 0 5,gapx 12");
|
||||
|
||||
//---- h4Preview ----
|
||||
h4Preview.setFontType("H4");
|
||||
h4Preview.setFontStyle("h4");
|
||||
add(h4Preview, "cell 0 6,gapx 12");
|
||||
|
||||
//---- textLabel ----
|
||||
textLabel.setText("Text");
|
||||
textLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(textLabel, "cell 0 7");
|
||||
|
||||
//---- largePreview ----
|
||||
largePreview.setFontType("Large");
|
||||
largePreview.setFontStyle("large");
|
||||
add(largePreview, "cell 0 8,gapx 12");
|
||||
|
||||
//---- defaultPreview ----
|
||||
defaultPreview.setFontType("Default");
|
||||
add(defaultPreview, "cell 0 9,gapx 12");
|
||||
|
||||
//---- mediumPreview ----
|
||||
mediumPreview.setFontType("Medium");
|
||||
mediumPreview.setFontStyle("medium");
|
||||
add(mediumPreview, "cell 0 10,gapx 12");
|
||||
|
||||
//---- smallPreview ----
|
||||
smallPreview.setFontType("Small");
|
||||
smallPreview.setFontStyle("small");
|
||||
add(smallPreview, "cell 0 11,gapx 12");
|
||||
|
||||
//---- miniPreview ----
|
||||
miniPreview.setFontType("Mini");
|
||||
miniPreview.setFontStyle("mini");
|
||||
add(miniPreview, "cell 0 12,gapx 12");
|
||||
|
||||
//---- lightPreview ----
|
||||
lightPreview.setFontType("Light");
|
||||
lightPreview.setFontStyle("light");
|
||||
add(lightPreview, "cell 0 13,gapx 12");
|
||||
|
||||
//---- semiboldPreview ----
|
||||
semiboldPreview.setFontType("Semibold");
|
||||
semiboldPreview.setFontStyle("semibold");
|
||||
add(semiboldPreview, "cell 0 14,gapx 12");
|
||||
|
||||
//---- monospacedPreview ----
|
||||
monospacedPreview.setFontType("Monospaced");
|
||||
monospacedPreview.setFontStyle("monospaced");
|
||||
add(monospacedPreview, "cell 0 15,gapx 12");
|
||||
|
||||
//---- scaleLabel ----
|
||||
scaleLabel.setText("Fonts in preview are scaled by:");
|
||||
add(scaleLabel, "cell 0 16,gapx 12");
|
||||
|
||||
//---- scaleValueLabel ----
|
||||
scaleValueLabel.setText("1x");
|
||||
scaleValueLabel.putClientProperty("FlatLaf.styleClass", "h2");
|
||||
add(scaleValueLabel, "cell 0 16");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private FlatThemePreviewFonts.FontPreview defaultPreview;
|
||||
private JLabel scaleValueLabel;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class FontPreview --------------------------------------------------
|
||||
|
||||
static class FontPreview
|
||||
extends JPanel
|
||||
{
|
||||
private String fontType;
|
||||
private String fontStyle;
|
||||
private String fontStyleRegular;
|
||||
|
||||
private FontPreview() {
|
||||
initComponents();
|
||||
|
||||
updateDescription( previewLabel.getFont() );
|
||||
previewLabel.addPropertyChangeListener( "font", e -> {
|
||||
updateDescription( previewLabel.getFont() );
|
||||
} );
|
||||
|
||||
preview2Label.setVisible( false );
|
||||
}
|
||||
|
||||
public String getFontType() {
|
||||
return fontType;
|
||||
}
|
||||
|
||||
public void setFontType( String fontType ) {
|
||||
this.fontType = fontType;
|
||||
previewLabel.setText( fontType );
|
||||
preview2Label.setText( " / " + fontType );
|
||||
}
|
||||
|
||||
public String getFontStyle() {
|
||||
return fontStyle;
|
||||
}
|
||||
|
||||
public void setFontStyle( String fontStyle ) {
|
||||
this.fontStyle = fontStyle;
|
||||
previewLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, fontStyle );
|
||||
}
|
||||
|
||||
public String getFontStyleRegular() {
|
||||
return fontStyleRegular;
|
||||
}
|
||||
|
||||
public void setFontStyleRegular( String fontStyleRegular ) {
|
||||
this.fontStyleRegular = fontStyleRegular;
|
||||
preview2Label.putClientProperty( FlatClientProperties.STYLE_CLASS, fontStyleRegular );
|
||||
preview2Label.setVisible( fontStyleRegular != null );
|
||||
}
|
||||
|
||||
private void updateDescription( Font font ) {
|
||||
int baseSize = getDefaultFont().getSize();
|
||||
int fontSize = font.getSize();
|
||||
|
||||
descLabel.setText( String.format( "%s %d %s%s (%+d %s)",
|
||||
font.getFamily(),
|
||||
fontSize,
|
||||
(font.getStyle() & Font.BOLD) != 0 ? " bold" : "",
|
||||
(font.getStyle() & Font.ITALIC) != 0 ? " italic" : "",
|
||||
fontSize - baseSize,
|
||||
SCALE_FORMAT.format( (float) fontSize / baseSize ) ) );
|
||||
}
|
||||
|
||||
private Font getDefaultFont() {
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
if( font == null )
|
||||
font = UIManager.getFont( "Label.font" );
|
||||
return font;
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
previewLabel = new JLabel();
|
||||
preview2Label = new JLabel();
|
||||
descLabel = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
"[90,left]" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]0"));
|
||||
|
||||
//---- previewLabel ----
|
||||
previewLabel.setText("preview");
|
||||
add(previewLabel, "cell 0 0");
|
||||
|
||||
//---- preview2Label ----
|
||||
preview2Label.setText("preview");
|
||||
add(preview2Label, "cell 0 0,gapx 0");
|
||||
|
||||
//---- descLabel ----
|
||||
descLabel.setText("description");
|
||||
descLabel.putClientProperty("FlatLaf.styleClass", "medium");
|
||||
add(descLabel, "cell 1 0");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel previewLabel;
|
||||
private JLabel preview2Label;
|
||||
private JLabel descLabel;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[left]unrel"
|
||||
"$rowConstraints": "[][bottom][bottom][bottom][bottom][bottom][bottom]para[][bottom][bottom][bottom][bottom][bottom]para[][]para[]para[]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "headingsLabel"
|
||||
"text": "Headings"
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h00Preview"
|
||||
"fontType": "H00"
|
||||
"fontStyle": "h00"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h0Preview"
|
||||
"fontType": "H0"
|
||||
"fontStyle": "h0"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h1Preview"
|
||||
"fontType": "H1"
|
||||
"fontStyle": "h1"
|
||||
"fontStyleRegular": "h1.regular"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h2Preview"
|
||||
"fontType": "H2"
|
||||
"fontStyle": "h2"
|
||||
"fontStyleRegular": "h2.regular"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h3Preview"
|
||||
"fontType": "H3"
|
||||
"fontStyle": "h3"
|
||||
"fontStyleRegular": "h3.regular"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "h4Preview"
|
||||
"fontType": "H4"
|
||||
"fontStyle": "h4"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "textLabel"
|
||||
"text": "Text"
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "largePreview"
|
||||
"fontType": "Large"
|
||||
"fontStyle": "large"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 8,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "defaultPreview"
|
||||
"fontType": "Default"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "mediumPreview"
|
||||
"fontType": "Medium"
|
||||
"fontStyle": "medium"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 10,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "smallPreview"
|
||||
"fontType": "Small"
|
||||
"fontStyle": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 11,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "miniPreview"
|
||||
"fontType": "Mini"
|
||||
"fontStyle": "mini"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 12,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "lightPreview"
|
||||
"fontType": "Light"
|
||||
"fontStyle": "light"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 13,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "semiboldPreview"
|
||||
"fontType": "Semibold"
|
||||
"fontStyle": "semibold"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 14,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.themeeditor.FlatThemePreviewFonts$FontPreview" ) {
|
||||
name: "monospacedPreview"
|
||||
"fontType": "Monospaced"
|
||||
"fontStyle": "monospaced"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 15,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "scaleLabel"
|
||||
"text": "Fonts in preview are scaled by:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 16,gapx 12"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "scaleValueLabel"
|
||||
"text": "1x"
|
||||
"$client.FlatLaf.styleClass": "h2"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 16"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 5, 0 )
|
||||
"size": new java.awt.Dimension( 335, 495 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3"
|
||||
"$columnConstraints": "[90,left][fill]"
|
||||
"$rowConstraints": "[]0"
|
||||
} ) {
|
||||
name: "panel1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.className": "FontPreview"
|
||||
"JavaCodeGenerator.variableName": "fontPreview"
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "previewLabel"
|
||||
"text": "preview"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "preview2Label"
|
||||
"text": "preview"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0,gapx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "descLabel"
|
||||
"text": "description"
|
||||
"$client.FlatLaf.styleClass": "medium"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 5, 545 )
|
||||
"size": new java.awt.Dimension( 235, 65 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -262,25 +262,25 @@ class FlatThemePreviewSwitches
|
||||
//---- zoom1xButton ----
|
||||
zoom1xButton.setText("1x");
|
||||
zoom1xButton.setSelected(true);
|
||||
zoom1xButton.setFont(zoom1xButton.getFont().deriveFont(zoom1xButton.getFont().getSize() - 2f));
|
||||
zoom1xButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
zoom1xButton.addActionListener(e -> zoomChanged());
|
||||
zoomToolBar.add(zoom1xButton);
|
||||
|
||||
//---- zoom2xButton ----
|
||||
zoom2xButton.setText("2x");
|
||||
zoom2xButton.setFont(zoom2xButton.getFont().deriveFont(zoom2xButton.getFont().getSize() - 2f));
|
||||
zoom2xButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
zoom2xButton.addActionListener(e -> zoomChanged());
|
||||
zoomToolBar.add(zoom2xButton);
|
||||
|
||||
//---- zoom3xButton ----
|
||||
zoom3xButton.setText("3x");
|
||||
zoom3xButton.setFont(zoom3xButton.getFont().deriveFont(zoom3xButton.getFont().getSize() - 2f));
|
||||
zoom3xButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
zoom3xButton.addActionListener(e -> zoomChanged());
|
||||
zoomToolBar.add(zoom3xButton);
|
||||
|
||||
//---- zoom4xButton ----
|
||||
zoom4xButton.setText("4x");
|
||||
zoom4xButton.setFont(zoom4xButton.getFont().deriveFont(zoom4xButton.getFont().getSize() - 2f));
|
||||
zoom4xButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
zoom4xButton.addActionListener(e -> zoomChanged());
|
||||
zoomToolBar.add(zoom4xButton);
|
||||
zoomToolBar.addSeparator();
|
||||
@@ -288,6 +288,7 @@ class FlatThemePreviewSwitches
|
||||
//---- indeterminateButton ----
|
||||
indeterminateButton.setText("indeterminate");
|
||||
indeterminateButton.setSelected(true);
|
||||
indeterminateButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
indeterminateButton.addActionListener(e -> indeterminateChanged());
|
||||
zoomToolBar.add(indeterminateButton);
|
||||
}
|
||||
@@ -297,7 +298,7 @@ class FlatThemePreviewSwitches
|
||||
|
||||
//---- label22 ----
|
||||
label22.setText("JCheckBox");
|
||||
label22.setFont(label22.getFont().deriveFont(label22.getFont().getSize() + 4f));
|
||||
label22.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label22, "cell 0 1 3 1");
|
||||
|
||||
//---- label1 ----
|
||||
@@ -310,32 +311,32 @@ class FlatThemePreviewSwitches
|
||||
|
||||
//---- label23 ----
|
||||
label23.setText("unsel.");
|
||||
label23.setFont(label23.getFont().deriveFont(label23.getFont().getSize() - 2f));
|
||||
label23.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label23, "cell 1 3,alignx center,growx 0");
|
||||
|
||||
//---- label28 ----
|
||||
label28.setText("sel.");
|
||||
label28.setFont(label28.getFont().deriveFont(label28.getFont().getSize() - 2f));
|
||||
label28.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label28, "cell 2 3,alignx center,growx 0");
|
||||
|
||||
//---- label37 ----
|
||||
label37.setText("ind.");
|
||||
label37.setFont(label37.getFont().deriveFont(label37.getFont().getSize() - 2f));
|
||||
label37.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label37, "cell 3 3,alignx center,growx 0");
|
||||
|
||||
//---- label24 ----
|
||||
label24.setText("unsel.");
|
||||
label24.setFont(label24.getFont().deriveFont(label24.getFont().getSize() - 2f));
|
||||
label24.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label24, "cell 4 3,alignx center,growx 0");
|
||||
|
||||
//---- label29 ----
|
||||
label29.setText("sel.");
|
||||
label29.setFont(label29.getFont().deriveFont(label29.getFont().getSize() - 2f));
|
||||
label29.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label29, "cell 5 3,alignx center,growx 0");
|
||||
|
||||
//---- label38 ----
|
||||
label38.setText("ind.");
|
||||
label38.setFont(label38.getFont().deriveFont(label38.getFont().getSize() - 2f));
|
||||
label38.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label38, "cell 6 3,alignx center,growx 0");
|
||||
|
||||
//---- label17 ----
|
||||
@@ -465,7 +466,7 @@ class FlatThemePreviewSwitches
|
||||
|
||||
//---- label27 ----
|
||||
label27.setText("JRadioButton");
|
||||
label27.setFont(label27.getFont().deriveFont(label27.getFont().getSize() + 4f));
|
||||
label27.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(label27, "cell 0 9 3 1");
|
||||
|
||||
//---- label3 ----
|
||||
@@ -478,22 +479,22 @@ class FlatThemePreviewSwitches
|
||||
|
||||
//---- label25 ----
|
||||
label25.setText("unsel.");
|
||||
label25.setFont(label25.getFont().deriveFont(label25.getFont().getSize() - 2f));
|
||||
label25.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label25, "cell 1 11,alignx center,growx 0");
|
||||
|
||||
//---- label30 ----
|
||||
label30.setText("sel.");
|
||||
label30.setFont(label30.getFont().deriveFont(label30.getFont().getSize() - 2f));
|
||||
label30.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label30, "cell 2 11,alignx center,growx 0");
|
||||
|
||||
//---- label26 ----
|
||||
label26.setText("unsel.");
|
||||
label26.setFont(label26.getFont().deriveFont(label26.getFont().getSize() - 2f));
|
||||
label26.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label26, "cell 4 11,alignx center,growx 0");
|
||||
|
||||
//---- label31 ----
|
||||
label31.setText("sel.");
|
||||
label31.setFont(label31.getFont().deriveFont(label31.getFont().getSize() - 2f));
|
||||
label31.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(label31, "cell 5 11,alignx center,growx 0");
|
||||
|
||||
//---- label36 ----
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.4.0.360" Java: "17" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -32,7 +32,7 @@ new FormModel {
|
||||
name: "zoom1xButton"
|
||||
"text": "1x"
|
||||
"selected": true
|
||||
"font": &SwingDerivedFont0 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
@@ -42,7 +42,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "zoom2xButton"
|
||||
"text": "2x"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"$buttonGroup": &FormReference0 new FormReference( "buttonGroup1" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
@@ -52,7 +52,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "zoom3xButton"
|
||||
"text": "3x"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"$buttonGroup": #FormReference0
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
@@ -62,7 +62,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "zoom4xButton"
|
||||
"text": "4x"
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"$buttonGroup": #FormReference0
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
@@ -76,6 +76,7 @@ new FormModel {
|
||||
name: "indeterminateButton"
|
||||
"text": "indeterminate"
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -90,7 +91,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label22"
|
||||
"text": "JCheckBox"
|
||||
"font": &SwingDerivedFont1 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1 3 1"
|
||||
} )
|
||||
@@ -109,42 +110,42 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label23"
|
||||
"text": "unsel."
|
||||
"font": &SwingDerivedFont2 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label28"
|
||||
"text": "sel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label37"
|
||||
"text": "ind."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label24"
|
||||
"text": "unsel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label29"
|
||||
"text": "sel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 3,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label38"
|
||||
"text": "ind."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 6 3,alignx center,growx 0"
|
||||
} )
|
||||
@@ -340,7 +341,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label27"
|
||||
"text": "JRadioButton"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9 3 1"
|
||||
} )
|
||||
@@ -359,28 +360,28 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label25"
|
||||
"text": "unsel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label30"
|
||||
"text": "sel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label26"
|
||||
"text": "unsel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 11,alignx center,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label31"
|
||||
"text": "sel."
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 11,alignx center,growx 0"
|
||||
} )
|
||||
|
||||
@@ -531,6 +531,7 @@ OptionPane.minimumSize
|
||||
OptionPane.questionIcon
|
||||
OptionPane.sameSizeButtons
|
||||
OptionPane.setButtonMargin
|
||||
OptionPane.showIcon
|
||||
OptionPane.warningIcon
|
||||
OptionPane.windowBindings
|
||||
OptionPaneUI
|
||||
@@ -631,10 +632,13 @@ RangeSliderUI
|
||||
Resizable.resizeBorder
|
||||
RootPane.activeBorderColor
|
||||
RootPane.ancestorInputMap
|
||||
RootPane.background
|
||||
RootPane.border
|
||||
RootPane.borderDragThickness
|
||||
RootPane.cornerDragWidth
|
||||
RootPane.defaultButtonWindowKeyBindings
|
||||
RootPane.font
|
||||
RootPane.foreground
|
||||
RootPane.honorDialogMinimumSizeOnResize
|
||||
RootPane.honorFrameMinimumSizeOnResize
|
||||
RootPane.inactiveBorderColor
|
||||
@@ -783,6 +787,7 @@ TabbedPane.buttonArc
|
||||
TabbedPane.buttonHoverBackground
|
||||
TabbedPane.buttonInsets
|
||||
TabbedPane.buttonPressedBackground
|
||||
TabbedPane.cardTabSelectionHeight
|
||||
TabbedPane.closeArc
|
||||
TabbedPane.closeCrossFilledSize
|
||||
TabbedPane.closeCrossLineWidth
|
||||
@@ -829,6 +834,7 @@ TabbedPane.tabRunOverlay
|
||||
TabbedPane.tabSelectionHeight
|
||||
TabbedPane.tabSeparatorColor
|
||||
TabbedPane.tabSeparatorsFullHeight
|
||||
TabbedPane.tabType
|
||||
TabbedPane.tabWidthMode
|
||||
TabbedPane.tabsOpaque
|
||||
TabbedPane.tabsOverlapBorder
|
||||
@@ -969,7 +975,9 @@ TitlePane.inactiveForeground
|
||||
TitlePane.maximizeIcon
|
||||
TitlePane.menuBarEmbedded
|
||||
TitlePane.menuBarTitleGap
|
||||
TitlePane.noIconLeftGap
|
||||
TitlePane.restoreIcon
|
||||
TitlePane.showIcon
|
||||
TitlePane.titleMargins
|
||||
TitlePane.unifiedBackground
|
||||
TitlePane.useWindowDecorations
|
||||
@@ -1091,6 +1099,22 @@ Viewport.background
|
||||
Viewport.font
|
||||
Viewport.foreground
|
||||
ViewportUI
|
||||
[style].h0
|
||||
[style].h00
|
||||
[style].h1
|
||||
[style].h1.regular
|
||||
[style].h2
|
||||
[style].h2.regular
|
||||
[style].h3
|
||||
[style].h3.regular
|
||||
[style].h4
|
||||
[style].large
|
||||
[style].light
|
||||
[style].medium
|
||||
[style].mini
|
||||
[style].monospaced
|
||||
[style].semibold
|
||||
[style].small
|
||||
activeCaption
|
||||
activeCaptionBorder
|
||||
activeCaptionText
|
||||
@@ -1102,6 +1126,15 @@ controlShadow
|
||||
controlText
|
||||
defaultFont
|
||||
desktop
|
||||
h0.font
|
||||
h00.font
|
||||
h1.font
|
||||
h1.regular.font
|
||||
h2.font
|
||||
h2.regular.font
|
||||
h3.font
|
||||
h3.regular.font
|
||||
h4.font
|
||||
html.missingImage
|
||||
html.pendingImage
|
||||
inactiveCaption
|
||||
@@ -1111,9 +1144,16 @@ info
|
||||
infoText
|
||||
laf.dark
|
||||
laf.scaleFactor
|
||||
large.font
|
||||
light.font
|
||||
medium.font
|
||||
menu
|
||||
menuText
|
||||
mini.font
|
||||
monospaced.font
|
||||
scrollbar
|
||||
semibold.font
|
||||
small.font
|
||||
swingx/TaskPaneUI
|
||||
text
|
||||
textHighlight
|
||||
|
||||
@@ -27,6 +27,7 @@ include( "flatlaf-theme-editor" )
|
||||
|
||||
includeProject( "flatlaf-natives-windows", "flatlaf-natives/flatlaf-natives-windows" )
|
||||
includeProject( "flatlaf-natives-jna", "flatlaf-natives/flatlaf-natives-jna" )
|
||||
includeProject( "flatlaf-testing-modular-app", "flatlaf-testing/flatlaf-testing-modular-app" )
|
||||
|
||||
fun includeProject( projectPath: String, projectDir: String ) {
|
||||
include( projectPath )
|
||||
|
||||
Reference in New Issue
Block a user