Compare commits

...

71 Commits
0.12 ... 0.18

Author SHA1 Message Date
Karl Tauber
6572198178 release 0.18 2019-11-10 10:06:59 +01:00
Karl Tauber
f69b3f56dd ToolTip: use anti-aliasing to render multi-line tooltips 2019-11-10 00:09:51 +01:00
Karl Tauber
c379f2f3b0 JIDE: added missing dependency to flatlaf-testing project 2019-11-09 18:51:52 +01:00
Karl Tauber
e7194e43b4 JIDE: README.md added and publishing added to build.gradle.kts 2019-11-09 18:44:31 +01:00
Karl Tauber
883b282cd8 JIDE: JideTabbedPane: hover tab event if mouse is over close button
unfortunately it is not possible to replace JIDEs arrow and close buttons with own implementations
2019-11-09 18:21:25 +01:00
Karl Tauber
7c2b2d7f26 JIDE: basic JideTabbedPane implementation 2019-11-09 17:23:55 +01:00
Karl Tauber
08f525de5f TabbedPane: content pane is no longer opaque and use antialiasing for painting separator and content border 2019-11-09 15:53:02 +01:00
Karl Tauber
433659a5df TabbedPane: no longer modify BasicTabbedPaneUI.contentBorderInsets in getContentBorderInsets() because this is useless and confusing 2019-11-09 13:57:39 +01:00
Karl Tauber
7f50a30b29 TabbedPane: reworked painting in scroll-tab-layout, so that the separator line now spans the whole width and is no longer interrupted by the scroll buttons 2019-11-09 10:58:31 +01:00
Karl Tauber
d5944779e8 TabbedPane: use FlatClientProperties for JTabbedPane.hasFullBorder client property 2019-11-08 23:01:33 +01:00
Karl Tauber
fdaea31475 JIDE: flatlaf-jide-oss subproject created 2019-11-08 15:51:28 +01:00
Karl Tauber
a66ebd29b4 update to Gradle 5.6.4
./gradlew wrapper --gradle-version=5.6.4
2019-11-07 18:24:33 +01:00
Karl Tauber
f3006467e9 TextField and TextArea: do not apply minimum width if columns property > 0 2019-10-30 15:14:23 +01:00
Karl Tauber
aa52af4c8f added FlatLaf.isDark() 2019-10-29 11:01:48 +01:00
Karl Tauber
2e0fde464d release 0.17 2019-10-27 12:29:12 +01:00
Karl Tauber
9bf0124950 FlatBorder: replaced Paint with Color 2019-10-27 12:27:31 +01:00
Karl Tauber
eaa6db1d19 Table: fixed missing upper right corner (e.g. in SwingX JXTable with column control visible) 2019-10-27 12:25:39 +01:00
Karl Tauber
2ec142f000 Button: hover and pressed background colors are now derived from actual button background color (issue #21) 2019-10-27 11:03:40 +01:00
Karl Tauber
ec572436a9 extracted properties file parsing to new class UIDefaultsLoader 2019-10-25 23:07:44 +02:00
Karl Tauber
6e5e548c9d Testing: fixed content panel insets and removed 5,5 gaps 2019-10-25 10:44:24 +02:00
Karl Tauber
61c3bbad60 ComboBox and Spinner:
- make child components explicitly non-opaque
- paint parent background only if necessary
2019-10-25 10:28:24 +02:00
Karl Tauber
bc10c4e871 Made JComboBox, JProgressBar, JSpinner and JXDatePicker non-opaque.
`JPasswordField`, `JScrollPane` and `JTextField` are non-opaque if they have
an outside focus border (e.g. IntelliJ and Darcula themes).
(issues #20 and #17)
2019-10-25 10:28:18 +02:00
Karl Tauber
8b8d84c2a3 TextField and PasswordField: reduced duplicate code 2019-10-24 20:47:31 +02:00
Karl Tauber
5743b5d59f CheckBox: removed accidentally checked in debug output 2019-10-24 18:07:22 +02:00
Karl Tauber
9450ba5e46 Extras: fixed link in README.md 2019-10-24 15:31:13 +02:00
Karl Tauber
cfcbf3e61c CheckBox:
- compute focus border arc based on Component.focusWidth
- allow specifying border arc in UI defaults (CheckBox.arc)
2019-10-24 14:28:50 +02:00
Karl Tauber
136481c110 Testing: added "opaque" checkbox to test apps 2019-10-24 12:44:16 +02:00
Karl Tauber
7f43b3003c TriStateCheckBox component added 2019-10-24 12:36:40 +02:00
Karl Tauber
1b0c2687c8 Testing: added "background" checkbox to test apps 2019-10-24 10:52:53 +02:00
Karl Tauber
aeb80f862b build.gradle.kts: depend task "assemble" on "sourcesJar" and "javadocJar" so that they are built on Travic CI to file problems early (previously those tasks were build only just before publishing) 2019-10-23 17:06:25 +02:00
Karl Tauber
1de367e19e moved testing applications from src/test to new project flatlaf-testing (part 2) 2019-10-23 16:44:39 +02:00
Karl Tauber
62895a602f moved testing applications from src/test to new project flatlaf-testing (part 1) 2019-10-23 16:44:19 +02:00
Karl Tauber
6438e890bb release 0.16 2019-10-23 10:46:46 +02:00
Karl Tauber
7d72b13ac9 made JButton, JCheckBox, JRadioButton, JToggleButton and JSlider non-opaque (#20) 2019-10-23 10:36:33 +02:00
Karl Tauber
a2e21cb07b fixed Java 9 module descriptor (broken since 0.14) 2019-10-23 09:55:55 +02:00
Karl Tauber
06766cb4db Demo: missing SwingUtilities.invokeLater() added 2019-10-23 09:03:08 +02:00
Karl Tauber
72e8ab70a3 Demo: tooltips added to toolbar buttons 2019-10-22 12:09:04 +02:00
Karl Tauber
0f38af5922 ComboBox: right-to-left fixes (#18) 2019-10-22 12:07:23 +02:00
Karl Tauber
4181759008 right-to-left fixes:
-Slider: colored track (if ticks and labels are hidden) was on the left side of the thumb
- ToolTip: multi-line text was not aligned to the right

(issue #18)
2019-10-21 22:12:51 +02:00
Karl Tauber
fff0e5e946 fixed FlatTestLaf (broken by commit 342b932f9e) 2019-10-21 20:11:35 +02:00
Karl Tauber
be88eeb343 release 0.15 2019-10-21 18:29:40 +02:00
Karl Tauber
342b932f9e ToolTip:
- Improved styling of dark tooltips (darker background, no border).
- increased top and bottom margins
- use brighter color in light theme
- Fixed colors in tooltips of disabled components. (issue #15)
2019-10-21 18:07:43 +02:00
Karl Tauber
964dc14a8a ComboBox: fixed NPE in combobox with custom renderer after switching to FlatLaf (#16; regression in 0.14) 2019-10-21 17:04:23 +02:00
Karl Tauber
b56f462626 SwingX: added screenshots 2019-10-21 13:42:22 +02:00
Karl Tauber
4477b4c44e release 0.14 2019-10-21 10:52:33 +02:00
Karl Tauber
714c6e2920 TextField and PasswordField: fixed minimum width if focusWidth > 2 and not having a FlatBorder 2019-10-20 22:17:15 +02:00
Karl Tauber
0853a1aa2e SwingX: fixed preferred width of JXDatePicker, which was too large (#8) 2019-10-20 22:16:13 +02:00
Karl Tauber
f9d2312b3a ComboBox: fixed StackOverflowError when switching LaF (#14) 2019-10-20 20:04:10 +02:00
Karl Tauber
f53f205f52 SwingX: fixed JXDatePicker.TodayPanel colors (#8) 2019-10-20 18:18:06 +02:00
Karl Tauber
41ecbccc76 EditorPane and TextPane: fixed font and text color when using HTML content (#9) 2019-10-20 18:17:47 +02:00
Karl Tauber
5a952c187c SwingX: JXMonthView support (#8) 2019-10-20 10:47:53 +02:00
Karl Tauber
0a86d00c1e FlatLaf: allow specifying value type in value for cases where auto-detecting value type from key or value does not work 2019-10-19 13:47:53 +02:00
Karl Tauber
b3e9d82537 SwingX: added SwingX LaF addon (#8) 2019-10-19 09:36:43 +02:00
Karl Tauber
0970dceee2 SwingX: JXDatePicker support (#8) 2019-10-19 09:35:01 +02:00
Karl Tauber
ffef71d6db OptionPane: fixed rendering of longer HTML text (#12) 2019-10-18 18:41:14 +02:00
Karl Tauber
0ede8cd5b9 SwingX: build.gradle.kts: added maven publishing and bintray upload 2019-10-18 14:36:04 +02:00
Karl Tauber
c1a9f48e6b SwingX: JXBusyLabel support (#8) 2019-10-18 13:26:30 +02:00
Karl Tauber
3f7215c602 update to Gradle 5.6.3
./gradlew wrapper --gradle-version=5.6.3
2019-10-18 10:34:39 +02:00
Karl Tauber
8b5e3e344a SwingX: JXHeader support (#8) 2019-10-18 10:33:05 +02:00
Karl Tauber
212ff012d6 SwingX: JXTaskPaneContainer and JXTaskPane support (#8) 2019-10-18 10:31:24 +02:00
Karl Tauber
7c77b857f6 SwingX: added test app 2019-10-17 12:09:22 +02:00
Karl Tauber
423c01074a SwingX: flatlaf-swingx subproject created; JXHyperlink support (#8) 2019-10-17 11:21:23 +02:00
Karl Tauber
2dbd584e28 use KeyEventPostProcessor instead of AWTEventListener for listening for Alt key pressed (similar to WindowLookAndFeel) (#4) 2019-10-16 19:42:55 +02:00
Karl Tauber
250f435ceb build.gradle.kts: moved jcenter to root script 2019-10-16 19:39:41 +02:00
Karl Tauber
fa4e409555 ToolBar: disable focusability of buttons in toolbar 2019-10-15 19:00:51 +02:00
Karl Tauber
dfc3b7c796 README.md: intro updated 2019-10-15 11:40:19 +02:00
Karl Tauber
41df9859ad ComboBox: use small border if used as table editor 2019-10-15 10:41:28 +02:00
Karl Tauber
a8b8cbdf8c FlatTestFrame: reduced duplicate code 2019-10-14 17:55:38 +02:00
Karl Tauber
fe2909c56a Demo: build.gradle.kts: added bintray upload 2019-10-14 10:59:45 +02:00
Karl Tauber
3a2fe06c34 README.md: added Maven Central coordinates 2019-10-13 22:54:41 +02:00
Karl Tauber
873e8604ce added developer information to Maven POM for Maven Central publishing 2019-10-13 21:37:49 +02:00
108 changed files with 5945 additions and 843 deletions

View File

@@ -1,6 +1,67 @@
FlatLaf Change Log
==================
## 0.18
- TextField and TextArea: Do not apply minimum width if `columns` property is
greater than zero.
- TabbedPane: In scroll-tab-layout, the separator line now spans the whole width
and is no longer interrupted by the scroll buttons.
- TabbedPane: Content pane is no longer opaque. Use antialiasing for painting
separator and content border.
- ToolTip: Use anti-aliasing to render multi-line tooltips.
- JIDE Common Layer: Support `JideTabbedPane`.
## 0.17
- CheckBox: Support painting a third state (set client property
"JButton.selectedState" to "indeterminate").
- `TriStateCheckBox` component added (see [FlatLaf Extras](flatlaf-extras)).
- Made `JComboBox`, `JProgressBar`, `JSpinner` and `JXDatePicker` non-opaque.
`JPasswordField`, `JScrollPane` and `JTextField` are non-opaque if they have
an outside focus border (e.g. IntelliJ and Darcula themes). (issues #20 and
#17)
- Button: Hover and pressed background colors are now derived from actual button
background color. (issue #21)
- Table: Fixed missing upper right corner (e.g. in SwingX JXTable with column
control visible).
## 0.16
- Made some fixes for right-to-left support in ComboBox, Slider and ToolTip.
(issue #18)
- Fixed Java 9 module descriptor (broken since 0.14).
- Made `JButton`, `JCheckBox`, `JRadioButton`, `JToggleButton` and `JSlider`
non-opaque. (issue #20)
## 0.15
- ToolTip: Improved styling of dark tooltips (darker background, no border).
- ToolTip: Fixed colors in tooltips of disabled components. (issue #15)
- ComboBox: Fixed NPE in combobox with custom renderer after switching to
FlatLaf. (issue #16; regression in 0.14)
## 0.14
- ComboBox: Use small border if used as table editor.
- ToolBar: Disable focusability of buttons in toolbar.
- OptionPane: Fixed rendering of longer HTML text. (issue #12)
- EditorPane and TextPane: Fixed font and text color when using HTML content.
(issue #9)
- ComboBox: Fixed `StackOverflowError` when switching LaF. (issue #14)
- SwingX: Support `JXBusyLabel`, `JXDatePicker`, `JXHeader`, `JXHyperlink`,
`JXMonthView`, `JXTaskPaneContainer` and `JXTaskPane`. (issue #8)
## 0.13
- Added developer information to Maven POM for Maven Central publishing.
## 0.12
- Support Linux. (issue #2)

View File

@@ -1,15 +1,15 @@
FlatLaf - Flat Look and Feel
============================
**FlatLaf** is a modern open-source cross-platform Look and Feel for Java
desktop applications.
**FlatLaf** is a modern **open-source** cross-platform Look and Feel for Java
Swing desktop applications.
It looks mostly "flat" (no shadows or gradients), clean, simple and elegant.
It looks almost flat (no shadows or gradients), clean, simple and elegant.
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
scales on **HiDPI** displays and runs on Java 8 or newer.
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
IntelliJ IDEA 2019.2+ and uses mostly the same colors and icons.
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
![Flat Light Demo](images/FlatLightDemo.png)
@@ -28,9 +28,25 @@ Requires Java 8 or newer.
Download
--------
FlatLaf binaries are available on **JCenter** and **Maven Central**.
If you use Maven or Gradle, add a dependency with following coordinates to your
build script:
groupId: com.formdev
artifactId: flatlaf
version: 0.18
Otherwise download `flatlaf-<version>.jar` here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)
Download from JCenter and Maven Central is coming soon.
Addons
------
- [SwingX](flatlaf-swingx)
- [JIDE Common Layer](https://github.com/jidesoft/jide-oss)
Documentation

View File

@@ -14,7 +14,13 @@
* limitations under the License.
*/
version = "0.12"
version = "0.18"
allprojects {
repositories {
jcenter()
}
}
// check required Java version
if( JavaVersion.current() < JavaVersion.VERSION_1_8 )

View File

@@ -22,10 +22,6 @@ plugins {
id( "com.jfrog.bintray" ) version "1.8.4"
}
repositories {
jcenter()
}
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
sourceSets {
create( "module-info" ) {
@@ -38,17 +34,19 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
}
}
dependencies {
testImplementation( "com.miglayout:miglayout-swing:5.2" )
testImplementation( "com.jgoodies:jgoodies-forms:1.9.0" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
named<JavaCompile>( "compileModuleInfoJava" ) {
sourceCompatibility = "9"
@@ -117,6 +115,14 @@ publishing {
}
}
developers {
developer {
name.set( "Karl Tauber" )
organization.set( "FormDev Software GmbH" )
organizationUrl.set( "https://www.formdev.com/" )
}
}
scm {
url.set( "https://github.com/JFormDesigner/FlatLaf" )
}

View File

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

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf;
/**
* A Flat LaF that has a dark color scheme and looks like Darcula LaF.
*
* The UI defaults are loaded from FlatDarculaLaf.properties, FlatDarkLaf.properties and FlatLaf.properties
*
* @author Karl Tauber
*/
public class FlatDarculaLaf

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf;
/**
* A Flat LaF that has a dark color scheme.
*
* The UI defaults are loaded from FlatDarkLaf.properties and FlatLaf.properties
*
* @author Karl Tauber
*/
public class FlatDarkLaf
@@ -37,4 +39,9 @@ public class FlatDarkLaf
public String getDescription() {
return "Flat Dark Look and Feel";
}
@Override
public boolean isDark() {
return true;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf;
import java.io.InputStream;
/**
* Addon for FlatLaf UI defaults.
*
* Allows loading of additional .properties files from addon JARs.
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
*
* If you extend this class in a addon JAR, you also have to add a text file named
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
* to the addon JAR. The file must contain a single line with the class name.
*
* See 'flatlaf-swingx' addon for an example
*
* @author Karl Tauber
*/
public abstract class FlatDefaultsAddon
{
/**
* Finds an addon .properties file for the given LaF class and returns
* it as input stream. Or {@code null} if not found.
*/
public abstract InputStream getDefaults( Class<?> lafClass );
}

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf;
/**
* A Flat LaF that has a light color scheme and looks like IntelliJ LaF.
*
* The UI defaults are loaded from FlatIntelliJLaf.properties, FlatLightLaf.properties and FlatLaf.properties
*
* @author Karl Tauber
*/
public class FlatIntelliJLaf

View File

@@ -16,29 +16,19 @@
package com.formdev.flatlaf;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Insets;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
@@ -47,16 +37,9 @@ import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ScaledNumber;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -68,17 +51,12 @@ import com.formdev.flatlaf.util.UIScale;
public abstract class FlatLaf
extends BasicLookAndFeel
{
private static final String VARIABLE_PREFIX = "@";
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?";
private static final String GLOBAL_PREFIX = "*.";
private BasicLookAndFeel base;
private String desktopPropertyName;
private PropertyChangeListener desktopPropertyListener;
private AWTEventListener mnemonicListener;
private KeyEventPostProcessor mnemonicListener;
private static boolean altKeyPressed;
public static boolean install( LookAndFeel newLookAndFeel ) {
@@ -96,6 +74,8 @@ public abstract class FlatLaf
return getName();
}
public abstract boolean isDark();
@Override
public boolean isNativeLookAndFeel() {
return true;
@@ -114,10 +94,11 @@ public abstract class FlatLaf
// add mnemonic listener
mnemonicListener = e -> {
if( e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT )
if( e.getKeyCode() == KeyEvent.VK_ALT )
altKeyChanged( e.getID() == KeyEvent.KEY_PRESSED );
return false;
};
Toolkit.getDefaultToolkit().addAWTEventListener( mnemonicListener, AWTEvent.KEY_EVENT_MASK );
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( mnemonicListener );
// listen to desktop property changes to update UI if system font or scaling changes
if( SystemInfo.IS_WINDOWS ) {
@@ -149,7 +130,7 @@ public abstract class FlatLaf
// remove mnemonic listener
if( mnemonicListener != null ) {
Toolkit.getDefaultToolkit().removeAWTEventListener( mnemonicListener );
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor( mnemonicListener );
mnemonicListener = null;
}
@@ -205,7 +186,7 @@ public abstract class FlatLaf
Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null;
initFonts( defaults );
loadDefaultsFromProperties( defaults );
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), defaults );
// use Aqua MenuBarUI if Mac screen menubar is enabled
if( useScreenMenuBar )
@@ -250,264 +231,8 @@ public abstract class FlatLaf
defaults.put( "MenuItem.acceleratorFont", uiFont );
}
/**
* Load properties associated to Flat LaF classes and add to UI defaults.
*
* Each class that extend this class may have its own .properties file
* in the same package as the class. Properties from superclasses are loaded
* first to give subclasses a chance to override defaults.
* E.g. if running FlatDarkLaf, then the FlatLaf.properties is loaded first
* and FlatDarkLaf.properties loaded second.
*/
private void loadDefaultsFromProperties( UIDefaults defaults ) {
// determine classes in class hierarchy in reverse order
ArrayList<Class<?>> lafClasses = new ArrayList<>();
for( Class<?> lafClass = getClass();
FlatLaf.class.isAssignableFrom( lafClass );
lafClass = lafClass.getSuperclass() )
{
lafClasses.add( 0, lafClass );
}
try {
// load properties files
Properties properties = new Properties();
for( Class<?> lafClass : lafClasses ) {
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null )
properties.load( in );
}
}
Function<String, String> resolver = value -> {
return resolveValue( properties, value );
};
// get globals, which override all other defaults that end with same suffix
HashMap<String, Object> globals = new HashMap<>();
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( !key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver ) );
}
// override UI defaults with globals
for( Object key : defaults.keySet() ) {
if( key instanceof String && ((String)key).contains( "." ) ) {
String skey = (String) key;
String globalKey = skey.substring( skey.lastIndexOf( '.' ) + 1 );
Object globalValue = globals.get( globalKey );
if( globalValue != null )
defaults.put( key, globalValue );
}
}
// add non-global properties to UI defaults
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( key.startsWith( VARIABLE_PREFIX ) || key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
defaults.put( key, parseValue( key, value, resolver ) );
}
} catch( IOException ex ) {
ex.printStackTrace();
}
}
private String resolveValue( Properties properties, String value ) {
if( !value.startsWith( VARIABLE_PREFIX ) )
return value;
if( value.startsWith( REF_PREFIX ) )
value = value.substring( REF_PREFIX.length() );
boolean optional = false;
if( value.startsWith( OPTIONAL_PREFIX ) ) {
value = value.substring( OPTIONAL_PREFIX.length() );
optional = true;
}
String newValue = properties.getProperty( value );
if( newValue == null ) {
if( optional )
return "null";
System.err.println( "variable or reference '" + value + "' not found" );
throw new IllegalArgumentException( value );
}
return resolveValue( properties, newValue );
}
private Object parseValue( String key, String value, Function<String, String> resolver ) {
value = value.trim();
// null, false, true
switch( value ) {
case "null": return null;
case "false": return false;
case "true": return true;
}
// borders
if( key.endsWith( ".border" ) || key.endsWith( "Border" ) )
return parseBorder( value, resolver );
// icons
if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
return parseInstance( value );
// insets
if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
return parseInsets( value );
// scaled number
ScaledNumber scaledNumber = parseScaledNumber( key, value );
if( scaledNumber != null )
return scaledNumber;
// size
if( key.endsWith( "Size" ) && !key.equals( "SplitPane.dividerSize" ))
return parseSize( value );
// width, height
if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
return parseInteger( value, true );
// colors
ColorUIResource color = parseColor( value, false );
if( color != null )
return color;
// integer
Integer integer = parseInteger( value, false );
if( integer != null )
return integer;
// string
return value;
}
private Object parseBorder( String value, Function<String, String> resolver ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor]
List<String> parts = split( value, ',' );
Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() == 5)
? parseColor( resolver.apply( parts.get( 4 ) ), true )
: null;
return (LazyValue) t -> {
return (lineColor != null)
? new FlatLineBorder( insets, lineColor )
: new FlatEmptyBorder( insets );
};
} else
return parseInstance( value );
}
private Object parseInstance( String value ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private Insets parseInsets( String value ) {
List<String> numbers = split( value, ',' );
try {
return new InsetsUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ),
Integer.parseInt( numbers.get( 2 ) ),
Integer.parseInt( numbers.get( 3 ) ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid insets '" + value + "'" );
throw ex;
}
}
private Dimension parseSize( String value ) {
List<String> numbers = split( value, ',' );
try {
return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid size '" + value + "'" );
throw ex;
}
}
private ColorUIResource parseColor( String value, boolean reportError ) {
try {
int rgb = Integer.parseInt( value, 16 );
if( value.length() == 6 )
return new ColorUIResource( rgb );
if( value.length() == 8 )
return new ColorUIResource( new Color( rgb, true ) );
if( reportError )
throw new NumberFormatException( value );
} catch( NumberFormatException ex ) {
if( reportError ) {
System.err.println( "invalid color '" + value + "'" );
throw ex;
}
// not a color --> ignore
}
return null;
}
private Integer parseInteger( String value, boolean reportError ) {
try {
return Integer.parseInt( value );
} catch( NumberFormatException ex ) {
if( reportError ) {
System.err.println( "invalid integer '" + value + "'" );
throw ex;
}
}
return null;
}
private ScaledNumber parseScaledNumber( String key, String value ) {
if( !key.equals( "OptionPane.buttonMinimumWidth" ) &&
!key.equals( "SplitPane.oneTouchButtonSize" ) &&
!key.equals( "SplitPane.oneTouchButtonOffset" ) )
return null; // not supported
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid integer '" + value + "'" );
throw ex;
}
}
public static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>();
int delimIndex = str.indexOf( delim );
int index = 0;
while( delimIndex >= 0 ) {
strs.add( str.substring( index, delimIndex ) );
index = delimIndex + 1;
delimIndex = str.indexOf( delim, index );
}
strs.add( str.substring( index ) );
return strs;
return UIDefaultsLoader.split( str, delim );
}
private static void reSetLookAndFeel() {

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf;
/**
* A Flat LaF that has a light color scheme.
*
* The UI defaults are loaded from FlatLightLaf.properties and FlatLaf.properties
*
* @author Karl Tauber
*/
public class FlatLightLaf
@@ -37,4 +39,9 @@ public class FlatLightLaf
public String getDescription() {
return "Flat Light Look and Feel";
}
@Override
public boolean isDark() {
return false;
}
}

View File

@@ -0,0 +1,407 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function;
import javax.swing.UIDefaults;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.InsetsUIResource;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ColorFunctions;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.ScaledNumber;
/**
* Load UI defaults from properties files associated to Flat LaF classes and add to UI defaults.
*
* Each class that extend the LaF class may have its own .properties file
* in the same package as the class. Properties from superclasses are loaded
* first to give subclasses a chance to override defaults.
* E.g. if running FlatDarkLaf, then the FlatLaf.properties is loaded first
* and FlatDarkLaf.properties loaded second.
*
* @author Karl Tauber
*/
class UIDefaultsLoader
{
private static final String TYPE_PREFIX = "{";
private static final String TYPE_PREFIX_END = "}";
private static final String VARIABLE_PREFIX = "@";
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?";
private static final String GLOBAL_PREFIX = "*.";
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, UIDefaults defaults ) {
// determine classes in class hierarchy in reverse order
ArrayList<Class<?>> lafClasses = new ArrayList<>();
for( Class<?> lafClass = lookAndFeelClass;
FlatLaf.class.isAssignableFrom( lafClass );
lafClass = lafClass.getSuperclass() )
{
lafClasses.add( 0, lafClass );
}
try {
// load properties files
Properties properties = new Properties();
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
for( Class<?> lafClass : lafClasses ) {
// load core properties
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null )
properties.load( in );
}
// load properties from addons
for( FlatDefaultsAddon addon : addonLoader ) {
try( InputStream in = addon.getDefaults( lafClass ) ) {
if( in != null )
properties.load( in );
}
}
}
Function<String, String> resolver = value -> {
return resolveValue( properties, value );
};
// get globals, which override all other defaults that end with same suffix
HashMap<String, Object> globals = new HashMap<>();
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( !key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
try {
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
}
// override UI defaults with globals
for( Object key : defaults.keySet() ) {
if( key instanceof String && ((String)key).contains( "." ) ) {
String skey = (String) key;
String globalKey = skey.substring( skey.lastIndexOf( '.' ) + 1 );
Object globalValue = globals.get( globalKey );
if( globalValue != null )
defaults.put( key, globalValue );
}
}
// add non-global properties to UI defaults
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( key.startsWith( VARIABLE_PREFIX ) || key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
try {
defaults.put( key, parseValue( key, value, resolver ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
}
} catch( IOException ex ) {
ex.printStackTrace();
}
}
private static void logParseError( String key, String value, RuntimeException ex ) {
System.err.println( "Failed to parse: '" + key + '=' + value + '\'' );
System.err.println( " " + ex.getMessage() );
}
private static String resolveValue( Properties properties, String value ) {
if( !value.startsWith( VARIABLE_PREFIX ) )
return value;
if( value.startsWith( REF_PREFIX ) )
value = value.substring( REF_PREFIX.length() );
boolean optional = false;
if( value.startsWith( OPTIONAL_PREFIX ) ) {
value = value.substring( OPTIONAL_PREFIX.length() );
optional = true;
}
String newValue = properties.getProperty( value );
if( newValue == null ) {
if( optional )
return "null";
throw new IllegalArgumentException( "variable or reference '" + value + "' not found" );
}
return resolveValue( properties, newValue );
}
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDNUMBER }
private static Object parseValue( String key, String value, Function<String, String> resolver ) {
value = value.trim();
// null, false, true
switch( value ) {
case "null": return null;
case "false": return false;
case "true": return true;
}
ValueType valueType = ValueType.UNKNOWN;
// check whether value type is specified in the value
if( value.startsWith( TYPE_PREFIX ) ) {
int end = value.indexOf( TYPE_PREFIX_END );
if( end != -1 ) {
try {
String typeStr = value.substring( TYPE_PREFIX.length(), end );
valueType = ValueType.valueOf( typeStr.toUpperCase( Locale.ENGLISH ) );
// remove type from value
value = value.substring( end + TYPE_PREFIX_END.length() );
} catch( IllegalArgumentException ex ) {
// ignore
}
}
}
// determine value type from key
if( valueType == ValueType.UNKNOWN ) {
if( key.endsWith( ".border" ) || key.endsWith( "Border" ) )
valueType = ValueType.BORDER;
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
valueType = ValueType.ICON;
else if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
valueType = ValueType.INSETS;
else if( key.endsWith( "Size" ) )
valueType = ValueType.SIZE;
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
valueType = ValueType.INTEGER;
}
// parse value
switch( valueType ) {
case STRING: return value;
case INTEGER: return parseInteger( value, true );
case BORDER: return parseBorder( value, resolver );
case ICON: return parseInstance( value );
case INSETS: return parseInsets( value );
case SIZE: return parseSize( value );
case COLOR: return parseColor( value, true );
case SCALEDNUMBER: return parseScaledNumber( value );
case UNKNOWN:
default:
// colors
ColorUIResource color = parseColor( value, false );
if( color != null )
return color;
// integer
Integer integer = parseInteger( value, false );
if( integer != null )
return integer;
// string
return value;
}
}
private static Object parseBorder( String value, Function<String, String> resolver ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor]
List<String> parts = split( value, ',' );
Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() == 5)
? parseColor( resolver.apply( parts.get( 4 ) ), true )
: null;
return (LazyValue) t -> {
return (lineColor != null)
? new FlatLineBorder( insets, lineColor )
: new FlatEmptyBorder( insets );
};
} else
return parseInstance( value );
}
private static Object parseInstance( String value ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private static Insets parseInsets( String value ) {
List<String> numbers = split( value, ',' );
try {
return new InsetsUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ),
Integer.parseInt( numbers.get( 2 ) ),
Integer.parseInt( numbers.get( 3 ) ) );
} catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid insets '" + value + "'" );
}
}
private static Dimension parseSize( String value ) {
List<String> numbers = split( value, ',' );
try {
return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ) );
} catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid size '" + value + "'" );
}
}
private static ColorUIResource parseColor( String value, boolean reportError ) {
if( value.endsWith( ")" ) )
return parseColorFunctions( value, reportError );
try {
int rgb = Integer.parseInt( value, 16 );
if( value.length() == 6 )
return new ColorUIResource( rgb );
if( value.length() == 8 )
return new ColorUIResource( new Color( rgb, true ) );
if( reportError )
throw new NumberFormatException( value );
} catch( NumberFormatException ex ) {
if( reportError )
throw new IllegalArgumentException( "invalid color '" + value + "'" );
// not a color --> ignore
}
return null;
}
private static ColorUIResource parseColorFunctions( String value, boolean reportError ) {
int paramsStart = value.indexOf( '(' );
if( paramsStart < 0 ) {
if( reportError )
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
return null;
}
String function = value.substring( 0, paramsStart ).trim();
List<String> params = split( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
if( params.isEmpty() )
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
switch( function ) {
case "lighten": return parseColorLightenOrDarken( true, params, reportError );
case "darken": return parseColorLightenOrDarken( false, params, reportError );
}
throw new IllegalArgumentException( "unknown color function '" + value + "'" );
}
/**
* Syntax: lighten(amount[,options]) or darken(amount[,options])
* - amount: percentage 0-100%
* - options: [relative] [autoInverse]
*/
private static ColorUIResource parseColorLightenOrDarken( boolean lighten, List<String> params, boolean reportError ) {
int amount = parsePercentage( params.get( 0 ) );
boolean relative = false;
boolean autoInverse = false;
if( params.size() >= 2 ) {
String options = params.get( 1 );
relative = options.contains( "relative" );
autoInverse = options.contains( "autoInverse" );
}
return new DerivedColor( lighten
? new ColorFunctions.Lighten( amount, relative, autoInverse )
: new ColorFunctions.Darken( amount, relative, autoInverse ) );
}
private static int parsePercentage( String value ) {
if( !value.endsWith( "%" ) )
throw new NumberFormatException( "invalid percentage '" + value + "'" );
int val;
try {
val = Integer.parseInt( value.substring( 0, value.length() - 1 ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid percentage '" + value + "'" );
}
if( val < 0 || val > 100 )
throw new IllegalArgumentException( "percentage out of range (0-100%) '" + value + "'" );
return val;
}
private static Integer parseInteger( String value, boolean reportError ) {
try {
return Integer.parseInt( value );
} catch( NumberFormatException ex ) {
if( reportError )
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
return null;
}
private static ScaledNumber parseScaledNumber( String value ) {
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
}
static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>();
int delimIndex = str.indexOf( delim );
int index = 0;
while( delimIndex >= 0 ) {
strs.add( str.substring( index, delimIndex ) );
index = delimIndex + 1;
delimIndex = str.indexOf( delim, index );
}
strs.add( str.substring( index ) );
return strs;
}
}

View File

@@ -16,14 +16,18 @@
package com.formdev.flatlaf.icons;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* Icon for {@link javax.swing.JCheckBox}.
@@ -50,6 +54,7 @@ import com.formdev.flatlaf.ui.FlatButtonUI;
* @uiDefault CheckBox.icon.selectedPressedBackground Color optional
* @uiDefault CheckBox.icon.checkmarkColor Color
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color
* @uiDefault CheckBox.arc int
*
* @author Karl Tauber
*/
@@ -58,6 +63,7 @@ public class FlatCheckBoxIcon
{
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
protected final Color borderColor = UIManager.getColor( "CheckBox.icon.borderColor" );
protected final Color disabledBorderColor = UIManager.getColor( "CheckBox.icon.disabledBorderColor" );
@@ -84,7 +90,8 @@ public class FlatCheckBoxIcon
@Override
protected void paintIcon( Component c, Graphics2D g2 ) {
boolean selected = (c instanceof AbstractButton) ? ((AbstractButton)c).isSelected() : false;
boolean indeterminate = c instanceof JComponent && clientPropertyEquals( (JComponent) c, SELECTED_STATE, SELECTED_STATE_INDETERMINATE );
boolean selected = indeterminate || (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
// paint focused border
if( c.hasFocus() && focusWidth > 0 ) {
@@ -102,33 +109,40 @@ public class FlatCheckBoxIcon
paintBorder( g2 );
// paint background
g2.setColor( FlatButtonUI.buttonStateColor( c,
FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
selected ? selectedBackground : background,
disabledBackground,
focusedBackground,
selected && selectedHoverBackground != null ? selectedHoverBackground : hoverBackground,
selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ) );
selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ),
background );
paintBackground( g2 );
// paint checkmark
if( selected ) {
if( selected || indeterminate ) {
g2.setColor( c.isEnabled() ? checkmarkColor : disabledCheckmarkColor );
paintCheckmark( g2 );
if( indeterminate )
paintIndeterminate( g2 );
else
paintCheckmark( g2 );
}
}
protected void paintFocusBorder( Graphics2D g2 ) {
// the outline focus border is painted outside of the icon
int wh = ICON_SIZE - 1 + (focusWidth * 2);
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, 8, 8 );
int arcwh = (arc + focusWidth) * 2;
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
}
protected void paintBorder( Graphics2D g2 ) {
g2.fillRoundRect( 1, 0, 14, 14, 4, 4 );
int arcwh = arc * 2;
g2.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
}
protected void paintBackground( Graphics2D g2 ) {
g2.fillRoundRect( 2, 1, 12, 12, 3, 3 );
int arcwh = (arc * 2) - 1;
g2.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
}
protected void paintCheckmark( Graphics2D g2 ) {
@@ -140,4 +154,8 @@ public class FlatCheckBoxIcon
g2.setStroke( new BasicStroke( 1.9f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
g2.draw( path );
}
protected void paintIndeterminate( Graphics2D g2 ) {
g2.fill( new RoundRectangle2D.Float( 3.75f, 5.75f, 8.5f, 2.5f, 2f, 2f ) );
}
}

View File

@@ -24,6 +24,7 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* Help button icon for {@link javax.swing.JButton}.
@@ -99,12 +100,12 @@ public class FlatHelpButtonIcon
g2.fill( new Ellipse2D.Float( focusWidth + 0.5f, focusWidth + 0.5f, 21, 21 ) );
// paint background
g2.setColor( FlatButtonUI.buttonStateColor( c,
FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
background,
disabledBackground,
focusedBackground,
hoverBackground,
pressedBackground ) );
pressedBackground ), background );
g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) );
// paint question mark

View File

@@ -157,7 +157,7 @@ public class FlatArrowButton
g.translate( -x, -y );
}
public static Shape createArrowShape( int direction, boolean chevron, int w, int h ) {
public static Shape createArrowShape( int direction, boolean chevron, float w, float h ) {
switch( direction ) {
case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h );
case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 );

View File

@@ -23,7 +23,6 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Paint;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
@@ -72,9 +71,10 @@ public class FlatBorder
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = getFocusWidth();
boolean isCellEditor = FlatUIUtils.isTableCellEditor( c );
float focusWidth = isCellEditor ? 0 : getFocusWidth();
float borderWidth = getBorderWidth( c );
float arc = getArc();
float arc = isCellEditor ? 0 : getArc();
if( isFocused( c ) ) {
g2.setColor( getFocusColor( c ) );
@@ -82,7 +82,7 @@ public class FlatBorder
getLineWidth() + scale( (float) innerFocusWidth ), arc );
}
g2.setPaint( getBorderColor( c ) );
g2.setColor( getBorderColor( c ) );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, borderWidth, arc );
} finally {
g2.dispose();
@@ -93,7 +93,7 @@ public class FlatBorder
return focusColor;
}
protected Paint getBorderColor( Component c ) {
protected Color getBorderColor( Component c ) {
boolean enabled = c.isEnabled() && (!(c instanceof JTextComponent) || ((JTextComponent)c).isEditable());
return enabled
? (isFocused( c ) ? focusedBorderColor : borderColor)
@@ -134,7 +134,8 @@ public class FlatBorder
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
float ow = getFocusWidth() + getLineWidth();
boolean isCellEditor = FlatUIUtils.isTableCellEditor( c );
float ow = (isCellEditor ? 0 : getFocusWidth()) + getLineWidth();
insets = super.getBorderInsets( c, insets );
insets.top = Math.round( scale( (float) insets.top ) + ow );

View File

@@ -21,7 +21,6 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Paint;
import javax.swing.JButton;
import javax.swing.UIManager;
import javax.swing.plaf.UIResource;
@@ -68,7 +67,7 @@ public class FlatButtonBorder
}
@Override
protected Paint getBorderColor( Component c ) {
protected Color getBorderColor( Component c ) {
boolean def = FlatButtonUI.isDefaultButton( c );
return FlatButtonUI.buttonStateColor( c,
def ? defaultBorderColor : borderColor,

View File

@@ -131,6 +131,7 @@ public class FlatButtonUI
defaults_initialized = true;
}
LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
MigLayoutVisualPadding.install( b, focusWidth );
@@ -169,15 +170,16 @@ public class FlatButtonUI
@Override
public void update( Graphics g, JComponent c ) {
if( isHelpButton( c ) ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() )
FlatUIUtils.paintParentBackground( g, c );
if( isHelpButton( c ) ) {
helpButtonIcon.paintIcon( c, g, 0, 0 );
return;
}
if( c.isOpaque() && isContentAreaFilled( c ) ) {
FlatUIUtils.paintParentBackground( g, c );
if( isContentAreaFilled( c ) ) {
Color background = getBackground( c );
if( background != null ) {
Graphics2D g2 = (Graphics2D) g.create();
@@ -188,7 +190,7 @@ public class FlatButtonUI
float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (border instanceof FlatButtonBorder || isToolBarButton( c )) ? scale( (float) this.arc ) : 0;
g2.setColor( background );
FlatUIUtils.setColor( g2, background, isDefaultButton(c) ? defaultBackground : c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();
@@ -218,7 +220,7 @@ public class FlatButtonUI
paintText( g, b, textRect, text, b.isEnabled() ? getForeground( b ) : disabledText );
}
static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
FontMetrics fm = b.getFontMetrics( b.getFont() );
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
@@ -40,6 +41,7 @@ import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
@@ -122,6 +124,8 @@ public class FlatComboBoxUI
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( comboBox, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
arrowType = UIManager.getString( "Component.arrowType" );
@@ -208,11 +212,14 @@ public class FlatComboBoxUI
String propertyName = e.getPropertyName();
if( editor != null &&
((source == comboBox && (propertyName == "background" || propertyName == "foreground")) ||
((source == comboBox && propertyName == "foreground") ||
(source == editor && propertyName == "enabled")) )
{
// fix editor component colors
updateEditorColors();
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
editor.applyComponentOrientation( o );
}
}
};
@@ -235,6 +242,12 @@ public class FlatComboBoxUI
if( editor instanceof JTextComponent )
((JTextComponent)editor).setBorder( BorderFactory.createEmptyBorder() );
// explicitly make non-opaque
if( editor instanceof JComponent )
((JComponent)editor).setOpaque( false );
editor.applyComponentOrientation( comboBox.getComponentOrientation() );
updateEditorColors();
}
@@ -243,7 +256,6 @@ public class FlatComboBoxUI
// is used, then the editor is updated after the combobox and the
// colors are again replaced with default colors
boolean enabled = editor.isEnabled();
editor.setBackground( FlatUIUtils.nonUIResource( enabled ? comboBox.getBackground() : disabledBackground ) );
editor.setForeground( FlatUIUtils.nonUIResource( (enabled || editor instanceof JTextComponent)
? comboBox.getForeground()
: disabledForeground ) );
@@ -265,44 +277,44 @@ public class FlatComboBoxUI
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
int arrowX = arrowButton.getX();
int arrowWidth = arrowButton.getWidth();
boolean enabled = comboBox.isEnabled();
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
int arrowX = arrowButton.getX();
int arrowWidth = arrowButton.getWidth();
boolean enabled = comboBox.isEnabled();
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
g2.setColor( comboBox.isEditable() ? buttonEditableBackground : buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint arrow button background
if( enabled ) {
g2.setColor( comboBox.isEditable() ? buttonEditableBackground : buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
if( comboBox.isEditable() ) {
// paint vertical line between value and arrow button
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
}
// paint vertical line between value and arrow button
if( comboBox.isEditable() ) {
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
}
paint( g, c );
@@ -315,6 +327,7 @@ public class FlatComboBoxUI
CellPaddingBorder.uninstall( renderer );
Component c = renderer.getListCellRendererComponent( listBox, comboBox.getSelectedItem(), -1, false, false );
c.setFont( comboBox.getFont() );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
CellPaddingBorder.uninstall( c );
boolean enabled = comboBox.isEnabled();
@@ -368,12 +381,20 @@ public class FlatComboBoxUI
@SuppressWarnings( { "rawtypes", "unchecked" } )
private class FlatComboPopup
extends BasicComboPopup
implements ListCellRenderer
{
private CellPaddingBorder paddingBorder;
FlatComboPopup( JComboBox combo ) {
super( combo );
// BasicComboPopup listens to JComboBox.componentOrientation and updates
// the component orientation of the list, scroller and popup, but when
// switching the LaF and a new combo popup is created, the component
// orientation is not applied.
ComponentOrientation o = comboBox.getComponentOrientation();
list.setComponentOrientation( o );
scroller.setComponentOrientation( o );
setComponentOrientation( o );
}
@Override
@@ -387,7 +408,13 @@ public class FlatComboBoxUI
comboBox.setPrototypeDisplayValue( prototype );
// make popup wider if necessary
pw = Math.max( pw, displaySize.width );
if( displaySize.width > pw ) {
int diff = displaySize.width - pw;
pw = displaySize.width;
if( !comboBox.getComponentOrientation().isLeftToRight() )
px -= diff;
}
return super.computePopupBounds( px, py, pw, ph );
}
@@ -405,7 +432,7 @@ public class FlatComboBoxUI
protected void configureList() {
super.configureList();
list.setCellRenderer( this );
list.setCellRenderer( new PopupListCellRenderer() );
}
@Override
@@ -416,27 +443,34 @@ public class FlatComboBoxUI
super.propertyChange( e );
if( e.getPropertyName() == "renderer" )
list.setCellRenderer( FlatComboPopup.this );
list.setCellRenderer( new PopupListCellRenderer() );
}
};
}
@Override
public Component getListCellRendererComponent( JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus )
//---- class PopupListCellRenderer -----
private class PopupListCellRenderer
implements ListCellRenderer
{
ListCellRenderer renderer = comboBox.getRenderer();
CellPaddingBorder.uninstall( renderer );
@Override
public Component getListCellRendererComponent( JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus )
{
ListCellRenderer renderer = comboBox.getRenderer();
CellPaddingBorder.uninstall( renderer );
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
if( c instanceof JComponent ) {
if( paddingBorder == null )
paddingBorder = new CellPaddingBorder( padding );
paddingBorder.install( (JComponent) c );
if( c instanceof JComponent ) {
if( paddingBorder == null )
paddingBorder = new CellPaddingBorder( padding );
paddingBorder.install( (JComponent) c );
}
return c;
}
return c;
}
}

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicEditorPaneUI;
@@ -37,6 +38,8 @@ public class FlatEditorPaneUI
{
protected int minimumWidth;
private Object oldHonorDisplayProperties;
public static ComponentUI createUI( JComponent c ) {
return new FlatEditorPaneUI();
}
@@ -46,6 +49,17 @@ public class FlatEditorPaneUI
super.installDefaults();
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
}
@Override

View File

@@ -23,6 +23,7 @@ import java.awt.GridBagConstraints;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.plaf.basic.BasicOptionPaneUI;
import com.formdev.flatlaf.util.UIScale;
@@ -122,6 +123,10 @@ public class FlatOptionPaneUI
if( messagePadding > 0 )
cons.insets.bottom = UIScale.scale( messagePadding );
// disable line wrapping for HTML
if( msg instanceof String && BasicHTML.isHTMLString( (String) msg ) )
maxll = Integer.MAX_VALUE;
super.addMessageComponents( container, cons, msg, maxll, internallyCreated );
}

View File

@@ -19,15 +19,12 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -46,7 +43,7 @@ public class FlatPasswordFieldUI
protected int focusWidth;
protected int minimumWidth;
private Handler handler;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatPasswordFieldUI();
@@ -63,6 +60,8 @@ public class FlatPasswordFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth );
}
@@ -77,71 +76,42 @@ public class FlatPasswordFieldUI
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener( getHandler() );
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( getHandler() );
handler = null;
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
public Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@Override
protected void paintSafely( Graphics g ) {
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth );
super.paintSafely( g );
}
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
g2.setColor( c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, 0 );
} finally {
g2.dispose();
}
// background is painted elsewhere
}
@Override
public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( super.getPreferredSize( c ) );
return applyMinimumWidth( super.getPreferredSize( c ), c );
}
@Override
public Dimension getMinimumSize( JComponent c ) {
return applyMinimumWidth( super.getMinimumSize( c ) );
return applyMinimumWidth( super.getMinimumSize( c ), c );
}
private Dimension applyMinimumWidth( Dimension size ) {
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size;
}
//---- class Handler ------------------------------------------------------
private class Handler
implements FocusListener
{
@Override
public void focusGained( FocusEvent e ) {
getComponent().repaint();
}
@Override
public void focusLost( FocusEvent e ) {
getComponent().repaint();
}
}
}

View File

@@ -23,6 +23,7 @@ import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI;
import com.formdev.flatlaf.util.UIScale;
@@ -39,6 +40,13 @@ public class FlatProgressBarUI
return new FlatProgressBarUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( progressBar, "opaque", false );
}
@Override
protected Dimension getPreferredInnerHorizontal() {
return UIScale.scale( super.getPreferredInnerHorizontal() );

View File

@@ -66,6 +66,7 @@ public class FlatRadioButtonUI
defaults_initialized = true;
}
LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
MigLayoutVisualPadding.install( b, null );

View File

@@ -17,10 +17,8 @@
package com.formdev.flatlaf.ui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
@@ -29,10 +27,9 @@ import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.ScrollPaneLayout;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicScrollPaneUI;
/**
@@ -53,17 +50,14 @@ public class FlatScrollPaneUI
public void installUI( JComponent c ) {
super.installUI( c );
if( scrollpane.getLayout() instanceof UIResource )
scrollpane.setLayout( new FlatScrollPaneLayout() );
int focusWidth = UIManager.getInt( "Component.focusWidth" );
LookAndFeel.installProperty( c, "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( scrollpane, UIManager.getInt( "Component.focusWidth" ) );
MigLayoutVisualPadding.install( scrollpane, focusWidth );
}
@Override
public void uninstallUI( JComponent c ) {
if( scrollpane.getLayout() instanceof FlatScrollPaneLayout )
scrollpane.setLayout( new ScrollPaneLayout.UIResource() );
MigLayoutVisualPadding.uninstall( scrollpane );
super.uninstallUI( c );
@@ -169,27 +163,4 @@ public class FlatScrollPaneUI
scrollpane.repaint();
}
}
//---- class FlatScrollPaneLayout -----------------------------------------
private static class FlatScrollPaneLayout
extends ScrollPaneLayout
{
@Override
public void layoutContainer( Container parent ) {
super.layoutContainer( parent );
// increase height of vertical scroll bar so that it also fills the upper right corner
if( colHead != null && vsb != null && colHead.isVisible() && vsb.isVisible() ) {
Rectangle colHeadBounds = colHead.getBounds();
Rectangle vsbBounds = vsb.getBounds();
if( vsbBounds.y > colHeadBounds.y ) {
vsbBounds.height += (vsbBounds.y - colHeadBounds.y);
vsbBounds.y = colHeadBounds.y;
vsb.setBounds( vsbBounds );
}
}
}
}
}

View File

@@ -25,6 +25,7 @@ import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSliderUI;
@@ -96,6 +97,8 @@ public class FlatSliderUI
protected void installDefaults( JSlider slider ) {
super.installDefaults( slider );
LookAndFeel.installProperty( slider, "opaque", false );
trackWidth = UIManager.getInt( "Slider.trackWidth" );
thumbWidth = UIManager.getInt( "Slider.thumbWidth" );
@@ -170,9 +173,15 @@ public class FlatSliderUI
if( slider.getOrientation() == JSlider.HORIZONTAL ) {
float y = trackRect.y + (trackRect.height - tw) / 2f;
if( enabled && isRoundThumb() ) {
int cw = thumbRect.x + (thumbRect.width / 2) - trackRect.x;
coloredTrack = new RoundRectangle2D.Float( trackRect.x, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x + cw, y, trackRect.width - cw, tw, arc, arc );
if( slider.getComponentOrientation().isLeftToRight() ) {
int cw = thumbRect.x + (thumbRect.width / 2) - trackRect.x;
coloredTrack = new RoundRectangle2D.Float( trackRect.x, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x + cw, y, trackRect.width - cw, tw, arc, arc );
} else {
int cw = trackRect.x + trackRect.width - thumbRect.x - (thumbRect.width / 2);
coloredTrack = new RoundRectangle2D.Float( trackRect.x + trackRect.width - cw, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x, y, trackRect.width - cw, tw, arc, arc );
}
} else
track = new RoundRectangle2D.Float( trackRect.x, y, trackRect.width, tw, arc, arc );
} else {

View File

@@ -35,6 +35,7 @@ import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
@@ -88,6 +89,8 @@ public class FlatSpinnerUI
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( spinner, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
@@ -152,6 +155,13 @@ public class FlatSpinnerUI
@Override
protected JComponent createEditor() {
JComponent editor = super.createEditor();
// explicitly make non-opaque
editor.setOpaque( false );
JTextField textField = getEditorTextField( editor );
if( textField != null )
textField.setOpaque( false );
updateEditorColors();
return editor;
}
@@ -183,8 +193,6 @@ public class FlatSpinnerUI
// use non-UIResource colors because when SwingUtilities.updateComponentTreeUI()
// is used, then the text field is updated after the spinner and the
// colors are again replaced with default colors
textField.setBackground( FlatUIUtils.nonUIResource( spinner.isEnabled()
? spinner.getBackground() : disabledBackground ) );
textField.setForeground( FlatUIUtils.nonUIResource( spinner.getForeground() ) );
textField.setDisabledTextColor( FlatUIUtils.nonUIResource( disabledForeground ) );
}
@@ -225,45 +233,45 @@ public class FlatSpinnerUI
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
Component nextButton = getHandler().nextButton;
int arrowX = nextButton.getX();
int arrowWidth = nextButton.getWidth();
boolean enabled = spinner.isEnabled();
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
Component nextButton = getHandler().nextButton;
int arrowX = nextButton.getX();
int arrowWidth = nextButton.getWidth();
boolean enabled = spinner.isEnabled();
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow buttons background
if( enabled ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow buttons background
if( enabled ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow buttons
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow buttons
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
paint( g, c );
}
@@ -370,7 +378,6 @@ public class FlatSpinnerUI
@Override
public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case "background":
case "foreground":
case "enabled":
updateEditorColors();

View File

@@ -17,12 +17,19 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
@@ -108,7 +115,6 @@ public class FlatTabbedPaneUI
tabAreaInsets = scale( tabAreaInsets );
tabHeight = scale( tabHeight );
tabSelectionHeight = scale( tabSelectionHeight );
contentSeparatorHeight = scale( contentSeparatorHeight );
MigLayoutVisualPadding.install( tabPane, null );
}
@@ -135,7 +141,7 @@ public class FlatTabbedPaneUI
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( "JTabbedPane.hasFullBorder".equals( e.getPropertyName() ) ) {
if( TABBED_PANE_HAS_FULL_BORDER.equals( e.getPropertyName() ) ) {
tabPane.revalidate();
tabPane.repaint();
}
@@ -176,70 +182,45 @@ public class FlatTabbedPaneUI
@Override
protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) {
return super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3 // was added by superclass
+ (!isTopOrBottom( tabPlacement ) && isScrollTabLayout() ? contentSeparatorHeight : 0);
return super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3 /* was added by superclass */;
}
@Override
protected int calculateTabHeight( int tabPlacement, int tabIndex, int fontHeight ) {
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ )
+ (isTopOrBottom( tabPlacement ) && isScrollTabLayout() ? contentSeparatorHeight : 0);
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
}
/**
* The content border insets are used to create a separator between tabs and content.
* Except in scroll tab policy, where the separator is painted in paintTabArea().
* If client property JTabbedPane.hasFullBorder is true, then the content border insets
* are also used for the border.
*/
@Override
protected Insets getContentBorderInsets( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || (tabPane.getClientProperty( "JTabbedPane.hasFullBorder" ) == Boolean.TRUE);
int sh = contentSeparatorHeight;
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
if( isScrollTabLayout() )
insets.top = 0;
Insets contentBorderInsets = new Insets( 0, 0, 0, 0 );
rotateInsets( insets, contentBorderInsets, tabPlacement );
return contentBorderInsets;
}
@Override
protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) {
if( isScrollTabLayout() && !isTopOrBottom( tabPlacement ) ) {
float shift = contentSeparatorHeight / 2f;
return Math.round( tabPlacement == LEFT ? -shift : shift );
} else
return 0;
return 0;
}
@Override
protected int getTabLabelShiftY( int tabPlacement, int tabIndex, boolean isSelected ) {
if( isScrollTabLayout() && isTopOrBottom( tabPlacement ) ) {
float shift = contentSeparatorHeight / 2f;
return Math.round( tabPlacement == TOP ? -shift : shift );
} else
return 0;
return 0;
}
@Override
protected void paintTabArea( Graphics g, int tabPlacement, int selectedIndex ) {
if( isScrollTabLayout() ) {
// paint separator between tabs and content
Rectangle bounds = g.getClipBounds();
g.setColor( contentAreaColor );
public void update( Graphics g, JComponent c ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
int y = (tabPlacement == TOP) ? bounds.y + bounds.height - contentSeparatorHeight : bounds.y;
g.fillRect( bounds.x, y, bounds.x + bounds.width, contentSeparatorHeight );
} else {
int x = (tabPlacement == LEFT) ? bounds.x + bounds.width - contentSeparatorHeight : bounds.x;
g.fillRect( x, bounds.y, contentSeparatorHeight, bounds.y + bounds.height );
}
}
super.paintTabArea( g, tabPlacement, selectedIndex );
super.update( g, c );
}
@Override
@@ -275,19 +256,6 @@ public class FlatTabbedPaneUI
protected void paintTabBackground( Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected )
{
if( isScrollTabLayout() ) {
// make tab bounds smaller for separator between tabs and content
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
if( tabPlacement == BOTTOM )
y += contentSeparatorHeight;
h -= contentSeparatorHeight;
} else {
if( tabPlacement == RIGHT )
x += contentSeparatorHeight;
w -= contentSeparatorHeight;
}
}
// paint tab background
boolean enabled = tabPane.isEnabled();
g.setColor( enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
@@ -302,8 +270,38 @@ public class FlatTabbedPaneUI
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected )
{
if( !isSelected )
return;
if( isSelected )
paintTabSelection( g, tabPlacement, x, y, w, h );
}
protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
// increase clip bounds in scroll-tab-layout to paint over the separator line
Rectangle clipBounds = isScrollTabLayout() ? g.getClipBounds() : null;
if( clipBounds != null ) {
Rectangle newClipBounds = new Rectangle( clipBounds );
int contentSeparatorHeight = scale( this.contentSeparatorHeight );
switch( tabPlacement ) {
case TOP:
default:
newClipBounds.height += contentSeparatorHeight;
break;
case BOTTOM:
newClipBounds.y -= contentSeparatorHeight;
newClipBounds.height += contentSeparatorHeight;
break;
case LEFT:
newClipBounds.width += contentSeparatorHeight;
break;
case RIGHT:
newClipBounds.x -= contentSeparatorHeight;
newClipBounds.width += contentSeparatorHeight;
break;
}
g.setClip( newClipBounds );
}
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
@@ -330,13 +328,16 @@ public class FlatTabbedPaneUI
g.fillRect( x - contentInsets.right, y, tabSelectionHeight, h );
break;
}
if( clipBounds != null )
g.setClip( clipBounds );
}
/**
* Actually does the nearly the same as super.paintContentBorder() but
* - content pane is always opaque
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
* - not invoking paintContentBorder*Edge() methods
* - repaint selection
*/
@Override
protected void paintContentBorder( Graphics g, int tabPlacement, int selectedIndex ) {
@@ -377,9 +378,34 @@ public class FlatTabbedPaneUI
h -= (y - insets.top);
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
// paint content area
g.setColor( contentAreaColor );
g.fillRect( x, y, w, h );
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 );
((Graphics2D)g).fill( path );
// repaint selection in scroll-tab-layout because it may be painted before
// the content border was painted (from BasicTabbedPaneUI$ScrollableTabPanel)
if( isScrollTabLayout() && selectedIndex >= 0 ) {
Component scrollableTabViewport = findComponentByClassName( tabPane,
BasicTabbedPaneUI.class.getName() + "$ScrollableTabViewport" );
if( scrollableTabViewport != null ) {
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
Shape oldClip = g.getClip();
g.setClip( scrollableTabViewport.getBounds() );
paintTabSelection( g, tabPlacement, tabRect.x, tabRect.y, tabRect.width, tabRect.height );
g.setClip( oldClip );
}
}
}
@Override
@@ -392,7 +418,17 @@ public class FlatTabbedPaneUI
return tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
}
private boolean isTopOrBottom( int tabPlacement ) {
return tabPlacement == TOP || tabPlacement == BOTTOM;
private Component findComponentByClassName( Container c, String className ) {
for( Component child : c.getComponents() ) {
if( className.equals( child.getClass().getName() ) )
return child;
if( child instanceof Container ) {
Component c2 = findComponentByClassName( (Container) child, className );
if( c2 != null )
return c2;
}
}
return null;
}
}

View File

@@ -21,6 +21,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
@@ -81,15 +82,19 @@ public class FlatTextAreaUI
@Override
public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( super.getPreferredSize( c ) );
return applyMinimumWidth( super.getPreferredSize( c ), c );
}
@Override
public Dimension getMinimumSize( JComponent c ) {
return applyMinimumWidth( super.getMinimumSize( c ) );
return applyMinimumWidth( super.getMinimumSize( c ), c );
}
private Dimension applyMinimumWidth( Dimension size ) {
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
// do not apply minimum width if JTextArea.columns is set
if( c instanceof JTextArea && ((JTextArea)c).getColumns() > 0 )
return size;
// Assume that text area is in a scroll pane (that displays the border)
// and subtract 1px border line width.
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding

View File

@@ -21,11 +21,12 @@ import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextFieldUI;
@@ -47,7 +48,7 @@ public class FlatTextFieldUI
protected int focusWidth;
protected int minimumWidth;
private Handler handler;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatTextFieldUI();
@@ -60,6 +61,8 @@ public class FlatTextFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth );
}
@@ -74,38 +77,51 @@ public class FlatTextFieldUI
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener( getHandler() );
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( getHandler() );
handler = null;
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
public Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@Override
protected void paintSafely( Graphics g ) {
paintBackground( g, getComponent(), focusWidth );
super.paintSafely( g );
}
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
// background is painted elsewhere
}
FlatUIUtils.paintParentBackground( g, c );
static void paintBackground( Graphics g, JTextComponent c, int focusWidth ) {
// do not paint background if:
// - not opaque and
// - border is not a flat border and
// - opaque was explicitly set (to false)
// (same behaviour as in AquaTextFieldUI)
if( !c.isOpaque() && !(c.getBorder() instanceof FlatBorder) && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
return;
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && focusWidth > 0 )
FlatUIUtils.paintParentBackground( g, c );
// paint background
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float fFocusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) focusWidth ) : 0;
g2.setColor( c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, 0 );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
} finally {
g2.dispose();
}
@@ -122,29 +138,18 @@ public class FlatTextFieldUI
}
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
// do not apply minimum width if JTextField.columns is set
if( c instanceof JTextField && ((JTextField)c).getColumns() > 0 )
return size;
Container parent = c.getParent();
if( parent instanceof JComboBox ||
parent instanceof JSpinner ||
(parent != null && parent.getParent() instanceof JSpinner) )
return size;
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size;
}
//---- class Handler ------------------------------------------------------
private class Handler
implements FocusListener
{
@Override
public void focusGained( FocusEvent e ) {
getComponent().repaint();
}
@Override
public void focusLost( FocusEvent e ) {
getComponent().repaint();
}
}
}

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextPaneUI;
@@ -37,6 +38,8 @@ public class FlatTextPaneUI
{
protected int minimumWidth;
private Object oldHonorDisplayProperties;
public static ComponentUI createUI( JComponent c ) {
return new FlatTextPaneUI();
}
@@ -46,6 +49,17 @@ public class FlatTextPaneUI
super.installDefaults();
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
}
@Override

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Component;
import java.awt.Insets;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
@@ -53,6 +55,29 @@ public class FlatToolBarUI
rolloverBorder = null;
}
@Override
protected ContainerListener createToolBarContListener() {
return new ToolBarContListener() {
@Override
public void componentAdded( ContainerEvent e ) {
super.componentAdded( e );
Component c = e.getChild();
if( c instanceof AbstractButton )
c.setFocusable( false );
}
@Override
public void componentRemoved( ContainerEvent e ) {
super.componentRemoved( e );
Component c = e.getChild();
if( c instanceof AbstractButton )
c.setFocusable( true );
}
};
}
@Override
protected Border createRolloverBorder() {
return getRolloverBorder();

View File

@@ -74,11 +74,14 @@ public class FlatToolTipUI
List<String> lines = FlatLaf.split( ((JToolTip)c).getTipText(), '\n' );
int x = insets.left;
int x2 = c.getWidth() - insets.right;
int y = insets.top - fm.getDescent();
int lineHeight = fm.getHeight();
JComponent comp = ((JToolTip)c).getComponent();
boolean leftToRight = (comp != null ? comp : c).getComponentOrientation().isLeftToRight();
for( String line : lines ) {
y += lineHeight;
g.drawString( line, x, y );
FlatUIUtils.drawString( c, g, line, leftToRight ? x : x2 - SwingUtilities.computeStringWidth( fm, line ), y );
}
} else
super.paint( g, c );

View File

@@ -17,13 +17,17 @@
package com.formdev.flatlaf.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
@@ -31,8 +35,10 @@ import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.function.Consumer;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.UIScale;
@@ -61,6 +67,20 @@ public class FlatUIUtils
r.height - insets.top - insets.bottom );
}
public static Dimension addInsets( Dimension dim, Insets insets ) {
return new Dimension(
dim.width + insets.left + insets.right,
dim.height + insets.top + insets.bottom );
}
public static Insets addInsets( Insets insets1, Insets insets2 ) {
return new Insets(
insets1.top + insets2.top,
insets1.left + insets2.left,
insets1.bottom + insets2.bottom,
insets1.right + insets2.right );
}
public static Color getUIColor( String key, int defaultColorRGB ) {
Color color = UIManager.getColor( key );
return (color != null) ? color : new Color( defaultColorRGB );
@@ -80,6 +100,10 @@ public class FlatUIUtils
return (c instanceof ColorUIResource) ? new Color( c.getRGB(), true ) : c;
}
public static boolean isTableCellEditor( Component c ) {
return c instanceof JComponent && Boolean.TRUE.equals( ((JComponent)c).getClientProperty( "JComboBox.isTableCellEditor" ) );
}
/**
* Sets rendering hints used for painting.
*/
@@ -89,6 +113,12 @@ public class FlatUIUtils
MAC_USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE );
}
public static void setColor( Graphics g, Color color, Color baseColor ) {
if( color instanceof DerivedColor )
color = ((DerivedColor)color).derive( baseColor );
g.setColor( color );
}
/**
* Draws a round rectangle.
*/
@@ -160,21 +190,52 @@ public class FlatUIUtils
}
private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) {
if( arc <= 0 )
return createRoundRectanglePath( x, y, width, height, arc, arc, arc, arc );
}
/**
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
*/
public static Path2D createRoundRectangle( float x, float y, float width, float height,
float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createRoundRectanglePath( x, y, width, height, arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight ), false );
path.append( createRoundRectanglePath( x + lineWidth, y + lineWidth, width - (lineWidth * 2), height - (lineWidth * 2),
arcTopLeft - lineWidth, arcTopRight - lineWidth, arcBottomLeft - lineWidth, arcBottomRight - lineWidth ), false );
return path;
}
/**
* Creates a filled rounded rectangle shape and allows specifying the radius or each corner.
*/
public static Shape createRoundRectanglePath( float x, float y, float width, float height,
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
if( arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0 && arcBottomRight <= 0 )
return new Rectangle2D.Float( x, y, width, height );
if( arcTopLeft < 0 )
arcTopLeft = 0;
if( arcTopRight < 0 )
arcTopRight = 0;
if( arcBottomLeft < 0 )
arcBottomLeft = 0;
if( arcBottomRight < 0 )
arcBottomRight = 0;
float x2 = x + width;
float y2 = y + height;
Path2D rect = new Path2D.Float();
rect.moveTo( x2 - arc, y );
rect.quadTo( x2, y, x2, y + arc );
rect.lineTo( x2, y2 - arc );
rect.quadTo( x2, y2, x2 - arc, y2 );
rect.lineTo( x + arc, y2 );
rect.quadTo( x, y2, x, y2 - arc );
rect.lineTo( x, y + arc );
rect.quadTo( x, y, x + arc, y );
rect.moveTo( x2 - arcTopRight, y );
rect.quadTo( x2, y, x2, y + arcTopRight );
rect.lineTo( x2, y2 - arcBottomRight );
rect.quadTo( x2, y2, x2 - arcBottomRight, y2 );
rect.lineTo( x + arcBottomLeft, y2 );
rect.quadTo( x, y2, x, y2 - arcBottomLeft );
rect.lineTo( x, y + arcTopLeft );
rect.quadTo( x, y, x + arcTopLeft, y );
rect.closePath();
return rect;
@@ -195,6 +256,22 @@ public class FlatUIUtils
}
/**
* Draws the given string at the specified location using text properties
* and anti-aliasing hints from the provided component.
*
* Use this method instead of Graphics.drawString() for correct anti-aliasing.
*
* Replacement for SwingUtilities2.drawString()
*/
public static void drawString( JComponent c, Graphics g, String text, int x, int y ) {
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, -1, x, y );
}
/**
* Draws the given string at the specified location underlining the specified
* character. The provided component is used to query text properties and
* anti-aliasing hints.
*
* Replacement for SwingUtilities2.drawStringUnderlineCharAt()
*/
public static void drawStringUnderlineCharAt( JComponent c, Graphics g,
@@ -203,15 +280,23 @@ public class FlatUIUtils
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
}
public static boolean hasOpaqueBeenExplicitlySet( JComponent c ) {
boolean oldOpaque = c.isOpaque();
LookAndFeel.installProperty( c, "opaque", !oldOpaque );
boolean explicitlySet = c.isOpaque() == oldOpaque;
LookAndFeel.installProperty( c, "opaque", oldOpaque );
return explicitlySet;
}
//---- class HoverListener ------------------------------------------------
public static class HoverListener
extends MouseAdapter
{
private final JComponent repaintComponent;
private final Component repaintComponent;
private final Consumer<Boolean> hoverChanged;
public HoverListener( JComponent repaintComponent, Consumer<Boolean> hoverChanged ) {
public HoverListener( Component repaintComponent, Consumer<Boolean> hoverChanged ) {
this.repaintComponent = repaintComponent;
this.hoverChanged = hoverChanged;
}
@@ -233,4 +318,26 @@ public class FlatUIUtils
repaintComponent.repaint();
}
}
//---- class RepaintFocusListener -----------------------------------------
public static class RepaintFocusListener
implements FocusListener
{
private final Component repaintComponent;
public RepaintFocusListener( Component repaintComponent ) {
this.repaintComponent = repaintComponent;
}
@Override
public void focusGained( FocusEvent e ) {
repaintComponent.repaint();
}
@Override
public void focusLost( FocusEvent e ) {
repaintComponent.repaint();
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.util;
import java.awt.Color;
/**
* Functions that modify colors.
*
* @author Karl Tauber
*/
public class ColorFunctions
{
public static Color applyFunctions( Color color, ColorFunction[] functions ) {
float[] hsl = HSLColor.fromRGB( color );
float alpha = color.getAlpha() / 255f;
for( ColorFunction function : functions )
function.apply( hsl );
return HSLColor.toRGB( hsl, alpha );
}
private static float clamp( float value ) {
return (value < 0)
? 0
: ((value > 100)
? 100
: value);
}
//---- interface ColorFunction --------------------------------------------
public interface ColorFunction {
void apply( float[] hsl );
}
//---- class Lighten ------------------------------------------------------
/**
* Increase the lightness of a color in the HSL color space by an absolute
* or relative amount.
*/
public static class Lighten
implements ColorFunction
{
private final float amount;
private final boolean relative;
private final boolean autoInverse;
public Lighten( float amount, boolean relative, boolean autoInverse ) {
this.amount = amount;
this.relative = relative;
this.autoInverse = autoInverse;
}
@Override
public void apply( float[] hsl ) {
float amount2 = autoInverse && shouldInverse( hsl ) ? -amount : amount;
hsl[2] = clamp( relative
? (hsl[2] * ((100 + amount2) / 100))
: (hsl[2] + amount2) );
}
protected boolean shouldInverse( float[] hsl ) {
return hsl[2] >= 50;
}
}
//---- class Darken -------------------------------------------------------
/**
* Decrease the lightness of a color in the HSL color space by an absolute
* or relative amount.
*/
public static class Darken
extends Lighten
{
public Darken( float amount, boolean relative, boolean autoInverse ) {
super( -amount, relative, autoInverse );
}
@Override
protected boolean shouldInverse( float[] hsl ) {
return hsl[2] < 50;
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.util;
import java.awt.Color;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
/**
* A (red) color that acts as a placeholder in UI defaults.
* The actual color is derived from another color,
* which is modified by the given color functions.
*
* @author Karl Tauber
*/
public class DerivedColor
extends ColorUIResource
{
private final ColorFunction[] functions;
public DerivedColor( ColorFunction... functions ) {
super( Color.red );
this.functions = functions;
}
public Color derive( Color baseColor ) {
return ColorFunctions.applyFunctions( baseColor, functions );
}
}

View File

@@ -0,0 +1,432 @@
/*
* From http://tips4java.wordpress.com/2009/07/05/hsl-color/
*
* License note on http://tips4java.wordpress.com/about/
* "You are free to use and/or modify any or all code posted on the
* Java Tips Weblog without restriction. A credit in the code comments
* would be nice, but not in any way mandatory."
*/
package com.formdev.flatlaf.util;
import java.awt.Color;
/**
* The HSLColor class provides methods to manipulate HSL (Hue, Saturation
* Luminance) values to create a corresponding Color object using the RGB
* ColorSpace.
*
* The HUE is the color, the Saturation is the purity of the color (with
* respect to grey) and Luminance is the brightness of the color (with respect
* to black and white)
*
* The Hue is specified as an angel between 0 - 360 degrees where red is 0,
* green is 120 and blue is 240. In between you have the colors of the rainbow.
* Saturation is specified as a percentage between 0 - 100 where 100 is fully
* saturated and 0 approaches gray. Luminance is specified as a percentage
* between 0 - 100 where 0 is black and 100 is white.
*
* In particular the HSL color space makes it easier change the Tone or Shade
* of a color by adjusting the luminance value.
*/
public class HSLColor
{
private final Color rgb;
private final float[] hsl;
private final float alpha;
/**
* Create a HSLColor object using an RGB Color object.
*
* @param rgb the RGB Color object
*/
public HSLColor(Color rgb)
{
this.rgb = rgb;
hsl = fromRGB( rgb );
alpha = rgb.getAlpha() / 255.0f;
}
/**
* Create a HSLColor object using individual HSL values and a default
* alpha value of 1.0.
*
* @param h is the Hue value in degrees between 0 - 360
* @param s is the Saturation percentage between 0 - 100
* @param l is the Lumanance percentage between 0 - 100
*/
public HSLColor(float h, float s, float l)
{
this(h, s, l, 1.0f);
}
/**
* Create a HSLColor object using individual HSL values.
*
* @param h the Hue value in degrees between 0 - 360
* @param s the Saturation percentage between 0 - 100
* @param l the Lumanance percentage between 0 - 100
* @param alpha the alpha value between 0 - 1
*/
public HSLColor(float h, float s, float l, float alpha)
{
hsl = new float[] {h, s, l};
this.alpha = alpha;
rgb = toRGB(hsl, alpha);
}
/**
* Create a HSLColor object using an an array containing the
* individual HSL values and with a default alpha value of 1.
*
* @param hsl array containing HSL values
*/
public HSLColor(float[] hsl)
{
this(hsl, 1.0f);
}
/**
* Create a HSLColor object using an an array containing the
* individual HSL values.
*
* @param hsl array containing HSL values
* @param alpha the alpha value between 0 - 1
*/
public HSLColor(float[] hsl, float alpha)
{
this.hsl = hsl;
this.alpha = alpha;
rgb = toRGB(hsl, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Hue value. The degrees specified is an absolute value.
*
* @param degrees - the Hue value between 0 - 360
* @return the RGB Color object
*/
public Color adjustHue(float degrees)
{
return toRGB(degrees, hsl[1], hsl[2], alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Luminance value. The percent specified is an absolute value.
*
* @param percent - the Luminance value between 0 - 100
* @return the RGB Color object
*/
public Color adjustLuminance(float percent)
{
return toRGB(hsl[0], hsl[1], percent, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Saturation value. The percent specified is an absolute value.
*
* @param percent - the Saturation value between 0 - 100
* @return the RGB Color object
*/
public Color adjustSaturation(float percent)
{
return toRGB(hsl[0], percent, hsl[2], alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Shade. Changing the shade will return a darker color. The percent
* specified is a relative value.
*
* @param percent - the value between 0 - 100
* @return the RGB Color object
*/
public Color adjustShade(float percent)
{
float multiplier = (100.0f - percent) / 100.0f;
float l = Math.max(0.0f, hsl[2] * multiplier);
return toRGB(hsl[0], hsl[1], l, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Tone. Changing the tone will return a lighter color. The percent
* specified is a relative value.
*
* @param percent - the value between 0 - 100
* @return the RGB Color object
*/
public Color adjustTone(float percent)
{
float multiplier = (100.0f + percent) / 100.0f;
float l = Math.min(100.0f, hsl[2] * multiplier);
return toRGB(hsl[0], hsl[1], l, alpha);
}
/**
* Get the Alpha value.
*
* @return the Alpha value.
*/
public float getAlpha()
{
return alpha;
}
/**
* Create a RGB Color object that is the complementary color of this
* HSLColor. This is a convenience method. The complementary color is
* determined by adding 180 degrees to the Hue value.
* @return the RGB Color object
*/
public Color getComplementary()
{
float hue = (hsl[0] + 180.0f) % 360.0f;
return toRGB(hue, hsl[1], hsl[2]);
}
/**
* Get the Hue value.
*
* @return the Hue value.
*/
public float getHue()
{
return hsl[0];
}
/**
* Get the HSL values.
*
* @return the HSL values.
*/
public float[] getHSL()
{
return hsl;
}
/**
* Get the Luminance value.
*
* @return the Luminance value.
*/
public float getLuminance()
{
return hsl[2];
}
/**
* Get the RGB Color object represented by this HDLColor.
*
* @return the RGB Color object.
*/
public Color getRGB()
{
return rgb;
}
/**
* Get the Saturation value.
*
* @return the Saturation value.
*/
public float getSaturation()
{
return hsl[1];
}
@Override
public String toString()
{
String toString =
"HSLColor[h=" + hsl[0] +
",s=" + hsl[1] +
",l=" + hsl[2] +
",alpha=" + alpha + "]";
return toString;
}
/**
* Convert a RGB Color to it corresponding HSL values.
*
* @return an array containing the 3 HSL values.
*/
public static float[] fromRGB(Color color)
{
// Get RGB values in the range 0 - 1
float[] rgb = color.getRGBColorComponents( null );
float r = rgb[0];
float g = rgb[1];
float b = rgb[2];
// Minimum and Maximum RGB values are used in the HSL calculations
float min = Math.min(r, Math.min(g, b));
float max = Math.max(r, Math.max(g, b));
// Calculate the Hue
float h = 0;
if (max == min)
h = 0;
else if (max == r)
h = ((60 * (g - b) / (max - min)) + 360) % 360;
else if (max == g)
h = (60 * (b - r) / (max - min)) + 120;
else if (max == b)
h = (60 * (r - g) / (max - min)) + 240;
// Calculate the Luminance
float l = (max + min) / 2;
// System.out.println(max + " : " + min + " : " + l);
// Calculate the Saturation
float s = 0;
if (max == min)
s = 0;
else if (l <= .5f)
s = (max - min) / (max + min);
else
s = (max - min) / (2 - max - min);
// System.out.println(new HSLColor( new float[] {h, s * 100, l * 100} ));
return new float[] {h, s * 100, l * 100};
}
/**
* Convert HSL values to a RGB Color with a default alpha value of 1.
* H (Hue) is specified as degrees in the range 0 - 360.
* S (Saturation) is specified as a percentage in the range 1 - 100.
* L (Lumanance) is specified as a percentage in the range 1 - 100.
*
* @param hsl an array containing the 3 HSL values
*
* @returns the RGB Color object
*/
public static Color toRGB(float[] hsl)
{
return toRGB(hsl, 1.0f);
}
/**
* Convert HSL values to a RGB Color.
* H (Hue) is specified as degrees in the range 0 - 360.
* S (Saturation) is specified as a percentage in the range 1 - 100.
* L (Lumanance) is specified as a percentage in the range 1 - 100.
*
* @param hsl an array containing the 3 HSL values
* @param alpha the alpha value between 0 - 1
*
* @returns the RGB Color object
*/
public static Color toRGB(float[] hsl, float alpha)
{
return toRGB(hsl[0], hsl[1], hsl[2], alpha);
}
/**
* Convert HSL values to a RGB Color with a default alpha value of 1.
*
* @param h Hue is specified as degrees in the range 0 - 360.
* @param s Saturation is specified as a percentage in the range 1 - 100.
* @param l Lumanance is specified as a percentage in the range 1 - 100.
*
* @returns the RGB Color object
*/
public static Color toRGB(float h, float s, float l)
{
return toRGB(h, s, l, 1.0f);
}
/**
* Convert HSL values to a RGB Color.
*
* @param h Hue is specified as degrees in the range 0 - 360.
* @param s Saturation is specified as a percentage in the range 1 - 100.
* @param l Lumanance is specified as a percentage in the range 1 - 100.
* @param alpha the alpha value between 0 - 1
*
* @returns the RGB Color object
*/
public static Color toRGB(float h, float s, float l, float alpha)
{
if (s <0.0f || s > 100.0f)
{
String message = "Color parameter outside of expected range - Saturation";
throw new IllegalArgumentException( message );
}
if (l <0.0f || l > 100.0f)
{
String message = "Color parameter outside of expected range - Luminance";
throw new IllegalArgumentException( message );
}
if (alpha <0.0f || alpha > 1.0f)
{
String message = "Color parameter outside of expected range - Alpha";
throw new IllegalArgumentException( message );
}
// Formula needs all values between 0 - 1.
h = h % 360.0f;
h /= 360f;
s /= 100f;
l /= 100f;
float q = 0;
if (l < 0.5)
q = l * (1 + s);
else
q = (l + s) - (s * l);
float p = 2 * l - q;
float r = Math.max(0, HueToRGB(p, q, h + (1.0f / 3.0f)));
float g = Math.max(0, HueToRGB(p, q, h));
float b = Math.max(0, HueToRGB(p, q, h - (1.0f / 3.0f)));
r = Math.min(r, 1.0f);
g = Math.min(g, 1.0f);
b = Math.min(b, 1.0f);
return new Color(r, g, b, alpha);
}
private static float HueToRGB(float p, float q, float h)
{
if (h < 0) h += 1;
if (h > 1 ) h -= 1;
if (6 * h < 1)
{
return p + ((q - p) * 6 * h);
}
if (2 * h < 1 )
{
return q;
}
if (3 * h < 2)
{
return p + ( (q - p) * 6 * ((2.0f / 3.0f) - h) );
}
return p;
}
}

View File

@@ -24,4 +24,6 @@ module com.formdev.flatlaf {
exports com.formdev.flatlaf.icons;
exports com.formdev.flatlaf.ui;
exports com.formdev.flatlaf.util;
uses com.formdev.flatlaf.FlatDefaultsAddon;
}

View File

@@ -31,6 +31,10 @@
@cellFocusColor=000000
@icon=adadad
# Button
@buttonHoverBackground=lighten(3%,autoInverse)
@buttonPressedBackground=lighten(6%,autoInverse)
#---- globals ----
@@ -63,8 +67,8 @@ window=@background
#---- Button ----
Button.background=4c5052
Button.hoverBackground=525658
Button.pressedBackground=5c6164
Button.hoverBackground=@buttonHoverBackground
Button.pressedBackground=@buttonPressedBackground
Button.borderColor=5e6060
Button.disabledBorderColor=5e6060
@@ -73,8 +77,8 @@ Button.hoverBorderColor=@@Button.focusedBorderColor
Button.default.background=365880
Button.default.foreground=bbbbbb
Button.default.hoverBackground=3d6185
Button.default.pressedBackground=43688c
Button.default.hoverBackground=@buttonHoverBackground
Button.default.pressedBackground=@buttonPressedBackground
Button.default.borderColor=4c708c
Button.default.hoverBorderColor=537699
Button.default.focusedBorderColor=537699
@@ -95,8 +99,8 @@ CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
CheckBox.icon.selectedFocusedBorderColor=466D94
CheckBox.icon.background=43494A
CheckBox.icon.disabledBackground=@background
CheckBox.icon.hoverBackground=4c5052
CheckBox.icon.pressedBackground=@@Button.pressedBackground
CheckBox.icon.hoverBackground=@buttonHoverBackground
CheckBox.icon.pressedBackground=@buttonPressedBackground
CheckBox.icon.selectedBackground=43494A
CheckBox.icon.checkmarkColor=A7A7A7
CheckBox.icon.disabledCheckmarkColor=606060
@@ -227,7 +231,8 @@ ToggleButton.toolbar.selectedBackground=5c6164
#---- ToolTip ----
ToolTip.background=4b4d4d
ToolTip.border=4,6,4,6
ToolTip.background=1e2123
#---- Tree ----

View File

@@ -77,6 +77,7 @@ Button.default.borderWidth=1
CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon
CheckBox.arc=2
CheckBox.margin=2,2,2,2
CheckBox.iconTextGap=4
CheckBox.rollover=true
@@ -212,7 +213,7 @@ OptionPane.maxCharactersPerLine=80
OptionPane.iconMessageGap=16
OptionPane.messagePadding=3
OptionPane.buttonPadding=8
OptionPane.buttonMinimumWidth=72
OptionPane.buttonMinimumWidth={scaledNumber}72
OptionPane.sameSizeButtons=true
OptionPane.setButtonMargin=false
OptionPane.buttonOrientation=4
@@ -277,6 +278,7 @@ ScrollBar.width=10
ScrollPane.border=com.formdev.flatlaf.ui.FlatBorder
ScrollPane.background=@@ScrollBar.track
ScrollPane.fillUpperCorner=true
#---- Separator ----
@@ -307,12 +309,12 @@ Spinner.editorBorderPainted=false
#---- SplitPane ----
SplitPane.dividerSize=5
SplitPane.dividerSize={integer}5
SplitPane.continuousLayout=true
SplitPane.border=null
SplitPane.centerOneTouchButtons=true
SplitPane.oneTouchButtonSize=6
SplitPane.oneTouchButtonOffset=2
SplitPane.oneTouchButtonSize={scaledNumber}6
SplitPane.oneTouchButtonOffset={scaledNumber}2
SplitPaneDivider.border=null
SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor
@@ -409,7 +411,10 @@ ToolBar.separatorColor=@@Separator.foreground
#---- ToolTip ----
ToolTip.border=2,6,2,6,@@Component.borderColor
ToolTip.border=4,6,4,6,@@Component.borderColor
ToolTip.borderInactive=null
ToolTip.backgroundInactive=@@ToolTip.background
ToolTip.foregroundInactive=@disabledText
#---- Tree ----

View File

@@ -31,6 +31,10 @@
@cellFocusColor=000000
@icon=afafaf
# Button
@buttonHoverBackground=darken(3%,autoInverse)
@buttonPressedBackground=darken(10%,autoInverse)
#---- globals ----
@@ -64,8 +68,8 @@ window=@background
Button.background=ffffff
Button.focusedBackground=e3f1fa
Button.hoverBackground=f8f8f8
Button.pressedBackground=dfdfdf
Button.hoverBackground=@buttonHoverBackground
Button.pressedBackground=@buttonPressedBackground
Button.borderColor=bfbfbf
Button.disabledBorderColor=cfcfcf
@@ -75,8 +79,8 @@ Button.hoverBorderColor=@@Button.focusedBorderColor
Button.default.background=@@Button.background
Button.default.foreground=@foreground
Button.default.focusedBackground=@@Button.focusedBackground
Button.default.hoverBackground=@@Button.hoverBackground
Button.default.pressedBackground=@@Button.pressedBackground
Button.default.hoverBackground=@buttonHoverBackground
Button.default.pressedBackground=@buttonPressedBackground
Button.default.borderColor=4D89C9
Button.default.hoverBorderColor=@@Button.hoverBorderColor
Button.default.focusedBorderColor=@@Button.focusedBorderColor
@@ -97,8 +101,8 @@ CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
CheckBox.icon.background=FFFFFF
CheckBox.icon.disabledBackground=@background
CheckBox.icon.focusedBackground=@@Button.focusedBackground
CheckBox.icon.hoverBackground=@@Button.hoverBackground
CheckBox.icon.pressedBackground=@@Button.pressedBackground
CheckBox.icon.hoverBackground=@buttonHoverBackground
CheckBox.icon.pressedBackground=@buttonPressedBackground
CheckBox.icon.selectedBackground=FFFFFF
CheckBox.icon.checkmarkColor=4D89C9
CheckBox.icon.disabledCheckmarkColor=ABABAB
@@ -234,7 +238,7 @@ ToggleButton.toolbar.selectedBackground=cfcfcf
#---- ToolTip ----
ToolTip.background=f7f7f7
ToolTip.background=fafafa
#---- Tree ----

View File

@@ -18,10 +18,7 @@ version = rootProject.version
plugins {
`java-library`
}
repositories {
jcenter()
id( "com.jfrog.bintray" ) version "1.8.4"
}
dependencies {
@@ -38,6 +35,8 @@ java {
tasks {
jar {
dependsOn( ":flatlaf-core:jar" )
manifest {
attributes( "Main-Class" to "com.formdev.flatlaf.demo.FlatLafDemo" )
}
@@ -50,3 +49,23 @@ tasks {
} )
}
}
bintray {
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
setConfigurations( "archives" )
with( pkg ) {
repo = "flatlaf"
name = "flatlaf-demo"
setLicenses( "Apache-2.0" )
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
with( version ) {
name = project.version.toString()
}
publish = true
}
}

View File

@@ -205,18 +205,37 @@ class DemoFrame
//======== toolBar1 ========
{
toolBar1.setMargin(new Insets(3, 3, 3, 3));
//---- backButton ----
backButton.setToolTipText("Back");
toolBar1.add(backButton);
//---- forwardButton ----
forwardButton.setToolTipText("Forward");
toolBar1.add(forwardButton);
toolBar1.addSeparator();
//---- cutButton ----
cutButton.setToolTipText("Cut");
toolBar1.add(cutButton);
//---- copyButton ----
copyButton.setToolTipText("Copy");
toolBar1.add(copyButton);
//---- pasteButton ----
pasteButton.setToolTipText("Paste");
toolBar1.add(pasteButton);
toolBar1.addSeparator();
//---- refreshButton ----
refreshButton.setToolTipText("Refresh");
toolBar1.add(refreshButton);
toolBar1.addSeparator();
//---- showToggleButton ----
showToggleButton.setSelected(true);
showToggleButton.setToolTipText("Show Details");
toolBar1.add(showToggleButton);
}
contentPane.add(toolBar1, BorderLayout.NORTH);

View File

@@ -17,27 +17,33 @@ new FormModel {
"margin": new java.awt.Insets( 3, 3, 3, 3 )
add( new FormComponent( "javax.swing.JButton" ) {
name: "backButton"
"toolTipText": "Back"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "forwardButton"
"toolTipText": "Forward"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator5"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "cutButton"
"toolTipText": "Cut"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "copyButton"
"toolTipText": "Copy"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "pasteButton"
"toolTipText": "Paste"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator6"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "refreshButton"
"toolTipText": "Refresh"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator7"
@@ -45,6 +51,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JToggleButton" ) {
name: "showToggleButton"
"selected": true
"toolTipText": "Show Details"
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "North"

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.demo;
import java.util.prefs.Preferences;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLightLaf;
@@ -32,29 +33,31 @@ public class FlatLafDemo
static Preferences prefs;
public static void main( String[] args ) {
prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
SwingUtilities.invokeLater( () -> {
prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
// create frame
DemoFrame frame = new DemoFrame();
// create frame
DemoFrame frame = new DemoFrame();
// show frame
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
// show frame
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
} );
}
}

View File

@@ -201,7 +201,7 @@ class OptionPanePanel
//---- warningOptionPane ----
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
warningOptionPane.setMessage("Beware of the dog!");
warningOptionPane.setMessage("<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines.");
panel5.add(warningOptionPane, BorderLayout.CENTER);
}
panel9.add(panel5, "cell 1 4");

View File

@@ -143,7 +143,7 @@ new FormModel {
name: "warningOptionPane"
"messageType": 2
"optionType": 2
"message": "Beware of the dog!"
"message": "<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines."
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "Center"
} )

View File

@@ -24,8 +24,9 @@ import java.awt.image.BufferedImage;
import java.net.URISyntaxException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
import com.kitfox.svg.app.beans.SVGIcon;
@@ -129,6 +130,7 @@ public class ScaledSVGIcon
}
private static void lafChanged() {
darkLaf = (UIManager.getLookAndFeel() instanceof FlatDarkLaf);
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
darkLaf = (lookAndFeel instanceof FlatLaf && ((FlatLaf)lookAndFeel).isDark());
}
}

View File

@@ -4,6 +4,7 @@
package com.formdev.flatlaf.demo;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -30,10 +31,10 @@ class TabsPanel
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane2.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane3.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane4.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane2.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane3.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane4.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
}
private void moreTabsChanged() {

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

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

View File

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

View File

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

View File

@@ -0,0 +1,37 @@
FlatLaf addon for JIDE Common Layer
===================================
This addon for FlatLaf adds support for **some**
[JIDE Common Layer](https://github.com/jidesoft/jide-oss) components.
Following JIDE Common Layer components are currently supported by this addon:
- `JideTabbedPane`
**Note**: We have currently no plans to support additional components. If you're
a paid customer of JFormDesigner and need support for other components, email to
JFormDesigner support and ask for it. Otherwise, try to implement it yourself
and create a pull request.
Download
--------
FlatLaf for JIDE Common Layer binaries are available on **JCenter** and **Maven
Central**.
If you use Maven or Gradle, add a dependency with following coordinates to your
build script:
groupId: com.formdev
artifactId: flatlaf-jide-oss
version: 0.18
Otherwise download `flatlaf-jide-oss-<version>.jar` here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf-jide-oss/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf-jide-oss/_latestVersion)
You also need `flatlaf-<version>.jar`, which you can download here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
version = rootProject.version
plugins {
`java-library`
`maven-publish`
id( "com.jfrog.bintray" ) version "1.8.4"
}
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( "com.jidesoft:jide-oss:3.6.18" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
javadoc {
options {
this as StandardJavadocDocletOptions
tags = listOf( "uiDefault", "clientProperty" )
}
isFailOnError = false
}
register( "sourcesJar", Jar::class ) {
archiveClassifier.set( "sources" )
from( sourceSets.main.get().allJava )
}
register( "javadocJar", Jar::class ) {
archiveClassifier.set( "javadoc" )
from( javadoc )
}
}
publishing {
publications {
create<MavenPublication>( "maven" ) {
artifactId = "flatlaf-jide-oss"
groupId = "com.formdev"
from( components["java"] )
artifact( tasks["sourcesJar"] )
artifact( tasks["javadocJar"] )
pom {
name.set( "FlatLaf addon for JIDE Common Layer" )
description.set( "Flat Look and Feel addon for JIDE Common Layer" )
url.set( "https://github.com/JFormDesigner/FlatLaf" )
licenses {
license {
name.set( "The Apache License, Version 2.0" )
url.set( "http://www.apache.org/licenses/LICENSE-2.0.txt" )
}
}
developers {
developer {
name.set( "Karl Tauber" )
organization.set( "FormDev Software GmbH" )
organizationUrl.set( "https://www.formdev.com/" )
}
}
scm {
url.set( "https://github.com/JFormDesigner/FlatLaf" )
}
}
}
}
}
bintray {
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
setPublications( "maven" )
with( pkg ) {
repo = "flatlaf"
name = "flatlaf-jide-oss"
setLicenses( "Apache-2.0" )
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
with( version ) {
name = project.version.toString()
}
publish = true
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.jideoss;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.swing.UIDefaults;
import com.formdev.flatlaf.FlatDefaultsAddon;
import com.formdev.flatlaf.FlatLaf;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.plaf.LookAndFeelFactory.UIDefaultsCustomizer;
import com.jidesoft.plaf.LookAndFeelFactory.UIDefaultsInitializer;
/**
* JIDE Common Layer addon for FlatLaf.
*
* @author Karl Tauber
*/
public class FlatJideOssDefaultsAddon
extends FlatDefaultsAddon
{
/**
* Finds JIDE Common Layer addon .properties file for the given LaF class
* in the same package as this class.
*/
@Override
public InputStream getDefaults( Class<?> lafClass ) {
LookAndFeelFactory.registerDefaultInitializer( FlatLaf.class.getName(), FlatJideUIDefaultsCustomizer.class.getName() );
LookAndFeelFactory.registerDefaultCustomizer( FlatLaf.class.getName(), FlatJideUIDefaultsCustomizer.class.getName() );
Class<?> addonClass = this.getClass();
String propertiesName = "/" + addonClass.getPackage().getName().replace( '.', '/' )
+ '/' + lafClass.getSimpleName() + ".properties";
return addonClass.getResourceAsStream( propertiesName );
}
//---- class FlatJideUIDefaultsCustomizer ---------------------------------
/**
* Because JIDE overwrites our UI defaults (from properties files) with its
* own UI defaults, we have to first remember our UI defaults in the initializer
* (invoked before JIDE overwrites UI defaults) and then restore them in the customizer.
*/
public static class FlatJideUIDefaultsCustomizer
implements UIDefaultsInitializer, UIDefaultsCustomizer
{
private static HashMap<Object, Object> jideDefaults;
@Override
public void initialize( UIDefaults defaults ) {
jideDefaults = new HashMap<>();
for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
Object key = e.getKey();
if( key instanceof String && ((String)key).startsWith( "Jide" ) )
jideDefaults.put( key, e.getValue() );
}
}
@Override
public void customize( UIDefaults defaults ) {
if( jideDefaults != null ) {
defaults.putAll( jideDefaults );
jideDefaults = null;
}
}
}
}

View File

@@ -0,0 +1,372 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.jideoss.ui;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyEquals;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.jidesoft.plaf.UIDefaultsLookup;
import com.jidesoft.plaf.basic.BasicJideTabbedPaneUI;
import com.jidesoft.swing.JideTabbedPane;
/**
* Provides the Flat LaF UI delegate for {@link com.jidesoft.swing.JideTabbedPane}.
*
* @author Karl Tauber
*/
public class FlatJideTabbedPaneUI
extends BasicJideTabbedPaneUI
{
protected Color underlineColor;
protected Color disabledUnderlineColor;
protected Color hoverColor;
protected Color focusColor;
protected Color contentAreaColor;
protected int tabHeight;
protected int tabSelectionHeight;
protected int contentSeparatorHeight;
protected boolean hasFullBorder;
protected boolean tabsOverlapBorder;
public static ComponentUI createUI( JComponent c ) {
return new FlatJideTabbedPaneUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
_background = UIDefaultsLookup.getColor( "JideTabbedPane.background" );
underlineColor = UIManager.getColor( "TabbedPane.underlineColor" );
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" );
// scale
_textIconGap = scale( _textIconGap );
tabHeight = scale( tabHeight );
tabSelectionHeight = scale( tabSelectionHeight );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
underlineColor = null;
disabledUnderlineColor = null;
hoverColor = null;
focusColor = null;
contentAreaColor = null;
}
@Override
protected PropertyChangeListener createPropertyChangeListener() {
return new PropertyChangeHandler() {
@Override
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
String propertyName = e.getPropertyName();
if( JideTabbedPane.PROPERTY_SELECTED_INDEX.equals( propertyName ) ) {
repaintTab( (Integer) e.getOldValue() );
repaintTab( (Integer) e.getNewValue() );
} else if( FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER.equals( propertyName ) ) {
_tabPane.revalidate();
_tabPane.repaint();
}
}
};
}
private void repaintTab( int tabIndex ) {
if( tabIndex < 0 || tabIndex >= _tabPane.getTabCount() )
return;
Rectangle r = getTabBounds( _tabPane, tabIndex );
if( r != null )
_tabPane.repaint( r );
}
@Override
protected MouseListener createMouseListener() {
return new RolloverMouseHandler();
}
@Override
protected MouseMotionListener createMouseMotionListener() {
return new RolloverMouseMotionHandler();
}
@Override
protected int calculateTabHeight( int tabPlacement, int tabIndex, FontMetrics metrics ) {
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, metrics ) );
}
@Override
protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) {
return Math.max( tabHeight, super.calculateTabWidth( tabPlacement, tabIndex, metrics ) );
}
@Override
protected Insets getTabInsets( int tabPlacement, int tabIndex ) {
return scale( super.getTabInsets( tabPlacement, tabIndex ) );
}
@Override
protected Insets getSelectedTabPadInsets( int tabPlacement ) {
return scale( super.getSelectedTabPadInsets( tabPlacement ) );
}
@Override
protected Insets getTabAreaInsets( int tabPlacement ) {
return scale( super.getTabAreaInsets( tabPlacement ) );
}
@Override
protected int getTabShape() {
return JideTabbedPane.SHAPE_BOX;
}
/**
* The content border insets are used to create a separator between tabs and content.
* If client property JTabbedPane.hasFullBorder is true, then the content border insets
* are also used for the border.
*/
@Override
protected Insets getContentBorderInsets( int tabPlacement ) {
return FlatUIUtils.addInsets( getContentBorderInsets0( tabPlacement ),
scale( super.getContentBorderInsets( tabPlacement ) ) );
}
private Insets getContentBorderInsets0( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
Insets contentBorderInsets = new Insets( 0, 0, 0, 0 );
rotateInsets( insets, contentBorderInsets, tabPlacement );
return contentBorderInsets;
}
@Override
public void update( Graphics g, JComponent c ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.update( g, c );
}
@Override
public void paint( Graphics g, JComponent c ) {
super.paint( g, c );
// must paint tab area after content border was painted
if( !scrollableTabLayoutEnabled() && _tabPane.getTabCount() > 0 )
paintTabArea( g, _tabPane.getTabPlacement(), _tabPane.getSelectedIndex(), c );
}
@Override
protected void paintTabBackground( Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected )
{
// paint tab background
boolean enabled = _tabPane.isEnabled();
g.setColor( enabled && _tabPane.isEnabledAt( tabIndex ) &&
(_indexMouseOver == tabIndex || (_closeButtons != null && ((JideTabbedPane.NoFocusButton)_closeButtons[tabIndex]).isMouseOver()))
? hoverColor
: (enabled && isSelected && _tabPane.hasFocus()
? focusColor
: _tabPane.getBackgroundAt( tabIndex )) );
g.fillRect( x, y, w, h );
}
@Override
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h,
boolean isSelected )
{
if( isSelected )
paintTabSelection( g, tabPlacement, x, y, w, h );
}
protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
// increase clip bounds in scroll-tab-layout to paint over the separator line
Rectangle clipBounds = scrollableTabLayoutEnabled() ? g.getClipBounds() : null;
if( clipBounds != null ) {
Rectangle newClipBounds = new Rectangle( clipBounds );
int contentSeparatorHeight = scale( this.contentSeparatorHeight );
switch( tabPlacement ) {
case TOP:
default:
newClipBounds.height += contentSeparatorHeight;
break;
case BOTTOM:
newClipBounds.y -= contentSeparatorHeight;
newClipBounds.height += contentSeparatorHeight;
break;
case LEFT:
newClipBounds.width += contentSeparatorHeight;
break;
case RIGHT:
newClipBounds.x -= contentSeparatorHeight;
newClipBounds.width += contentSeparatorHeight;
break;
}
g.setClip( newClipBounds );
}
g.setColor( _tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
Insets contentInsets = getContentBorderInsets0( tabPlacement );
// paint underline selection
switch( tabPlacement ) {
case TOP:
default:
int sy = y + h + contentInsets.top - tabSelectionHeight;
g.fillRect( x, sy, w, tabSelectionHeight );
break;
case BOTTOM:
g.fillRect( x, y - contentInsets.bottom, w, tabSelectionHeight );
break;
case LEFT:
int sx = x + w + contentInsets.left - tabSelectionHeight;
g.fillRect( sx, y, tabSelectionHeight, h );
break;
case RIGHT:
g.fillRect( x - contentInsets.right, y, tabSelectionHeight, h );
break;
}
if( clipBounds != null )
g.setClip( clipBounds );
}
/**
* Actually does the nearly the same as super.paintContentBorder() but
* - not invoking paintContentBorder*Edge() methods
* - repaint selection
*/
@Override
protected void paintContentBorder( Graphics g, int tabPlacement, int selectedIndex ) {
if( _tabPane.getTabCount() <= 0 )
return;
Insets insets = _tabPane.getInsets();
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
int x = insets.left;
int y = insets.top;
int w = _tabPane.getWidth() - insets.right - insets.left;
int h = _tabPane.getHeight() - insets.top - insets.bottom;
Dimension lsize = isTabLeadingComponentVisible() ? _tabLeadingComponent.getPreferredSize() : new Dimension();
Dimension tsize = isTabTrailingComponentVisible() ? _tabTrailingComponent.getPreferredSize() : new Dimension();
// remove tabs from bounds
switch( tabPlacement ) {
case LEFT:
x += Math.max( calculateTabAreaWidth( tabPlacement, _runCount, _maxTabWidth ),
Math.max( lsize.width, tsize.width ) );
if( tabsOverlapBorder )
x -= tabAreaInsets.right;
w -= (x - insets.left);
break;
case RIGHT:
w -= calculateTabAreaWidth( tabPlacement, _runCount, _maxTabWidth );
if( tabsOverlapBorder )
w += tabAreaInsets.left;
break;
case BOTTOM:
h -= calculateTabAreaHeight( tabPlacement, _runCount, _maxTabHeight );
if( tabsOverlapBorder )
h += tabAreaInsets.top;
break;
case TOP:
default:
y += Math.max( calculateTabAreaHeight( tabPlacement, _runCount, _maxTabHeight ),
Math.max( lsize.height, tsize.height ) );
if( tabsOverlapBorder )
y -= tabAreaInsets.bottom;
h -= (y - insets.top);
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
// paint content area
g.setColor( contentAreaColor );
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 );
((Graphics2D)g).fill( path );
// repaint selection in scroll-tab-layout because it may be painted before
// the content border was painted (from BasicTabbedPaneUI$ScrollableTabPanel)
if( scrollableTabLayoutEnabled() && selectedIndex >= 0 && _tabScroller != null && _tabScroller.viewport != null ) {
Rectangle tabRect = getTabBounds( _tabPane, selectedIndex );
Shape oldClip = g.getClip();
g.setClip( _tabScroller.viewport.getBounds() );
paintTabSelection( g, tabPlacement, tabRect.x, tabRect.y, tabRect.width, tabRect.height );
g.setClip( oldClip );
}
}
@Override
protected void paintFocusIndicator( Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex,
Rectangle iconRect, Rectangle textRect, boolean isSelected )
{
}
}

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.jideoss.FlatJideOssDefaultsAddon

View File

@@ -0,0 +1,32 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- UI delegates ----
JideTabbedPaneUI=com.formdev.flatlaf.jideoss.ui.FlatJideTabbedPaneUI
#---- JideTabbedPane ----
JideTabbedPane.background=@background
JideTabbedPane.foreground=@foreground
JideTabbedPane.tabAreaBackground=@background
JideTabbedPane.tabInsets=@@TabbedPane.tabInsets
JideTabbedPane.tabAreaInsets=@@TabbedPane.tabAreaInsets
JideTabbedPane.contentBorderInsets=0,0,0,0
JideTabbedPane.tabRunOverlay=@@TabbedPane.tabRunOverlay
JideTabbedPane.shadow=@@TabbedPane.shadow

43
flatlaf-swingx/README.md Normal file
View File

@@ -0,0 +1,43 @@
FlatLaf addon for SwingX
========================
This addon for FlatLaf adds support for **some** widely used SwingX components.
Many SwingX components that do not use UI delegates (e.g. `JXButton`, `JXLabel`,
`JXList`, etc) work with FlatLaf without adaptation.
Following SwingX components, which use UI delegates, are currently supported by
this addon:
- `JXBusyLabel`
- `JXDatePicker`
- `JXHeader`
- `JXHyperlink`
- `JXMonthView`
- `JXTaskPaneContainer`
- `JXTaskPane`
![Flat Light SwingX Demo](../images/FlatLightSwingXTest.png)
![Flat Dark SwingX Demo](../images/FlatDarkSwingXTest.png)
Download
--------
FlatLaf for SwingX binaries are available on **JCenter** and **Maven Central**.
If you use Maven or Gradle, add a dependency with following coordinates to your
build script:
groupId: com.formdev
artifactId: flatlaf-swingx
version: 0.18
Otherwise download `flatlaf-swingx-<version>.jar` here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf-swingx/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf-swingx/_latestVersion)
You also need `flatlaf-<version>.jar`, which you can download here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
version = rootProject.version
plugins {
`java-library`
`maven-publish`
id( "com.jfrog.bintray" ) version "1.8.4"
}
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( "org.swinglabs.swingx:swingx-all:1.6.5-1" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
javadoc {
options {
this as StandardJavadocDocletOptions
tags = listOf( "uiDefault", "clientProperty" )
}
isFailOnError = false
}
register( "sourcesJar", Jar::class ) {
archiveClassifier.set( "sources" )
from( sourceSets.main.get().allJava )
}
register( "javadocJar", Jar::class ) {
archiveClassifier.set( "javadoc" )
from( javadoc )
}
}
publishing {
publications {
create<MavenPublication>( "maven" ) {
artifactId = "flatlaf-swingx"
groupId = "com.formdev"
from( components["java"] )
artifact( tasks["sourcesJar"] )
artifact( tasks["javadocJar"] )
pom {
name.set( "FlatLaf addon for SwingX" )
description.set( "Flat Look and Feel addon for SwingX" )
url.set( "https://github.com/JFormDesigner/FlatLaf" )
licenses {
license {
name.set( "The Apache License, Version 2.0" )
url.set( "http://www.apache.org/licenses/LICENSE-2.0.txt" )
}
}
developers {
developer {
name.set( "Karl Tauber" )
organization.set( "FormDev Software GmbH" )
organizationUrl.set( "https://www.formdev.com/" )
}
}
scm {
url.set( "https://github.com/JFormDesigner/FlatLaf" )
}
}
}
}
}
bintray {
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
setPublications( "maven" )
with( pkg ) {
repo = "flatlaf"
name = "flatlaf-swingx"
setLicenses( "Apache-2.0" )
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
with( version ) {
name = project.version.toString()
}
publish = true
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
import javax.swing.UIManager;
import org.jdesktop.swingx.plaf.basic.BasicLookAndFeelAddons;
import com.formdev.flatlaf.FlatLaf;
/**
* SwingX LaF addon.
*
* This class is required because without this class, the system addon would be used,
* which may result in wrong UI defaults. (e.g. background of TaskPaneContainer)
*
* @author Karl Tauber
*/
public class FlatLookAndFeelAddons
extends BasicLookAndFeelAddons
{
@Override
protected boolean matches() {
return UIManager.getLookAndFeel() instanceof FlatLaf;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
import java.io.InputStream;
import com.formdev.flatlaf.FlatDefaultsAddon;
/**
* SwingX addon for FlatLaf.
*
* @author Karl Tauber
*/
public class FlatSwingXDefaultsAddon
extends FlatDefaultsAddon
{
/**
* Finds SwingX addon .properties file for the given LaF class
* in the same package as this class.
*/
@Override
public InputStream getDefaults( Class<?> lafClass ) {
Class<?> addonClass = this.getClass();
String propertiesName = "/" + addonClass.getPackage().getName().replace( '.', '/' )
+ '/' + lafClass.getSimpleName() + ".properties";
return addonClass.getResourceAsStream( propertiesName );
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXBusyLabel;
import org.jdesktop.swingx.plaf.basic.BasicBusyLabelUI;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.ui.FlatUIUtils;
//TODO scale busy spinner
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXBusyLabel}.
*
* @author Karl Tauber
*/
public class FlatBusyLabelUI
extends BasicBusyLabelUI
{
private Color disabledForeground;
public static ComponentUI createUI( JComponent c ) {
return new FlatBusyLabelUI( (JXBusyLabel) c );
}
public FlatBusyLabelUI( JXBusyLabel busyLabel ) {
super( busyLabel );
}
@Override
protected void installDefaults( JLabel c ) {
super.installDefaults( c );
disabledForeground = UIManager.getColor( "Label.disabledForeground" );
// force recreation of busy painter for correct colors when switching LaF
if( c.getIcon() != null ) {
JXBusyLabel busyLabel = (JXBusyLabel) c;
boolean oldBusy = busyLabel.isBusy();
busyLabel.setBusy( false );
busyLabel.setBusyPainter( null );
busyLabel.setBusy( oldBusy );
}
}
@Override
protected void uninstallDefaults( JLabel c ) {
super.uninstallDefaults( c );
disabledForeground = null;
}
@Override
protected void paintDisabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
int mnemIndex = FlatLaf.isShowMnemonics() ? l.getDisplayedMnemonicIndex() : -1;
g.setColor( disabledForeground );
FlatUIUtils.drawStringUnderlineCharAt( l, g, s, mnemIndex, textX, textY );
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Component;
import org.jdesktop.swingx.JXDatePicker;
import com.formdev.flatlaf.ui.FlatRoundBorder;
/**
* Border for {@link org.jdesktop.swingx.JXDatePicker}.
*
* @author Karl Tauber
*/
public class FlatDatePickerBorder
extends FlatRoundBorder
{
@Override
protected boolean isFocused( Component c ) {
if( c instanceof JXDatePicker )
return ((JXDatePicker)c).getEditor().hasFocus();
return super.isFocused( c );
}
}

View File

@@ -0,0 +1,303 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.text.ParseException;
import java.util.Calendar;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import org.jdesktop.swingx.JXHyperlink;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.calendar.DatePickerFormatter.DatePickerFormatterUIResource;
import org.jdesktop.swingx.plaf.basic.BasicDatePickerUI;
import com.formdev.flatlaf.ui.FlatArrowButton;
import com.formdev.flatlaf.ui.FlatBorder;
import com.formdev.flatlaf.ui.FlatRoundBorder;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.ui.MigLayoutVisualPadding;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXDatePicker}.
*
* @author Karl Tauber
*/
public class FlatDatePickerUI
extends BasicDatePickerUI
{
protected Insets padding;
protected int focusWidth;
protected int arc;
protected String arrowType;
protected Color borderColor;
protected Color disabledBorderColor;
protected Color disabledBackground;
protected Color buttonBackground;
protected Color buttonArrowColor;
protected Color buttonDisabledArrowColor;
protected Color buttonHoverArrowColor;
private JButton popupButton;
public static ComponentUI createUI( JComponent c ) {
return new FlatDatePickerUI();
}
@Override
public void installUI( JComponent c ) {
// must get UI defaults here because installDefaults() is invoked after
// installComponents(), which uses these values to create popup button
padding = UIManager.getInsets( "ComboBox.padding" );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
arrowType = UIManager.getString( "Component.arrowType" );
borderColor = UIManager.getColor( "Component.borderColor" );
disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
buttonBackground = UIManager.getColor( "ComboBox.buttonBackground" );
buttonArrowColor = UIManager.getColor( "ComboBox.buttonArrowColor" );
buttonDisabledArrowColor = UIManager.getColor( "ComboBox.buttonDisabledArrowColor" );
buttonHoverArrowColor = UIManager.getColor( "ComboBox.buttonHoverArrowColor" );
super.installUI( c );
LookAndFeel.installProperty( datePicker, "opaque", false );
// hack JXDatePicker.TodayPanel colors
// (there is no need to uninstall these changes because only UIResources are used,
// which are automatically replaced when switching LaF)
JPanel linkPanel = datePicker.getLinkPanel();
if( linkPanel instanceof JXPanel && linkPanel.getClass().getName().equals( "org.jdesktop.swingx.JXDatePicker$TodayPanel" ) ) {
((JXPanel)linkPanel).setBackgroundPainter( null );
linkPanel.setBackground( UIManager.getColor( "JXMonthView.background" ) );
if( linkPanel.getComponentCount() >= 1 && linkPanel.getComponent( 0 ) instanceof JXHyperlink ) {
JXHyperlink todayLink = (JXHyperlink) linkPanel.getComponent( 0 );
todayLink.setUnclickedColor( UIManager.getColor( "Hyperlink.linkColor" ) );
todayLink.setClickedColor( UIManager.getColor( "Hyperlink.visitedColor" ) );
}
}
}
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installColors( datePicker, "ComboBox.background", "ComboBox.foreground" );
LookAndFeel.installBorder( datePicker, "JXDatePicker.border" );
LookAndFeel.installProperty( datePicker, "opaque", Boolean.TRUE );
MigLayoutVisualPadding.install( datePicker, focusWidth );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
borderColor = null;
disabledBorderColor = null;
disabledBackground = null;
buttonBackground = null;
buttonArrowColor = null;
buttonDisabledArrowColor = null;
buttonHoverArrowColor = null;
if( datePicker.getBorder() instanceof UIResource )
datePicker.setBorder( null );
MigLayoutVisualPadding.uninstall( datePicker );
}
@Override
protected JFormattedTextField createEditor() {
JFormattedTextField editor = new DefaultEditor( new DatePickerFormatterUIResource( datePicker.getLocale() ) );
editor.setName( "dateField" );
editor.setBorder( BorderFactory.createEmptyBorder() );
editor.setOpaque( false );
editor.addFocusListener( new FlatUIUtils.RepaintFocusListener( datePicker ) );
return editor;
}
@Override
protected JButton createPopupButton() {
popupButton = new FlatArrowButton( SwingConstants.SOUTH, arrowType, buttonArrowColor,
buttonDisabledArrowColor, buttonHoverArrowColor, null );
popupButton.setName( "popupButton" );
return popupButton;
}
@Override
protected LayoutManager createLayoutManager() {
return new LayoutManager() {
@Override
public void addLayoutComponent( String name, Component comp ) {}
@Override
public void removeLayoutComponent( Component comp ) {}
@Override
public Dimension preferredLayoutSize( Container parent ) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize( Container parent ) {
return parent.getMinimumSize();
}
@Override
public void layoutContainer( Container parent ) {
Insets insets = datePicker.getInsets();
int x = insets.left;
int y = insets.top;
int width = datePicker.getWidth() - insets.left - insets.right;
int height = datePicker.getHeight() - insets.top - insets.bottom;
int popupButtonWidth = popupButton != null ? height : 0;
boolean ltr = datePicker.getComponentOrientation().isLeftToRight();
Rectangle r = new Rectangle( x + (ltr ? 0 : popupButtonWidth), y, width - popupButtonWidth, height );
r = FlatUIUtils.subtractInsets( r, UIScale.scale( padding ) );
datePicker.getEditor().setBounds( r );
if( popupButton != null )
popupButton.setBounds( x + (ltr ? width - popupButtonWidth : 0), y, popupButtonWidth, height );
}
};
}
@Override
public Dimension getPreferredSize( JComponent c ) {
Dimension dim = datePicker.getEditor().getPreferredSize();
dim = FlatUIUtils.addInsets( dim, UIScale.scale( padding ) );
if( popupButton != null )
dim.width += dim.height;
return FlatUIUtils.addInsets( dim, datePicker.getInsets() );
}
@Override
public void update( Graphics g, JComponent c ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
int arrowX = popupButton.getX();
int arrowWidth = popupButton.getWidth();
boolean enabled = c.isEnabled();
boolean isLeftToRight = c.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow button
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
paint( g, c );
}
//---- class DefaultEditor ------------------------------------------------
private class DefaultEditor
extends JFormattedTextField
implements UIResource
{
DefaultEditor( AbstractFormatter formatter ) {
super( formatter );
// disable Component.minimumWidth
setColumns( 1 );
}
@Override
public Dimension getPreferredSize() {
Dimension prefSize = super.getPreferredSize();
// create date 2000-11-30 that is used for minimum width calculation
Calendar calendar = Calendar.getInstance( datePicker.getLocale() );
calendar.set( 2000, 11, 30 );
try {
AbstractFormatter formatter = getFormatter();
String str = formatter.valueToString( calendar.getTime() );
Insets insets = getInsets();
FontMetrics metrics = getFontMetrics( getFont() );
int minWidth = metrics.stringWidth( str ) + insets.left + insets.right + 2;
return new Dimension( Math.max( minWidth, prefSize.width ), prefSize.height );
} catch( ParseException ex ) {
// ignore
return prefSize;
}
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXHeader;
import org.jdesktop.swingx.plaf.basic.BasicHeaderUI;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXHeader}.
*
* @author Karl Tauber
*/
public class FlatHeaderUI
extends BasicHeaderUI
{
public static ComponentUI createUI( JComponent c ) {
return new FlatHeaderUI();
}
@Override
protected void installComponents( JXHeader header ) {
super.installComponents( header );
scaleLayout( header );
}
@Override
protected void onPropertyChange( JXHeader h, String propertyName, Object oldValue, Object newValue ) {
super.onPropertyChange( h, propertyName, oldValue, newValue );
if( "iconPosition".equals( propertyName ) )
scaleLayout( h );
}
private void scaleLayout( JXHeader header ) {
if( UIScale.getUserScaleFactor() == 1f )
return;
LayoutManager layout = header.getLayout();
if( !(layout instanceof GridBagLayout) )
return;
GridBagLayout gbl = (GridBagLayout) layout;
for( Component c : header.getComponents() ) {
GridBagConstraints cons = gbl.getConstraints( c );
cons.insets = UIScale.scale( cons.insets );
gbl.setConstraints( c, cons );
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.plaf.basic.BasicHyperlinkUI;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXHyperlink}.
*
* @uiDefault Hyperlink.disabledText Color
*
* @author Karl Tauber
*/
public class FlatHyperlinkUI
extends BasicHyperlinkUI
{
protected Color disabledText;
public static ComponentUI createUI( JComponent c ) {
return new FlatHyperlinkUI();
}
@Override
protected void installDefaults( AbstractButton b ) {
super.installDefaults( b );
disabledText = UIManager.getColor( "Hyperlink.disabledText" );
}
@Override
protected void uninstallDefaults( AbstractButton b ) {
super.uninstallDefaults( b );
disabledText = null;
}
@Override
public void paint( Graphics g, JComponent c ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paint( g, c );
}
@Override
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
FlatButtonUI.paintText( g, b, textRect, text, b.isEnabled() ? b.getForeground() : disabledText );
if( b.getModel().isRollover() )
paintUnderline( g, textRect );
}
private void paintUnderline( Graphics g, Rectangle rect ) {
int descent = g.getFontMetrics().getDescent();
((Graphics2D)g).fill( new Rectangle2D.Float(
rect.x, (rect.y + rect.height) - descent + UIScale.scale( 1f ),
rect.width, UIScale.scale( 1f ) ) );
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Shape;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import com.formdev.flatlaf.icons.FlatAbstractIcon;
import com.formdev.flatlaf.ui.FlatArrowButton;
/**
* "month down" icon for {@link org.jdesktop.swingx.JXMonthView}.
*
* @uiDefault Component.arrowType String triangle (default) or chevron
* @uiDefault JXMonthView.arrowColor Color
* @uiDefault JXMonthView.disabledArrowColor Color
*
* @author Karl Tauber
*/
public class FlatMonthDownIcon
extends FlatAbstractIcon
{
protected final boolean chevron = "chevron".equals( UIManager.getString( "Component.arrowType" ) );
protected final Color arrowColor = UIManager.getColor( "JXMonthView.arrowColor" );
protected final Color disabledArrowColor = UIManager.getColor( "JXMonthView.disabledArrowColor" );
private final int direction;
public FlatMonthDownIcon() {
this( SwingConstants.WEST );
}
protected FlatMonthDownIcon( int direction ) {
super( 20, 20, null );
this.direction = direction;
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
int h = chevron ? 4 : 5;
int w = chevron ? 8 : 9;
int x = Math.round( (width - h) / 2f );
int y = Math.round( (height - w) / 2f );
g.setColor( c.isEnabled() ? arrowColor : disabledArrowColor );
g.translate( x, y );
Shape arrowShape = FlatArrowButton.createArrowShape( direction, chevron, w, h );
if( chevron ) {
// chevron arrow
g.setStroke( new BasicStroke( 1f ) );
g.draw( arrowShape );
} else {
// triangle arrow
g.fill( arrowShape );
}
g.translate( -x, -y );
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import javax.swing.SwingConstants;
/**
* "month up" icon for {@link org.jdesktop.swingx.JXMonthView}.
*
* @author Karl Tauber
*/
public class FlatMonthUpIcon
extends FlatMonthDownIcon
{
public FlatMonthUpIcon() {
super( SwingConstants.EAST );
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Insets;
import java.util.Calendar;
import javax.swing.JComponent;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.plaf.basic.BasicMonthViewUI;
import org.jdesktop.swingx.plaf.basic.CalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.CalendarState;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXMonthView}.
*
* @author Karl Tauber
*/
public class FlatMonthViewUI
extends BasicMonthViewUI
{
public static ComponentUI createUI( JComponent c ) {
return new FlatMonthViewUI();
}
@Override
protected CalendarRenderingHandler createRenderingHandler() {
return new FlatRenderingHandler();
}
//---- class FlatRenderingHandler -----------------------------------------
private static class FlatRenderingHandler
extends RenderingHandler
{
@Override
public JComponent prepareRenderingComponent( JXMonthView monthView, Calendar calendar,
CalendarState dayState )
{
JComponent c = super.prepareRenderingComponent( monthView, calendar, dayState );
int px = monthView.getBoxPaddingX();
int py = monthView.getBoxPaddingY();
// scale borders
Border border = null;
if( dayState == CalendarState.TITLE && monthView.isTraversable() ) {
Border b = c.getBorder();
if( b instanceof CompoundBorder && ((CompoundBorder)b).getInsideBorder() instanceof EmptyBorder )
border = new CompoundBorder( ((CompoundBorder)b).getOutsideBorder(), new FlatEmptyBorder( py * 2, 0, py * 2, 0 ) );
} else if( dayState == CalendarState.TODAY )
border = new FlatLineBorder( new Insets( py, px, py, px ), monthView.getTodayBackground() );
if( border == null )
border = new FlatEmptyBorder( py, px, py, px );
c.setBorder( border );
return c;
}
}
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.plaf.basic.BasicTaskPaneUI;
import com.formdev.flatlaf.ui.FlatArrowButton;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXTaskPane}.
*
* @author Karl Tauber
*/
public class FlatTaskPaneUI
extends BasicTaskPaneUI
{
private Color background;
public static ComponentUI createUI( JComponent c ) {
return new FlatTaskPaneUI();
}
@Override
protected void installDefaults() {
if( group.getContentPane() instanceof JComponent ) {
// remove default SwingX content border, which may be still set when switching LaF
JComponent content = (JComponent) group.getContentPane();
Border contentBorder = content.getBorder();
if( contentBorder instanceof CompoundBorder &&
((CompoundBorder)contentBorder).getOutsideBorder() instanceof BasicTaskPaneUI.ContentPaneBorder &&
((CompoundBorder)contentBorder).getInsideBorder() instanceof EmptyBorder )
{
content.setBorder( null );
}
// set non-UIResource color to background to avoid that it is lost when switching LaF
background = UIManager.getColor( "TaskPane.background" );
Color bg = content.getBackground();
if( bg == null || bg instanceof UIResource ) {
content.setBackground( new Color( background.getRGB(), true ) );
}
}
roundHeight = FlatUIUtils.getUIInt( "TaskPane.roundHeight", UIManager.getInt( "Component.arc" ) );
super.installDefaults();
}
@Override
public void uninstallUI( JComponent c ) {
if( group.getContentPane() instanceof JComponent ) {
// uninstall our content border, because it does not implement UIResource,
// to alloy other LaF to install its own border
JComponent content = (JComponent) group.getContentPane();
if( content.getBorder() instanceof FlatContentPaneBorder )
content.setBorder( null );
// replace our non-UIResouce background with UIResouce background
// to allow next LaF to overwrite it
if( background.equals( content.getBackground() ) )
content.setBackground( background );
background = null;
}
super.uninstallUI( c );
}
@Override
protected int getTitleHeight( Component c ) {
return Math.max( super.getTitleHeight( c ), UIScale.scale( titleHeight ) );
}
@Override
protected int getRoundHeight() {
return UIScale.scale( roundHeight );
}
@Override
protected Border createPaneBorder() {
return new FlatPaneBorder();
}
@Override
protected Border createContentPaneBorder() {
return new FlatContentPaneBorder( UIManager.getColor( "TaskPane.borderColor" ),
UIManager.getInsets( "TaskPane.contentInsets" ) );
}
//---- class FlatContentPaneBorder ----------------------------------------
/**
* The content pane border.
*/
private static class FlatContentPaneBorder
extends EmptyBorder
{
Color color;
FlatContentPaneBorder( Color color, Insets insets ) {
super( insets );
this.color = color;
// add space for the line border
left++;
right++;
bottom++;
}
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
if( color == null )
return;
FlatUIUtils.setRenderingHints( (Graphics2D) g );
g.setColor( color );
float lineWidth = UIScale.scale( 1f );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Rectangle2D.Float( x, y, width, height ), false );
path.append( new Rectangle2D.Float( x + lineWidth, y, width - (lineWidth * 2), height - lineWidth ), false );
((Graphics2D)g).fill( path );
}
@Override
public Insets getBorderInsets() {
return new Insets( scale( top ), scale( left ), scale( bottom ), scale( right ) );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
insets.left = scale( left );
insets.top = scale( top );
insets.right = scale( right );
insets.bottom = scale( bottom );
return insets;
}
}
//---- class FlatPaneBorder -----------------------------------------------
private class FlatPaneBorder
extends PaneBorder
{
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paintBorder( c, g, x, y, width, height );
}
@Override
protected void paintTitleBackground( JXTaskPane group, Graphics g ) {
int width = group.getWidth();
int height = getTitleHeight( group ) ;
float arc = UIScale.scale( (float) roundHeight );
float lineWidth = UIScale.scale( 1f );
// paint background
g.setColor( group.isSpecial() ? specialTitleBackground : titleBackgroundGradientStart );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectanglePath( lineWidth, lineWidth,
width - (lineWidth * 2), height - (lineWidth * 2), arc - lineWidth, arc - lineWidth, 0, 0 ) );
// paint border
if( borderColor != null ) {
g.setColor( borderColor );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectangle( 0, 0, width, height, lineWidth, arc, arc, 0, 0 ) );
}
}
@Override
protected void paintExpandedControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
g.setColor( getPaintColor( group ) );
paintChevronControls( group, g, x, y, width, height );
}
@Override
protected void paintChevronControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
Graphics2D g2 = (Graphics2D) g;
// scale chevron size
float cw = scale( 6f );
float ch = scale( 3f );
// create arrow shape
int direction = group.isCollapsed() ? SwingConstants.SOUTH : SwingConstants.NORTH;
Shape arrowShape = FlatArrowButton.createArrowShape( direction, true, cw, ch );
// fix position of controls
x = group.getComponentOrientation().isLeftToRight() ? (group.getWidth() - width - y) : y;
// compute chevron position
int cx = (int) (x + width / 2 - cw / 2);
int cy = (int) (y + (height / 2 - ch));
float offset = ch + UIScale.scale( 1f );
// set stroke with scaled width
g2.setStroke( new BasicStroke( scale( 1f ) ) );
// paint
g2.translate( cx, cy );
g2.draw( arrowShape );
g2.translate( 0, offset );
g2.draw( arrowShape );
g2.translate( -cx, -(cy + offset) );
}
@Override
protected void paintTitle( JXTaskPane group, Graphics g, Color textColor,
int x, int y, int width, int height )
{
// scale title position
int titleX = UIScale.scale( 3 );
int titleWidth = group.getWidth() - getTitleHeight(group) - titleX;
if( !group.getComponentOrientation().isLeftToRight() ) {
// right-to-left
titleX = group.getWidth() - titleX - titleWidth;
}
super.paintTitle( group, g, textColor, titleX, y, titleWidth, height );
}
@Override
protected void paintFocus( Graphics g, Color paintColor, int x, int y, int width, int height ) {
// scale focus rectangle
int sx = UIScale.scale( x );
int sy = UIScale.scale( y );
int swidth = width - (sx - x) * 2;
int sheight = height - (sy - y) * 2;
super.paintFocus( g, paintColor, sx, sy, swidth, sheight );
}
@Override
protected boolean isMouseOverBorder() {
return true;
}
}
}

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.swingx.FlatSwingXDefaultsAddon

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.swingx.FlatLookAndFeelAddons

View File

@@ -0,0 +1,69 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- BusyLabel ----
JXBusyLabel.baseColor=777777
JXBusyLabel.highlightColor=e0e0e0
#---- Header ----
JXHeader.background=@background
JXHeader.startBackground=4c5052
#---- Hyperlink ----
Hyperlink.linkColor=589df6
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- MonthView ----
JXMonthView.background=@textComponentBackground
JXMonthView.monthStringBackground=4c5052
JXMonthView.monthStringForeground=@foreground
JXMonthView.daysOfTheWeekForeground=aaaaaa
JXMonthView.weekOfTheYearForeground=888888
JXMonthView.unselectableDayForeground=E05555
JXMonthView.selectedBackground=@selectionBackground
JXMonthView.flaggedDayForeground=E05555
JXMonthView.leadingDayForeground=@disabledText
JXMonthView.trailingDayForeground=@disabledText
JXMonthView.arrowColor=@foreground
JXMonthView.disabledArrowColor=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=3E434C
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=4c5052
TaskPane.titleForeground=@foreground
TaskPane.titleOver=888888
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

@@ -0,0 +1,35 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- UI delegates ----
BusyLabelUI=com.formdev.flatlaf.swingx.ui.FlatBusyLabelUI
DatePickerUI=com.formdev.flatlaf.swingx.ui.FlatDatePickerUI
HeaderUI=com.formdev.flatlaf.swingx.ui.FlatHeaderUI
HyperlinkUI=com.formdev.flatlaf.swingx.ui.FlatHyperlinkUI
MonthViewUI=com.formdev.flatlaf.swingx.ui.FlatMonthViewUI
swingx/TaskPaneUI=com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI
#---- DatePicker ----
JXDatePicker.border=com.formdev.flatlaf.swingx.ui.FlatDatePickerBorder
#---- MonthView ----
JXMonthView.monthDownFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthDownIcon
JXMonthView.monthUpFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthUpIcon

View File

@@ -0,0 +1,69 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- BusyLabel ----
JXBusyLabel.baseColor=c4c4c4
JXBusyLabel.highlightColor=808080
#---- Header ----
JXHeader.background=@background
JXHeader.startBackground=ffffff
#---- Hyperlink ----
Hyperlink.linkColor=4a78c2
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- MonthView ----
JXMonthView.background=@textComponentBackground
JXMonthView.monthStringBackground=dfdfdf
JXMonthView.monthStringForeground=@foreground
JXMonthView.daysOfTheWeekForeground=444444
JXMonthView.weekOfTheYearForeground=666666
JXMonthView.unselectableDayForeground=E02222
JXMonthView.selectedBackground=B9CEF8
JXMonthView.flaggedDayForeground=E02222
JXMonthView.leadingDayForeground=@disabledText
JXMonthView.trailingDayForeground=@disabledText
JXMonthView.arrowColor=@foreground
JXMonthView.disabledArrowColor=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=E6EBF0
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=dfdfdf
TaskPane.titleForeground=222222
TaskPane.titleOver=666666
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

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

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import javax.swing.*;
import net.miginfocom.swing.*;
@@ -23,11 +23,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatChooserTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
frame.showFrame( new FlatChooserTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
frame.showFrame( FlatChooserTest::new );
} );
}
FlatChooserTest() {
@@ -54,7 +56,7 @@ public class FlatChooserTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]",

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][]"
"$rowConstraints": "[top][top][]"
} ) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import javax.swing.*;
import javax.swing.table.*;
@@ -24,11 +24,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatComponents2Test
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponents2Test" );
frame.showFrame( new FlatComponents2Test() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponents2Test" );
frame.showFrame( FlatComponents2Test::new );
} );
}
FlatComponents2Test() {
@@ -60,7 +62,7 @@ public class FlatComponents2Test
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[200]" +

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][200][200]"
"$rowConstraints": "[][][][::200][::150]"
} ) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import javax.swing.*;
@@ -25,11 +25,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatComponentsTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" );
frame.showFrame( new FlatComponentsTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" );
frame.showFrame( FlatComponentsTest::new );
} );
}
FlatComponentsTest() {
@@ -143,7 +145,14 @@ public class FlatComponentsTest
JToggleButton toggleButton7 = new JToggleButton();
JLabel scrollBarLabel = new JLabel();
JScrollBar scrollBar1 = new JScrollBar();
JLabel label4 = new JLabel();
JScrollBar scrollBar4 = new JScrollBar();
JPanel panel3 = new JPanel();
JLabel label3 = new JLabel();
JScrollPane scrollPane15 = new JScrollPane();
JEditorPane editorPane6 = new JEditorPane();
JScrollPane scrollPane16 = new JScrollPane();
JTextPane textPane6 = new JTextPane();
JLabel separatorLabel = new JLabel();
JSeparator separator1 = new JSeparator();
JPanel panel2 = new JPanel();
@@ -169,7 +178,7 @@ public class FlatComponentsTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]" +
@@ -223,17 +232,20 @@ public class FlatComponentsTest
//---- button1 ----
button1.setText("enabled");
button1.setDisplayedMnemonicIndex(0);
button1.setToolTipText("This button is enabled.");
add(button1, "cell 1 1");
//---- button2 ----
button2.setText("disabled");
button2.setDisplayedMnemonicIndex(0);
button2.setEnabled(false);
button2.setToolTipText("This button is disabled.");
add(button2, "cell 2 1");
//---- button5 ----
button5.setText("default");
button5.setDisplayedMnemonicIndex(0);
button5.setToolTipText("Tool tip with\nmultiple\nlines.");
add(button5, "cell 3 1");
//---- button3 ----
@@ -337,7 +349,15 @@ public class FlatComponentsTest
"editable",
"a",
"bb",
"ccc"
"ccc",
"dd",
"e",
"ff",
"ggg",
"hh",
"i",
"jj",
"kkk"
}));
add(comboBox1, "cell 1 5,growx");
@@ -357,7 +377,15 @@ public class FlatComponentsTest
"not editable",
"a",
"bb",
"ccc"
"ccc",
"dd",
"e",
"ff",
"ggg",
"hh",
"i",
"jj",
"kkk"
}));
add(comboBox3, "cell 3 5,growx");
@@ -719,11 +747,53 @@ public class FlatComponentsTest
scrollBar1.setOrientation(Adjustable.HORIZONTAL);
add(scrollBar1, "cell 1 14,growx");
//---- label4 ----
label4.setText("HTML:");
add(label4, "cell 5 14");
//---- scrollBar4 ----
scrollBar4.setOrientation(Adjustable.HORIZONTAL);
scrollBar4.setEnabled(false);
add(scrollBar4, "cell 1 15,growx");
//======== panel3 ========
{
panel3.setOpaque(false);
panel3.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[]",
// rows
"[]" +
"[]" +
"[]"));
//---- label3 ----
label3.setText("<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>");
panel3.add(label3, "cell 0 0");
//======== scrollPane15 ========
{
//---- editorPane6 ----
editorPane6.setContentType("text/html");
editorPane6.setText("JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u>");
scrollPane15.setViewportView(editorPane6);
}
panel3.add(scrollPane15, "cell 0 1,grow");
//======== scrollPane16 ========
{
//---- textPane6 ----
textPane6.setContentType("text/html");
textPane6.setText("JTextPane HTML<br>Sample <b>content</b><br> <u>text</u>");
scrollPane16.setViewportView(textPane6);
}
panel3.add(scrollPane16, "cell 0 2,grow");
}
add(panel3, "cell 5 15 1 7,aligny top,grow 100 0");
//---- separatorLabel ----
separatorLabel.setText("JSeparator:");
add(separatorLabel, "cell 0 16");
@@ -732,6 +802,7 @@ public class FlatComponentsTest
//======== panel2 ========
{
panel2.setBorder(new TitledBorder("TitledBorder"));
panel2.setOpaque(false);
panel2.setLayout(new FlowLayout());
}
add(panel2, "cell 3 16,grow");

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][][][][]"
"$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][]"
} ) {
@@ -43,6 +43,7 @@ new FormModel {
name: "button1"
"text": "enabled"
"displayedMnemonicIndex": 0
"toolTipText": "This button is enabled."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
@@ -51,13 +52,15 @@ new FormModel {
"text": "disabled"
"displayedMnemonicIndex": 0
"enabled": false
"toolTipText": "This button is disabled."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatComponentsTest$TestDefaultButton" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatComponentsTest$TestDefaultButton" ) {
name: "button5"
"text": "default"
"displayedMnemonicIndex": 0
"toolTipText": "Tool tip with\nmultiple\nlines."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 1"
} )
@@ -203,6 +206,14 @@ new FormModel {
addElement( "a" )
addElement( "bb" )
addElement( "ccc" )
addElement( "dd" )
addElement( "e" )
addElement( "ff" )
addElement( "ggg" )
addElement( "hh" )
addElement( "i" )
addElement( "jj" )
addElement( "kkk" )
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5,growx"
@@ -229,6 +240,14 @@ new FormModel {
addElement( "a" )
addElement( "bb" )
addElement( "ccc" )
addElement( "dd" )
addElement( "e" )
addElement( "ff" )
addElement( "ggg" )
addElement( "hh" )
addElement( "i" )
addElement( "jj" )
addElement( "kkk" )
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 5,growx"
@@ -678,6 +697,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 14,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "HTML:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 14"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar4"
"orientation": 0
@@ -685,6 +710,42 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15,growx"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[][][]"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel3"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane15"
add( new FormComponent( "javax.swing.JEditorPane" ) {
name: "editorPane6"
"contentType": "text/html"
"text": "JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u>"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,grow"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane16"
add( new FormComponent( "javax.swing.JTextPane" ) {
name: "textPane6"
"contentType": "text/html"
"text": "JTextPane HTML<br>Sample <b>content</b><br> <u>text</u>"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2,grow"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 15 1 7,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "separatorLabel"
"text": "JSeparator:"
@@ -699,6 +760,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": new javax.swing.border.TitledBorder( "TitledBorder" )
"opaque": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 16,grow"
} )
@@ -837,7 +899,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 715 )
"size": new java.awt.Dimension( 790, 750 )
} )
}
}

View File

@@ -2,8 +2,9 @@
* Created by JFormDesigner on Tue Aug 27 21:47:02 CEST 2019
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -14,11 +15,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatContainerTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatContainerTest" );
frame.showFrame( new FlatContainerTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatContainerTest" );
frame.showFrame( FlatContainerTest::new );
} );
}
public FlatContainerTest() {
@@ -35,10 +38,10 @@ public class FlatContainerTest
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane2.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane3.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane4.putClientProperty( "JTabbedPane.hasFullBorder", hasFullBorder );
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane2.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane3.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane4.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
}
private void moreTabsChanged() {
@@ -102,7 +105,7 @@ public class FlatContainerTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3",
"insets dialog,hidemode 3",
// columns
"[grow,fill]",
// rows
@@ -110,6 +113,7 @@ public class FlatContainerTest
//======== panel9 ========
{
panel9.setOpaque(false);
panel9.setLayout(new FormLayout(
"70dlu:grow, $lcgap, 70dlu:grow",
"default, $lgap, fill:70dlu, $lgap, pref, 2*($lgap, fill:70dlu:grow), $lgap, pref"));
@@ -281,6 +285,7 @@ public class FlatContainerTest
//======== panel14 ========
{
panel14.setOpaque(false);
panel14.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
@@ -17,6 +17,7 @@ new FormModel {
"$rowSpecs": "default, linegap, fill:70dlu, linegap, pref, linegap, fill:70dlu:grow, linegap, fill:70dlu:grow, linegap, pref"
} ) {
name: "panel9"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "splitPaneLabel"
"text": "JSplitPane:"
@@ -203,6 +204,7 @@ new FormModel {
"$rowConstraints": "[center]"
} ) {
name: "panel14"
"opaque": false
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "moreTabsCheckBox"
"text": "more tabs"

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.Color;
import java.awt.Component;
@@ -58,6 +58,7 @@ public class FlatInspector
private Component lastComponent;
private int lastX;
private int lastY;
private boolean inspectParent;
private JComponent highlightFigure;
private JToolTip tip;
@@ -70,6 +71,7 @@ public class FlatInspector
public void mouseMoved( MouseEvent e ) {
lastX = e.getX();
lastY = e.getY();
inspectParent = e.isShiftDown();
inspect( lastX, lastY );
}
} );
@@ -105,6 +107,8 @@ public class FlatInspector
private void inspect( int x, int y ) {
Container contentPane = rootPane.getContentPane();
Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y );
if( inspectParent && c != null && c != contentPane )
c = c.getParent();
if( c == contentPane || (c != null && c.getParent() == contentPane) )
c = null;
@@ -236,6 +240,11 @@ public class FlatInspector
}
}
text += "Enabled: " + c.isEnabled() + '\n';
text += "Opaque: " + c.isOpaque() + (c instanceof JComponent &&
FlatUIUtils.hasOpaqueBeenExplicitlySet( (JComponent) c ) ? " EXPLICIT" : "") + '\n';
text += "Focusable: " + c.isFocusable() + '\n';
text += "Left-to-right: " + c.getComponentOrientation().isLeftToRight() + '\n';
text += "Parent: " + c.getParent().getClass().getName();
return text;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.Component;
import java.awt.Container;
@@ -26,11 +26,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatMenusTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatMenusTest" );
frame.showFrame( new FlatMenusTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatMenusTest" );
frame.showFrame( FlatMenusTest::new );
} );
}
FlatMenusTest() {
@@ -101,7 +103,7 @@ public class FlatMenusTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[125]" +
"[]" +
@@ -153,8 +155,9 @@ public class FlatMenusTest
//======== panel1 ========
{
panel1.setOpaque(false);
panel1.setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets 0,hidemode 3",
// columns
"[125,left]" +
"[fill]",
@@ -211,8 +214,9 @@ public class FlatMenusTest
//======== panel2 ========
{
panel2.setOpaque(false);
panel2.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows
@@ -251,8 +255,9 @@ public class FlatMenusTest
//======== panel3 ========
{
panel3.setOpaque(false);
panel3.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows
@@ -290,8 +295,9 @@ public class FlatMenusTest
//======== panel4 ========
{
panel4.setOpaque(false);
panel4.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[125][][][][]"
"$rowConstraints": "[][top][][]"
} ) {
@@ -50,9 +50,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[125,left][fill]"
"$rowConstraints": "[][][][][]"
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel1"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "menuLabel"
"text": "JMenu:"
@@ -121,9 +122,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel2"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu2"
"text": "disabled"
@@ -161,9 +163,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel3"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu3"
"text": "text"
@@ -201,9 +204,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel4"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu4"
"text": "text"

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.awt.event.MouseAdapter;
@@ -27,11 +27,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatOptionPaneTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" );
frame.showFrame( new FlatOptionPaneTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" );
frame.showFrame( FlatOptionPaneTest::new );
} );
}
FlatOptionPaneTest() {
@@ -88,7 +90,7 @@ public class FlatOptionPaneTest
//======== this ========
setLayout(new MigLayout(
"flowy,ltr,insets 0,hidemode 3,gap 5 5",
"flowy,ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]" +
@@ -201,7 +203,7 @@ public class FlatOptionPaneTest
//---- warningOptionPane ----
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
warningOptionPane.setMessage("Beware of the dog!");
warningOptionPane.setMessage("<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines.");
panel5.add(warningOptionPane, BorderLayout.CENTER);
}
add(panel5, "cell 1 4");

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "flowy,ltr,insets 0,hidemode 3,gap 5 5"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "flowy,ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][fill]"
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
} ) {
@@ -30,7 +30,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "plainShowDialogLabel"
"optionPane": new FormReference( "plainOptionPane" )
"titleLabel": new FormReference( "plainLabel" )
@@ -60,7 +60,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "errorShowDialogLabel"
"titleLabel": new FormReference( "errorLabel" )
"optionPane": new FormReference( "errorOptionPane" )
@@ -90,7 +90,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "informationShowDialogLabel"
"optionPane": new FormReference( "informationOptionPane" )
"titleLabel": new FormReference( "informationLabel" )
@@ -120,7 +120,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "questionShowDialogLabel"
"optionPane": new FormReference( "questionOptionPane" )
"titleLabel": new FormReference( "questionLabel" )
@@ -140,14 +140,14 @@ new FormModel {
name: "warningOptionPane"
"messageType": 2
"optionType": 2
"message": "Beware of the dog!"
"message": "<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines."
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "Center"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "warningShowDialogLabel"
"optionPane": new FormReference( "warningOptionPane" )
"titleLabel": new FormReference( "warningLabel" )
@@ -174,7 +174,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "inputShowDialogLabel"
"optionPane": new FormReference( "inputOptionPane" )
"titleLabel": new FormReference( "inputLabel" )
@@ -202,7 +202,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "inputIconShowDialogLabel"
"titleLabel": new FormReference( "inputIconLabel" )
"optionPane": new FormReference( "inputIconOptionPane" )
@@ -230,7 +230,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "customShowDialogLabel"
"optionPane": new FormReference( "customOptionPane" )
"titleLabel": new FormReference( "customLabel" )
@@ -239,7 +239,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 840 )
"size": new java.awt.Dimension( 790, 920 )
} )
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.awt.event.ComponentAdapter;
@@ -22,13 +22,20 @@ import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.extras.TriStateCheckBox.State;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -45,9 +52,12 @@ public class FlatTestFrame
private static final String KEY_SCALE_FACTOR = "scaleFactor";
private final String title;
private Supplier<JComponent> contentFactory;
private JComponent content;
private FlatInspector inspector;
public boolean useApplyComponentOrientation;
public static FlatTestFrame create( String[] args, String title ) {
Preferences prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
@@ -205,8 +215,9 @@ public class FlatTestFrame
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
}
protected void showFrame( JComponent content ) {
this.content = content;
public void showFrame( Supplier<JComponent> contentFactory ) {
this.contentFactory = contentFactory;
this.content = contentFactory.get();
contentPanel.getContentPane().add( content );
pack();
@@ -290,7 +301,15 @@ public class FlatTestFrame
boolean explicit = explicitColorsCheckBox.isSelected();
ColorUIResource restoreColor = new ColorUIResource( Color.white );
explicitColors( content, explicit, restoreColor );
updateComponentsRecur( content, (c, type) -> {
if( type == "view" || type == "tab" ) {
c.setForeground( explicit ? Color.magenta : restoreColor );
c.setBackground( explicit ? Color.orange : restoreColor );
} else {
c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.green : restoreColor );
}
} );
// because colors may depend on state (e.g. disabled JTextField)
// it is best to update all UI delegates to get correct result
@@ -299,78 +318,35 @@ public class FlatTestFrame
} );
}
private void explicitColors( Container container, boolean explicit, ColorUIResource restoreColor ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
explicitColors( (JPanel) c, explicit, restoreColor );
continue;
}
c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.red : restoreColor );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null ) {
view.setForeground( explicit ? Color.magenta : restoreColor );
view.setBackground( explicit ? Color.orange : restoreColor );
}
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null ) {
tab.setForeground( explicit ? Color.magenta : restoreColor );
tab.setBackground( explicit ? Color.orange : restoreColor );
}
}
}
if( c instanceof JToolBar )
explicitColors( (JToolBar) c, explicit, restoreColor );
}
private void backgroundChanged() {
contentPanel.repaint();
}
boolean isPaintBackgroundPattern() {
return backgroundCheckBox.isSelected();
}
private void rightToLeftChanged() {
contentPanel.applyComponentOrientation( rightToLeftCheckBox.isSelected()
ComponentOrientation orientation = rightToLeftCheckBox.isSelected()
? ComponentOrientation.RIGHT_TO_LEFT
: ComponentOrientation.LEFT_TO_RIGHT );
: ComponentOrientation.LEFT_TO_RIGHT;
if( useApplyComponentOrientation )
content.applyComponentOrientation( orientation );
else {
updateComponentsRecur( content, (c, type) -> {
c.setComponentOrientation( orientation );
} );
}
contentPanel.revalidate();
contentPanel.repaint();
}
private void enabledChanged() {
enabledDisable( content, enabledCheckBox.isSelected() );
}
private void enabledDisable( Container container, boolean enabled ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
enabledDisable( (JPanel) c, enabled );
continue;
}
boolean enabled = enabledCheckBox.isSelected();
updateComponentsRecur( content, (c, type) -> {
c.setEnabled( enabled );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null )
view.setEnabled( enabled );
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null )
tab.setEnabled( enabled );
}
}
if( c instanceof JToolBar )
enabledDisable( (JToolBar) c, enabled );
}
} );
}
private void inspectChanged() {
@@ -404,17 +380,76 @@ public class FlatTestFrame
scaleFactorComboBox.setEnabled( !UIScale.isSystemScalingEnabled() && UIManager.getLookAndFeel() instanceof FlatLaf );
}
private void updateComponentsRecur( Container container, BiConsumer<Component, String> action ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
updateComponentsRecur( (JPanel) c, action );
continue;
}
action.accept( c, null );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null )
action.accept( view, "view" );
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null )
action.accept( tab, "tab" );
}
}
if( c instanceof JToolBar )
updateComponentsRecur( (JToolBar) c, action );
}
}
private void opaqueChanged() {
State opaque = opaqueTriStateCheckBox.getState();
if( opaque == State.INDETERMINATE )
recreateContent();
else {
updateComponentsRecur( content, (c, type) -> {
if( c instanceof JComponent )
((JComponent)c).setOpaque( opaque == State.SELECTED );
} );
contentPanel.repaint();
}
}
private void recreateContent() {
contentPanel.getContentPane().remove( content );
content = contentFactory.get();
contentPanel.getContentPane().add( content );
if( rightToLeftCheckBox.isSelected() )
rightToLeftChanged();
if( !enabledCheckBox.isSelected() )
enabledChanged();
if( explicitColorsCheckBox.isSelected() )
explicitColorsChanged();
contentPanel.revalidate();
contentPanel.repaint();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
dialogPane = new JPanel();
contentPanel = new JRootPane();
buttonBar = new JPanel();
lookAndFeelComboBox = new JComboBox<>();
explicitColorsCheckBox = new JCheckBox();
scaleFactorComboBox = new JComboBox<>();
rightToLeftCheckBox = new JCheckBox();
enabledCheckBox = new JCheckBox();
inspectCheckBox = new JCheckBox();
scaleFactorComboBox = new JComboBox<>();
explicitColorsCheckBox = new JCheckBox();
backgroundCheckBox = new JCheckBox();
opaqueTriStateCheckBox = new TriStateCheckBox();
closeButton = new JButton();
//======== this ========
@@ -430,7 +465,7 @@ public class FlatTestFrame
{
Container contentPanelContentPane = contentPanel.getContentPane();
contentPanelContentPane.setLayout(new MigLayout(
"insets dialog,hidemode 3",
"insets 0,hidemode 3",
// columns
"[grow,fill]",
// rows
@@ -449,6 +484,8 @@ public class FlatTestFrame
"[fill]" +
"[fill]" +
"[fill]" +
"[fill]" +
"[fill]" +
"[grow,fill]" +
"[button,fill]",
// rows
@@ -458,11 +495,23 @@ public class FlatTestFrame
lookAndFeelComboBox.addActionListener(e -> lookAndFeelChanged());
buttonBar.add(lookAndFeelComboBox, "cell 0 0");
//---- explicitColorsCheckBox ----
explicitColorsCheckBox.setText("explicit colors");
explicitColorsCheckBox.setMnemonic('X');
explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged());
buttonBar.add(explicitColorsCheckBox, "cell 1 0");
//---- scaleFactorComboBox ----
scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"default",
"1",
"1.25",
"1.5",
"1.75",
"2.0",
"2.25",
"2.5",
"3",
"3.5",
"4"
}));
scaleFactorComboBox.setMaximumRowCount(20);
scaleFactorComboBox.addActionListener(e -> scaleFactorChanged());
buttonBar.add(scaleFactorComboBox, "cell 1 0");
//---- rightToLeftCheckBox ----
rightToLeftCheckBox.setText("right-to-left");
@@ -483,27 +532,27 @@ public class FlatTestFrame
inspectCheckBox.addActionListener(e -> inspectChanged());
buttonBar.add(inspectCheckBox, "cell 4 0");
//---- scaleFactorComboBox ----
scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"default",
"1",
"1.25",
"1.5",
"1.75",
"2.0",
"2.25",
"2.5",
"3",
"3.5",
"4"
}));
scaleFactorComboBox.setMaximumRowCount(20);
scaleFactorComboBox.addActionListener(e -> scaleFactorChanged());
buttonBar.add(scaleFactorComboBox, "cell 5 0");
//---- explicitColorsCheckBox ----
explicitColorsCheckBox.setText("explicit colors");
explicitColorsCheckBox.setMnemonic('X');
explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged());
buttonBar.add(explicitColorsCheckBox, "cell 5 0");
//---- backgroundCheckBox ----
backgroundCheckBox.setText("background");
backgroundCheckBox.setMnemonic('B');
backgroundCheckBox.addActionListener(e -> backgroundChanged());
buttonBar.add(backgroundCheckBox, "cell 6 0");
//---- opaqueTriStateCheckBox ----
opaqueTriStateCheckBox.setText("opaque");
opaqueTriStateCheckBox.setMnemonic('O');
opaqueTriStateCheckBox.addActionListener(e -> opaqueChanged());
buttonBar.add(opaqueTriStateCheckBox, "cell 7 0");
//---- closeButton ----
closeButton.setText("Close");
buttonBar.add(closeButton, "cell 7 0");
buttonBar.add(closeButton, "cell 9 0");
}
dialogPane.add(buttonBar, BorderLayout.SOUTH);
}
@@ -516,11 +565,13 @@ public class FlatTestFrame
private JRootPane contentPanel;
private JPanel buttonBar;
private JComboBox<LafInfo> lookAndFeelComboBox;
private JCheckBox explicitColorsCheckBox;
private JComboBox<String> scaleFactorComboBox;
private JCheckBox rightToLeftCheckBox;
private JCheckBox enabledCheckBox;
private JCheckBox inspectCheckBox;
private JComboBox<String> scaleFactorComboBox;
private JCheckBox explicitColorsCheckBox;
private JCheckBox backgroundCheckBox;
private TriStateCheckBox opaqueTriStateCheckBox;
private JButton closeButton;
// JFormDesigner - End of variables declaration //GEN-END:variables

View File

@@ -11,7 +11,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
name: "dialogPane"
add( new FormContainer( "javax.swing.JRootPane", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
@@ -21,7 +21,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog"
"$columnConstraints": "[fill][fill][fill][fill][fill][fill][grow,fill][button,fill]"
"$columnConstraints": "[fill][fill][fill][fill][fill][fill][fill][fill][grow,fill][button,fill]"
"$rowSpecs": "[fill]"
} ) {
name: "buttonBar"
@@ -34,11 +34,27 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "explicitColorsCheckBox"
"text": "explicit colors"
"mnemonic": 88
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "scaleFactorComboBox"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "default"
addElement( "default" )
addElement( "1" )
addElement( "1.25" )
addElement( "1.5" )
addElement( "1.75" )
addElement( "2.0" )
addElement( "2.25" )
addElement( "2.5" )
addElement( "3" )
addElement( "3.5" )
addElement( "4" )
}
"maximumRowCount": 20
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scaleFactorChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
@@ -67,35 +83,35 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "scaleFactorComboBox"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "default"
addElement( "default" )
addElement( "1" )
addElement( "1.25" )
addElement( "1.5" )
addElement( "1.75" )
addElement( "2.0" )
addElement( "2.25" )
addElement( "2.5" )
addElement( "3" )
addElement( "3.5" )
addElement( "4" )
}
"maximumRowCount": 20
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scaleFactorChanged", false ) )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "explicitColorsCheckBox"
"text": "explicit colors"
"mnemonic": 88
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "backgroundCheckBox"
"text": "background"
"mnemonic": 66
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "backgroundChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 6 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "opaqueTriStateCheckBox"
"text": "opaque"
"mnemonic": 79
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "opaqueChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 0"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "closeButton"
"text": "Close"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 0"
"value": "cell 9 0"
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "South"

View File

@@ -14,11 +14,15 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import com.formdev.flatlaf.FlatLaf;
/**
* A Flat LaF that has a test color scheme.
*
* The UI defaults are loaded from FlatTestLaf.properties and FlatLaf.properties
*
* Used to develop Flat LaF.
*
* @author Karl Tauber
@@ -35,4 +39,9 @@ public class FlatTestLaf
public String getDescription() {
return "Flat Test Look and Feel";
}
@Override
public boolean isDark() {
return false;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.testing;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* @author Karl Tauber
*/
public class FlatTestPanel
extends JPanel
{
@Override
protected void paintComponent( Graphics g ) {
int width = getWidth();
int height = getHeight();
g.setColor( super.getBackground() );
g.fillRect( 0, 0, width, height );
if( isPaintBackgroundPattern() ) {
g.setColor( Color.magenta );
for( int y = 0; y < height; y += 2 )
g.drawLine( 0, y, width - 1, y );
}
}
/**
* Overridden to see which components paint background with color from parent.
*/
@Override
public Color getBackground() {
return isPaintBackgroundPattern() ? Color.red : super.getBackground();
}
private boolean isPaintBackgroundPattern() {
FlatTestFrame frame = (FlatTestFrame) SwingUtilities.getAncestorOfClass( FlatTestFrame.class, this );
return frame != null && frame.isPaintBackgroundPattern();
}
}

View File

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

View File

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

View File

@@ -0,0 +1,294 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.testing.jideoss;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import com.formdev.flatlaf.testing.*;
import com.formdev.flatlaf.testing.FlatTestFrame;
import com.jgoodies.forms.layout.*;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.swing.*;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatJideOssTest
extends FlatTestPanel
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatJideOssTest" );
LookAndFeelFactory.installJideExtension();
frame.showFrame( FlatJideOssTest::new );
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
LookAndFeelFactory.installJideExtension();
}
} );
} );
}
FlatJideOssTest() {
initComponents();
}
private void tabScrollChanged() {
int tabLayoutPolicy = tabScrollCheckBox.isSelected() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT;
tabbedPane1.setTabLayoutPolicy( tabLayoutPolicy );
tabbedPane2.setTabLayoutPolicy( tabLayoutPolicy );
tabbedPane3.setTabLayoutPolicy( tabLayoutPolicy );
tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy );
}
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane2.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane3.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
tabbedPane4.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
}
private void moreTabsChanged() {
boolean moreTabs = moreTabsCheckBox.isSelected();
addRemoveMoreTabs( tabbedPane1, moreTabs );
addRemoveMoreTabs( tabbedPane2, moreTabs );
addRemoveMoreTabs( tabbedPane3, moreTabs );
addRemoveMoreTabs( tabbedPane4, moreTabs );
}
private void addRemoveMoreTabs( JTabbedPane tabbedPane, boolean add ) {
if( add ) {
tabbedPane.addTab( "Tab 4", new JLabel( "tab 4" ) );
tabbedPane.addTab( "Tab 5", new JLabel( "tab 5" ) );
} else {
int tabCount = tabbedPane.getTabCount();
if( tabCount > 3 ) {
for( int i = 0; i < 2; i++ )
tabbedPane.removeTabAt( tabbedPane.getTabCount() - 1 );
}
}
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JPanel panel9 = new JPanel();
JLabel tabbedPaneLabel = new JLabel();
tabbedPane1 = new JideTabbedPane();
JPanel panel1 = new JPanel();
JLabel label1 = new JLabel();
JPanel panel2 = new JPanel();
JLabel label2 = new JLabel();
tabbedPane3 = new JideTabbedPane();
JPanel panel5 = new JPanel();
JLabel label5 = new JLabel();
JPanel panel6 = new JPanel();
JLabel label6 = new JLabel();
tabbedPane2 = new JideTabbedPane();
JPanel panel3 = new JPanel();
JLabel label3 = new JLabel();
JPanel panel4 = new JPanel();
JLabel label4 = new JLabel();
tabbedPane4 = new JideTabbedPane();
JPanel panel7 = new JPanel();
JLabel label7 = new JLabel();
JPanel panel8 = new JPanel();
JLabel label8 = new JLabel();
JPanel panel14 = new JPanel();
moreTabsCheckBox = new JCheckBox();
tabScrollCheckBox = new JCheckBox();
hasFullBorderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
//======== this ========
setLayout(new MigLayout(
"insets dialog,hidemode 3",
// columns
"[grow,fill]",
// rows
"[grow,fill]"));
//======== panel9 ========
{
panel9.setOpaque(false);
panel9.setLayout(new FormLayout(
"70dlu:grow, $lcgap, 70dlu:grow",
"pref, 2*($lgap, fill:70dlu:grow), $lgap, pref"));
//---- tabbedPaneLabel ----
tabbedPaneLabel.setText("JideTabbedPane:");
panel9.add(tabbedPaneLabel, cc.xy(1, 1));
//======== tabbedPane1 ========
{
//======== panel1 ========
{
panel1.setLayout(new FlowLayout());
//---- label1 ----
label1.setText("TOP");
panel1.add(label1);
}
tabbedPane1.addTab("Tab 1", panel1);
//======== panel2 ========
{
panel2.setBorder(new LineBorder(Color.magenta));
panel2.setLayout(new FlowLayout());
}
tabbedPane1.addTab("Tab 2", panel2);
//---- label2 ----
label2.setText("text");
tabbedPane1.addTab("Tab 3", label2);
}
panel9.add(tabbedPane1, cc.xy(1, 3));
//======== tabbedPane3 ========
{
tabbedPane3.setTabPlacement(SwingConstants.LEFT);
//======== panel5 ========
{
panel5.setLayout(new FlowLayout());
//---- label5 ----
label5.setText("LEFT");
panel5.add(label5);
}
tabbedPane3.addTab("Tab 1", panel5);
//======== panel6 ========
{
panel6.setBorder(new LineBorder(Color.magenta));
panel6.setLayout(new FlowLayout());
}
tabbedPane3.addTab("Tab 2", panel6);
//---- label6 ----
label6.setText("text");
tabbedPane3.addTab("Tab 3", label6);
}
panel9.add(tabbedPane3, cc.xy(3, 3));
//======== tabbedPane2 ========
{
tabbedPane2.setTabPlacement(SwingConstants.BOTTOM);
//======== panel3 ========
{
panel3.setLayout(new FlowLayout());
//---- label3 ----
label3.setText("BOTTOM");
panel3.add(label3);
}
tabbedPane2.addTab("Tab 1", panel3);
//======== panel4 ========
{
panel4.setBorder(new LineBorder(Color.magenta));
panel4.setLayout(new FlowLayout());
}
tabbedPane2.addTab("Tab 2", panel4);
tabbedPane2.setEnabledAt(1, false);
//---- label4 ----
label4.setText("text");
tabbedPane2.addTab("Tab 3", label4);
}
panel9.add(tabbedPane2, cc.xy(1, 5));
//======== tabbedPane4 ========
{
tabbedPane4.setTabPlacement(SwingConstants.RIGHT);
//======== panel7 ========
{
panel7.setLayout(new FlowLayout());
//---- label7 ----
label7.setText("RIGHT");
panel7.add(label7);
}
tabbedPane4.addTab("Tab 1", panel7);
//======== panel8 ========
{
panel8.setBorder(new LineBorder(Color.magenta));
panel8.setLayout(new FlowLayout());
}
tabbedPane4.addTab("Tab 2", panel8);
//---- label8 ----
label8.setText("text");
tabbedPane4.addTab("Tab 3", label8);
}
panel9.add(tabbedPane4, cc.xy(3, 5));
//======== panel14 ========
{
panel14.setOpaque(false);
panel14.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns
"[]" +
"[]" +
"[]",
// rows
"[center]"));
//---- moreTabsCheckBox ----
moreTabsCheckBox.setText("more tabs");
moreTabsCheckBox.setMnemonic('M');
moreTabsCheckBox.addActionListener(e -> moreTabsChanged());
panel14.add(moreTabsCheckBox, "cell 0 0");
//---- tabScrollCheckBox ----
tabScrollCheckBox.setText("tabLayoutPolicy = SCROLL");
tabScrollCheckBox.setMnemonic('S');
tabScrollCheckBox.setSelected(true);
tabScrollCheckBox.addActionListener(e -> tabScrollChanged());
panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0");
//---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder");
hasFullBorderCheckBox.setMnemonic('F');
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0");
}
panel9.add(panel14, cc.xywh(1, 7, 3, 1));
}
add(panel9, "cell 0 0");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JideTabbedPane tabbedPane1;
private JideTabbedPane tabbedPane3;
private JideTabbedPane tabbedPane2;
private JideTabbedPane tabbedPane4;
private JCheckBox moreTabsCheckBox;
private JCheckBox tabScrollCheckBox;
private JCheckBox hasFullBorderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,203 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
name: "this"
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class com.jgoodies.forms.layout.FormLayout ) {
"$columnSpecs": "70dlu:grow, labelcompgap, 70dlu:grow"
"$rowSpecs": "pref, linegap, fill:70dlu:grow, linegap, fill:70dlu:grow, linegap, pref"
} ) {
name: "panel9"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "tabbedPaneLabel"
"text": "JideTabbedPane:"
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 1
} )
add( new FormContainer( "com.jidesoft.swing.JideTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) {
name: "tabbedPane1"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel1"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "TOP"
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color magenta, 1, false )
}, new FormLayoutConstraints( null ) {
"title": "Tab 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "text"
}, new FormLayoutConstraints( null ) {
"title": "Tab 3"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 1
"gridY": 3
} )
add( new FormContainer( "com.jidesoft.swing.JideTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) {
name: "tabbedPane3"
"tabPlacement": 2
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel5"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label5"
"text": "LEFT"
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel6"
"border": #LineBorder0
}, new FormLayoutConstraints( null ) {
"title": "Tab 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label6"
"text": "text"
}, new FormLayoutConstraints( null ) {
"title": "Tab 3"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 3
"gridY": 3
} )
add( new FormContainer( "com.jidesoft.swing.JideTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) {
name: "tabbedPane2"
"tabPlacement": 3
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel3"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "BOTTOM"
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel4"
"border": #LineBorder0
}, new FormLayoutConstraints( null ) {
"title": "Tab 2"
"enabled": false
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "text"
}, new FormLayoutConstraints( null ) {
"title": "Tab 3"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 5
} )
add( new FormContainer( "com.jidesoft.swing.JideTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) {
name: "tabbedPane4"
"tabPlacement": 4
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel7"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label7"
"text": "RIGHT"
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel8"
"border": #LineBorder0
}, new FormLayoutConstraints( null ) {
"title": "Tab 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label8"
"text": "text"
}, new FormLayoutConstraints( null ) {
"title": "Tab 3"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 3
"gridY": 5
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][][]"
"$rowConstraints": "[center]"
} ) {
name: "panel14"
"opaque": false
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "moreTabsCheckBox"
"text": "more tabs"
"mnemonic": 77
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "moreTabsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "tabScrollCheckBox"
"text": "tabLayoutPolicy = SCROLL"
"mnemonic": 83
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabScrollChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox"
"text": "JTabbedPane.hasFullBorder"
"mnemonic": 70
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 7
"gridWidth": 3
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 500 )
} )
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.testing.swingx;
import java.io.InputStream;
import com.formdev.flatlaf.FlatDefaultsAddon;
/**
* SwingX addon for FlatLaf for testing.
*
* @author Karl Tauber
*/
public class FlatSwingXDefaultsTestAddon
extends FlatDefaultsAddon
{
/**
* Finds SwingX addon .properties file for the given LaF class
* in the same package as this class.
*/
@Override
public InputStream getDefaults( Class<?> lafClass ) {
Class<?> addonClass = this.getClass();
String propertiesName = "/" + addonClass.getPackage().getName().replace( '.', '/' )
+ '/' + lafClass.getSimpleName() + ".properties";
return addonClass.getResourceAsStream( propertiesName );
}
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.testing.swingx;
import java.awt.*;
import java.util.Calendar;
import java.util.Date;
import javax.swing.*;
import net.miginfocom.swing.*;
import org.jdesktop.swingx.*;
import com.formdev.flatlaf.testing.FlatTestFrame;
import com.formdev.flatlaf.testing.FlatTestPanel;
/**
* @author Karl Tauber
*/
public class FlatSwingXTest
extends FlatTestPanel
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSwingXTest" );
frame.useApplyComponentOrientation = true;
frame.showFrame( FlatSwingXTest::new );
} );
}
FlatSwingXTest() {
initComponents();
Calendar calendar = Calendar.getInstance();
calendar.set( Calendar.DAY_OF_MONTH, 2 );
monthView1.setSelectionDate( calendar.getTime() );
calendar.set( Calendar.DAY_OF_MONTH, 9 );
monthView1.setFlaggedDates( calendar.getTime() );
calendar.set( Calendar.DAY_OF_MONTH, 16 );
monthView1.setUnselectableDates( calendar.getTime() );
}
private void busyChanged() {
boolean busy = busyCheckBox.isSelected();
xBusyLabel1.setBusy( busy );
xBusyLabel2.setBusy( busy );
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel label1 = new JLabel();
JLabel label3 = new JLabel();
JLabel datePickerLabel = new JLabel();
JXDatePicker xDatePicker1 = new JXDatePicker();
JXDatePicker xDatePicker2 = new JXDatePicker();
JLabel label4 = new JLabel();
JLabel label5 = new JLabel();
JXDatePicker xDatePicker3 = new JXDatePicker();
JXDatePicker xDatePicker4 = new JXDatePicker();
JLabel monthViewLabel = new JLabel();
monthView1 = new JXMonthView();
monthView2 = new JXMonthView();
JLabel hyperlinkLabel = new JLabel();
JXHyperlink xHyperlink1 = new JXHyperlink();
JXHyperlink xHyperlink2 = new JXHyperlink();
JLabel label2 = new JLabel();
xBusyLabel1 = new JXBusyLabel();
xBusyLabel2 = new JXBusyLabel();
busyCheckBox = new JCheckBox();
JPanel panel2 = new JPanel();
JLabel taskPaneContainerLabel = new JLabel();
JLabel taskPaneLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JXTaskPaneContainer xTaskPaneContainer1 = new JXTaskPaneContainer();
JXTaskPane xTaskPane3 = new JXTaskPane();
JXHyperlink xHyperlink3 = new JXHyperlink();
JXHyperlink xHyperlink4 = new JXHyperlink();
JXHyperlink xHyperlink5 = new JXHyperlink();
JXTaskPane xTaskPane4 = new JXTaskPane();
JXHyperlink xHyperlink6 = new JXHyperlink();
JXHyperlink xHyperlink7 = new JXHyperlink();
JXTaskPane xTaskPane5 = new JXTaskPane();
JXHyperlink xHyperlink8 = new JXHyperlink();
JXTaskPane xTaskPane6 = new JXTaskPane();
JXHyperlink xHyperlink9 = new JXHyperlink();
JXHyperlink xHyperlink10 = new JXHyperlink();
JLabel headerLabel = new JLabel();
JXHeader xHeader1 = new JXHeader();
//======== this ========
setLayout(new MigLayout(
"ltr,insets dialog,hidemode 3",
// columns
"[left]" +
"[]" +
"[]" +
"[fill]",
// rows
"[]0" +
"[]" +
"[]0" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- label1 ----
label1.setText("enabled");
add(label1, "cell 1 0");
//---- label3 ----
label3.setText("disabled");
add(label3, "cell 2 0");
//---- datePickerLabel ----
datePickerLabel.setText("JXDatePicker:");
add(datePickerLabel, "cell 0 1");
add(xDatePicker1, "cell 1 1");
//---- xDatePicker2 ----
xDatePicker2.setEnabled(false);
add(xDatePicker2, "cell 2 1");
//---- label4 ----
label4.setText("not editable");
add(label4, "cell 1 2");
//---- label5 ----
label5.setText("not editable disabled");
add(label5, "cell 2 2");
//---- xDatePicker3 ----
xDatePicker3.setEditable(false);
add(xDatePicker3, "cell 1 3");
//---- xDatePicker4 ----
xDatePicker4.setEnabled(false);
xDatePicker4.setEditable(false);
add(xDatePicker4, "cell 2 3");
//---- monthViewLabel ----
monthViewLabel.setText("JXMonthView:");
add(monthViewLabel, "cell 0 4,aligny top,growy 0");
//---- monthView1 ----
monthView1.setTraversable(true);
monthView1.setShowingLeadingDays(true);
monthView1.setShowingTrailingDays(true);
monthView1.setShowingWeekNumber(true);
add(monthView1, "cell 1 4");
//---- monthView2 ----
monthView2.setTraversable(true);
monthView2.setShowingLeadingDays(true);
monthView2.setShowingTrailingDays(true);
monthView2.setShowingWeekNumber(true);
monthView2.setEnabled(false);
add(monthView2, "cell 2 4");
//---- hyperlinkLabel ----
hyperlinkLabel.setText("JXHyperlink:");
add(hyperlinkLabel, "cell 0 5");
//---- xHyperlink1 ----
xHyperlink1.setText("enabled");
add(xHyperlink1, "cell 1 5");
//---- xHyperlink2 ----
xHyperlink2.setText("disabled");
xHyperlink2.setEnabled(false);
add(xHyperlink2, "cell 2 5");
//---- label2 ----
label2.setText("JXBusyLabel:");
add(label2, "cell 0 6");
//---- xBusyLabel1 ----
xBusyLabel1.setText("enabled");
add(xBusyLabel1, "cell 1 6");
//---- xBusyLabel2 ----
xBusyLabel2.setText("disabled");
xBusyLabel2.setEnabled(false);
add(xBusyLabel2, "cell 2 6,growx");
//---- busyCheckBox ----
busyCheckBox.setText("busy");
busyCheckBox.setMnemonic('Y');
busyCheckBox.addActionListener(e -> busyChanged());
add(busyCheckBox, "cell 2 6");
//======== panel2 ========
{
panel2.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]" +
"[]" +
"[]"));
//---- taskPaneContainerLabel ----
taskPaneContainerLabel.setText("JXTaskPaneContainer:");
panel2.add(taskPaneContainerLabel, "cell 0 0");
//---- taskPaneLabel ----
taskPaneLabel.setText("JXTaskPane:");
panel2.add(taskPaneLabel, "cell 0 1");
//======== scrollPane1 ========
{
//======== xTaskPaneContainer1 ========
{
//======== xTaskPane3 ========
{
xTaskPane3.setTitle("Basic Tasks");
Container xTaskPane3ContentPane = xTaskPane3.getContentPane();
//---- xHyperlink3 ----
xHyperlink3.setText("New");
xTaskPane3ContentPane.add(xHyperlink3);
//---- xHyperlink4 ----
xHyperlink4.setText("Open");
xTaskPane3ContentPane.add(xHyperlink4);
//---- xHyperlink5 ----
xHyperlink5.setText("Save");
xTaskPane3ContentPane.add(xHyperlink5);
}
xTaskPaneContainer1.add(xTaskPane3);
//======== xTaskPane4 ========
{
xTaskPane4.setTitle("Other Tasks");
xTaskPane4.setIcon(UIManager.getIcon("Tree.closedIcon"));
Container xTaskPane4ContentPane = xTaskPane4.getContentPane();
//---- xHyperlink6 ----
xHyperlink6.setText("Duplicate");
xTaskPane4ContentPane.add(xHyperlink6);
//---- xHyperlink7 ----
xHyperlink7.setText("Delete");
xTaskPane4ContentPane.add(xHyperlink7);
}
xTaskPaneContainer1.add(xTaskPane4);
//======== xTaskPane5 ========
{
xTaskPane5.setTitle("Special Tasks");
xTaskPane5.setSpecial(true);
Container xTaskPane5ContentPane = xTaskPane5.getContentPane();
//---- xHyperlink8 ----
xHyperlink8.setText("Go to space");
xTaskPane5ContentPane.add(xHyperlink8);
}
xTaskPaneContainer1.add(xTaskPane5);
//======== xTaskPane6 ========
{
xTaskPane6.setTitle("Collapsed");
xTaskPane6.setCollapsed(true);
Container xTaskPane6ContentPane = xTaskPane6.getContentPane();
//---- xHyperlink9 ----
xHyperlink9.setText("text");
xTaskPane6ContentPane.add(xHyperlink9);
//---- xHyperlink10 ----
xHyperlink10.setText("text");
xTaskPane6ContentPane.add(xHyperlink10);
}
xTaskPaneContainer1.add(xTaskPane6);
}
scrollPane1.setViewportView(xTaskPaneContainer1);
}
panel2.add(scrollPane1, "cell 0 2,width 150,height 350");
}
add(panel2, "cell 3 0 1 8,aligny top,growy 0");
//---- headerLabel ----
headerLabel.setText("JXHeader:");
add(headerLabel, "cell 0 7,aligny top,growy 0");
//---- xHeader1 ----
xHeader1.setTitle("Title");
xHeader1.setDescription("Description\nMore description");
xHeader1.setIcon(new ImageIcon(getClass().getResource("/org/jdesktop/swingx/plaf/windows/resources/tipoftheday.png")));
add(xHeader1, "cell 1 7 2 1,width 200");
// JFormDesigner - End of component initialization //GEN-END:initComponents
xDatePicker1.setDate( new Date() );
xDatePicker2.setDate( new Date() );
xDatePicker3.setDate( new Date() );
xDatePicker4.setDate( new Date() );
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JXMonthView monthView1;
private JXMonthView monthView2;
private JXBusyLabel xBusyLabel1;
private JXBusyLabel xBusyLabel2;
private JCheckBox busyCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

Some files were not shown because too many files have changed in this diff Show More