mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a6242d9ea | ||
|
|
82294b68eb | ||
|
|
c232de1996 | ||
|
|
dc18c8178d | ||
|
|
6662714277 | ||
|
|
c404a0d1a9 | ||
|
|
990da2b412 | ||
|
|
1b974379c8 | ||
|
|
835faf9773 | ||
|
|
80deecb73e | ||
|
|
64328ab9cc | ||
|
|
eafad942e7 | ||
|
|
eb5a3168b9 | ||
|
|
ac8225d8fb | ||
|
|
6f71e4ada0 | ||
|
|
7ed90cddf8 | ||
|
|
283ba83cef | ||
|
|
468c66e842 | ||
|
|
f22862b0a4 | ||
|
|
9e731cb67a | ||
|
|
7f911b61a2 | ||
|
|
cace4a9bfd | ||
|
|
0992e97a1a | ||
|
|
eee101f279 | ||
|
|
4b9f204951 | ||
|
|
019804407b | ||
|
|
65b54ced7a | ||
|
|
a308114b2f | ||
|
|
41da023bdd | ||
|
|
19fcb6a82c | ||
|
|
221a18c119 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,6 +1,18 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 0.38
|
||||
|
||||
- Hide focus indicator when window is inactive.
|
||||
- Custom window decorations: Improved/fixed window border color in dark themes.
|
||||
- Custom window decorations: Hide window border if window is maximized.
|
||||
- Custom window decorations: Center title if menu bar is embedded.
|
||||
- Custom window decorations: Cursor of components (e.g. TextField) was not
|
||||
changed. (issue #125)
|
||||
- CheckBox: Fixed colors in light IntelliJ themes. (issue #126)
|
||||
- InternalFrame: Use default icon in internal frames. (issue #122)
|
||||
|
||||
|
||||
## 0.37
|
||||
|
||||
- Custom window decorations (Windows 10 only; PR #108; issues #47 and #82)
|
||||
|
||||
@@ -98,8 +98,15 @@ Projects using FlatLaf
|
||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||
[AS4](https://mendelson-e-c.com/as4/) and
|
||||
[OFTP2](https://mendelson-e-c.com/oftp2) (commercial)
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.1.6
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform)
|
||||
- [Jes - Die Java-EÜR](https://www.jes-eur.de)
|
||||
- [Mapton](https://mapton.org/) 2.0
|
||||
([source code](https://github.com/trixon/mapton)) based on NetBeans platform
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE)
|
||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis)
|
||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - Multifunctional LED
|
||||
Control Software
|
||||
- and more...
|
||||
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "0.37"
|
||||
val developmentVersion = "0.38-SNAPSHOT"
|
||||
val releaseVersion = "0.38"
|
||||
val developmentVersion = "0.39-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
|
||||
@@ -412,6 +412,10 @@ public class IntelliJTheme
|
||||
|
||||
String newKey = checkboxKeyMapping.get( key );
|
||||
if( newKey != null ) {
|
||||
String checkBoxIconPrefix = "CheckBox.icon.";
|
||||
if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
|
||||
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
|
||||
|
||||
ColorUIResource color = toColor( (String) value );
|
||||
if( color != null ) {
|
||||
defaults.put( newKey, color );
|
||||
@@ -444,12 +448,23 @@ public class IntelliJTheme
|
||||
|
||||
// remove hover and pressed colors
|
||||
if( checkboxModified ) {
|
||||
defaults.remove( "CheckBox.icon.focusWidth" );
|
||||
defaults.remove( "CheckBox.icon.hoverBorderColor" );
|
||||
defaults.remove( "CheckBox.icon.focusedBackground" );
|
||||
defaults.remove( "CheckBox.icon.hoverBackground" );
|
||||
defaults.remove( "CheckBox.icon.pressedBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedFocusedBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedHoverBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedPressedBackground" );
|
||||
|
||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
||||
defaults.remove( "CheckBox.icon[filled].hoverBorderColor" );
|
||||
defaults.remove( "CheckBox.icon[filled].focusedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].hoverBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].pressedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedFocusedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedHoverBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedPressedBackground" );
|
||||
}
|
||||
|
||||
// copy values
|
||||
|
||||
@@ -154,8 +154,11 @@ class UIDefaultsLoader
|
||||
}
|
||||
}
|
||||
|
||||
Function<String, String> propertiesGetter = key -> {
|
||||
return properties.getProperty( key );
|
||||
};
|
||||
Function<String, String> resolver = value -> {
|
||||
return resolveValue( properties, value );
|
||||
return resolveValue( value, propertiesGetter );
|
||||
};
|
||||
|
||||
// get globals, which override all other defaults that end with same suffix
|
||||
@@ -165,9 +168,10 @@ class UIDefaultsLoader
|
||||
if( !key.startsWith( GLOBAL_PREFIX ) )
|
||||
continue;
|
||||
|
||||
String value = resolveValue( properties, (String) e.getValue() );
|
||||
String value = resolveValue( (String) e.getValue(), propertiesGetter );
|
||||
try {
|
||||
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver, addonClassLoaders ) );
|
||||
globals.put( key.substring( GLOBAL_PREFIX.length() ),
|
||||
parseValue( key, value, null, resolver, addonClassLoaders ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
logParseError( Level.SEVERE, key, value, ex );
|
||||
}
|
||||
@@ -190,9 +194,9 @@ class UIDefaultsLoader
|
||||
if( key.startsWith( VARIABLE_PREFIX ) || key.startsWith( GLOBAL_PREFIX ) )
|
||||
continue;
|
||||
|
||||
String value = resolveValue( properties, (String) e.getValue() );
|
||||
String value = resolveValue( (String) e.getValue(), propertiesGetter );
|
||||
try {
|
||||
defaults.put( key, parseValue( key, value, resolver, addonClassLoaders ) );
|
||||
defaults.put( key, parseValue( key, value, null, resolver, addonClassLoaders ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
logParseError( Level.SEVERE, key, value, ex );
|
||||
}
|
||||
@@ -206,7 +210,10 @@ class UIDefaultsLoader
|
||||
FlatLaf.LOG.log( level, "FlatLaf: Failed to parse: '" + key + '=' + value + '\'', ex );
|
||||
}
|
||||
|
||||
private static String resolveValue( Properties properties, String value ) {
|
||||
static String resolveValue( String value, Function<String, String> propertiesGetter ) {
|
||||
value = value.trim();
|
||||
String value0 = value;
|
||||
|
||||
if( value.startsWith( PROPERTY_PREFIX ) )
|
||||
value = value.substring( PROPERTY_PREFIX.length() );
|
||||
else if( !value.startsWith( VARIABLE_PREFIX ) )
|
||||
@@ -218,7 +225,7 @@ class UIDefaultsLoader
|
||||
optional = true;
|
||||
}
|
||||
|
||||
String newValue = properties.getProperty( value );
|
||||
String newValue = propertiesGetter.apply( value );
|
||||
if( newValue == null ) {
|
||||
if( optional )
|
||||
return "null";
|
||||
@@ -226,29 +233,40 @@ class UIDefaultsLoader
|
||||
throw new IllegalArgumentException( "variable or property '" + value + "' not found" );
|
||||
}
|
||||
|
||||
return resolveValue( properties, newValue );
|
||||
if( newValue.equals( value0 ) )
|
||||
throw new IllegalArgumentException( "endless recursion in variable or property '" + value + "'" );
|
||||
|
||||
return resolveValue( newValue, propertiesGetter );
|
||||
}
|
||||
|
||||
private enum ValueType { UNKNOWN, STRING, CHARACTER, INTEGER, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR,
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER }
|
||||
enum ValueType { UNKNOWN, STRING, BOOLEAN, CHARACTER, INTEGER, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR,
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER, NULL, LAZY }
|
||||
|
||||
private static ValueType[] tempResultValueType = new ValueType[1];
|
||||
|
||||
static Object parseValue( String key, String value ) {
|
||||
return parseValue( key, value, v -> v, Collections.emptyList() );
|
||||
return parseValue( key, value, null, v -> v, Collections.emptyList() );
|
||||
}
|
||||
|
||||
private static Object parseValue( String key, String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||
static Object parseValue( String key, String value, ValueType[] resultValueType,
|
||||
Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
||||
{
|
||||
if( resultValueType == null )
|
||||
resultValueType = tempResultValueType;
|
||||
|
||||
value = value.trim();
|
||||
|
||||
// null, false, true
|
||||
switch( value ) {
|
||||
case "null": return null;
|
||||
case "false": return false;
|
||||
case "true": return true;
|
||||
case "null": resultValueType[0] = ValueType.NULL; return null;
|
||||
case "false": resultValueType[0] = ValueType.BOOLEAN; return false;
|
||||
case "true": resultValueType[0] = ValueType.BOOLEAN; return true;
|
||||
}
|
||||
|
||||
// check for function "lazy"
|
||||
// Syntax: lazy(uiKey)
|
||||
if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) {
|
||||
resultValueType[0] = ValueType.LAZY;
|
||||
String uiKey = value.substring( 5, value.length() - 1 ).trim();
|
||||
return (LazyValue) t -> {
|
||||
return lazyUIManagerGet( uiKey );
|
||||
@@ -301,6 +319,8 @@ class UIDefaultsLoader
|
||||
valueType = ValueType.GRAYFILTER;
|
||||
}
|
||||
|
||||
resultValueType[0] = valueType;
|
||||
|
||||
// parse value
|
||||
switch( valueType ) {
|
||||
case STRING: return value;
|
||||
@@ -323,20 +343,27 @@ class UIDefaultsLoader
|
||||
default:
|
||||
// colors
|
||||
Object color = parseColorOrFunction( value, resolver, false );
|
||||
if( color != null )
|
||||
if( color != null ) {
|
||||
resultValueType[0] = ValueType.COLOR;
|
||||
return color;
|
||||
}
|
||||
|
||||
// integer
|
||||
Integer integer = parseInteger( value, false );
|
||||
if( integer != null )
|
||||
if( integer != null ) {
|
||||
resultValueType[0] = ValueType.INTEGER;
|
||||
return integer;
|
||||
}
|
||||
|
||||
// float
|
||||
Float f = parseFloat( value, false );
|
||||
if( f != null )
|
||||
if( f != null ) {
|
||||
resultValueType[0] = ValueType.FLOAT;
|
||||
return f;
|
||||
}
|
||||
|
||||
// string
|
||||
resultValueType[0] = ValueType.STRING;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,13 +202,7 @@ public class FlatButtonUI
|
||||
|
||||
@Override
|
||||
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
||||
return new BasicButtonListener( b ) {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
FlatButtonUI.this.propertyChange( b, e );
|
||||
}
|
||||
};
|
||||
return new FlatButtonListener( b );
|
||||
}
|
||||
|
||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||
@@ -475,4 +469,23 @@ public class FlatButtonUI
|
||||
|
||||
return prefSize;
|
||||
}
|
||||
|
||||
//---- class FlatButtonListener -------------------------------------------
|
||||
|
||||
protected class FlatButtonListener
|
||||
extends BasicButtonListener
|
||||
{
|
||||
private final AbstractButton b;
|
||||
|
||||
protected FlatButtonListener( AbstractButton b ) {
|
||||
super( b );
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
FlatButtonUI.this.propertyChange( b, e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class FlatComboBoxUI
|
||||
protected Color buttonHoverArrowColor;
|
||||
|
||||
private MouseListener hoverListener;
|
||||
private boolean hover;
|
||||
protected boolean hover;
|
||||
|
||||
private WeakReference<Component> lastRendererComponent;
|
||||
|
||||
@@ -332,14 +332,7 @@ public class FlatComboBoxUI
|
||||
|
||||
@Override
|
||||
protected JButton createArrowButton() {
|
||||
return new FlatArrowButton( SwingConstants.SOUTH, arrowType, buttonArrowColor,
|
||||
buttonDisabledArrowColor, buttonHoverArrowColor, null )
|
||||
{
|
||||
@Override
|
||||
protected boolean isHover() {
|
||||
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
||||
}
|
||||
};
|
||||
return new FlatComboBoxButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -507,6 +500,27 @@ public class FlatComboBoxUI
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatComboBoxButton -------------------------------------------
|
||||
|
||||
protected class FlatComboBoxButton
|
||||
extends FlatArrowButton
|
||||
{
|
||||
protected FlatComboBoxButton() {
|
||||
this( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor, buttonHoverArrowColor, null, null );
|
||||
}
|
||||
|
||||
protected FlatComboBoxButton( int direction, String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground, Color pressedBackground )
|
||||
{
|
||||
super( direction, type, foreground, disabledForeground, hoverForeground, hoverBackground, pressedBackground );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isHover() {
|
||||
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatComboPopup -----------------------------------------------
|
||||
|
||||
@SuppressWarnings( { "rawtypes", "unchecked" } )
|
||||
|
||||
@@ -26,13 +26,14 @@ import java.beans.PropertyChangeListener;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
|
||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -103,14 +104,16 @@ public class FlatInternalFrameTitlePane
|
||||
add( buttonPanel, BorderLayout.LINE_END );
|
||||
}
|
||||
|
||||
private void updateFrameIcon() {
|
||||
protected void updateFrameIcon() {
|
||||
Icon frameIcon = frame.getFrameIcon();
|
||||
if( frameIcon == UIManager.getIcon( "InternalFrame.icon" ) )
|
||||
if( frameIcon != null && (frameIcon.getIconWidth() == 0 || frameIcon.getIconHeight() == 0) )
|
||||
frameIcon = null;
|
||||
else if( frameIcon instanceof ImageIcon )
|
||||
frameIcon = new ScaledImageIcon( (ImageIcon) frameIcon );
|
||||
titleLabel.setIcon( frameIcon );
|
||||
}
|
||||
|
||||
private void updateColors() {
|
||||
protected void updateColors() {
|
||||
Color background = FlatUIUtils.nonUIResource( frame.isSelected() ? selectedTitleColor : notSelectedTitleColor );
|
||||
Color foreground = FlatUIUtils.nonUIResource( frame.isSelected() ? selectedTextColor : notSelectedTextColor );
|
||||
|
||||
@@ -123,7 +126,7 @@ public class FlatInternalFrameTitlePane
|
||||
closeButton.setForeground( foreground );
|
||||
}
|
||||
|
||||
private void updateButtonsVisibility() {
|
||||
protected void updateButtonsVisibility() {
|
||||
iconButton.setVisible( frame.isIconifiable() );
|
||||
maxButton.setVisible( frame.isMaximizable() );
|
||||
closeButton.setVisible( frame.isClosable() );
|
||||
@@ -150,7 +153,7 @@ public class FlatInternalFrameTitlePane
|
||||
|
||||
//---- class FlatPropertyChangeHandler ------------------------------------
|
||||
|
||||
private class FlatPropertyChangeHandler
|
||||
protected class FlatPropertyChangeHandler
|
||||
extends PropertyChangeHandler
|
||||
{
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import javax.swing.JComponent;
|
||||
@@ -106,7 +107,11 @@ public class FlatListUI
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
super.focusLost( e );
|
||||
toggleSelectionColors();
|
||||
|
||||
// use invokeLater for the case that the window is deactivated
|
||||
EventQueue.invokeLater( () -> {
|
||||
toggleSelectionColors();
|
||||
} );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,12 +20,13 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.LayoutManager2;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JComponent;
|
||||
@@ -51,12 +52,15 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
* <!-- FlatRootPaneUI -->
|
||||
*
|
||||
* @uiDefault RootPane.border Border
|
||||
* @uiDefault RootPane.activeBorderColor Color
|
||||
* @uiDefault RootPane.inactiveBorderColor Color
|
||||
*
|
||||
* <!-- FlatWindowResizer -->
|
||||
*
|
||||
* @uiDefault RootPane.borderDragThickness int
|
||||
* @uiDefault RootPane.cornerDragWidth int
|
||||
* @uiDefault RootPane.honorMinimumSizeOnResize boolean
|
||||
* @uiDefault RootPane.honorFrameMinimumSizeOnResize boolean
|
||||
* @uiDefault RootPane.honorDialogMinimumSizeOnResize boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -67,10 +71,11 @@ public class FlatRootPaneUI
|
||||
static final boolean canUseJBRCustomDecorations
|
||||
= SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER && SystemInfo.IS_WINDOWS_10_OR_LATER;
|
||||
|
||||
private JRootPane rootPane;
|
||||
private FlatTitlePane titlePane;
|
||||
protected JRootPane rootPane;
|
||||
protected FlatTitlePane titlePane;
|
||||
protected FlatWindowResizer windowResizer;
|
||||
|
||||
private LayoutManager oldLayout;
|
||||
private FlatWindowResizer windowResizer;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatRootPaneUI();
|
||||
@@ -323,24 +328,45 @@ public class FlatRootPaneUI
|
||||
public static class FlatWindowBorder
|
||||
extends BorderUIResource.EmptyBorderUIResource
|
||||
{
|
||||
protected final Color activeBorderColor = UIManager.getColor( "RootPane.activeBorderColor" );
|
||||
protected final Color inactiveBorderColor = UIManager.getColor( "RootPane.inactiveBorderColor" );
|
||||
protected final Color baseBorderColor = UIManager.getColor( "Panel.background" );
|
||||
|
||||
public FlatWindowBorder() {
|
||||
super( 1, 1, 1, 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Object borderColorObj = Toolkit.getDefaultToolkit().getDesktopProperty(
|
||||
"win.frame.activeBorderColor" );
|
||||
Color borderColor = (borderColorObj instanceof Color)
|
||||
? (Color) borderColorObj
|
||||
: UIManager.getColor( "windowBorder" );
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( isWindowMaximized( c ) ) {
|
||||
// hide border if window is maximized
|
||||
insets.top = insets.left = insets.bottom = insets.right = 0;
|
||||
return insets;
|
||||
} else
|
||||
return super.getBorderInsets( c, insets );
|
||||
}
|
||||
|
||||
g.setColor( borderColor );
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( isWindowMaximized( c ) )
|
||||
return;
|
||||
|
||||
Container parent = c.getParent();
|
||||
boolean active = parent instanceof Window ? ((Window)parent).isActive() : false;
|
||||
|
||||
g.setColor( FlatUIUtils.deriveColor( active ? activeBorderColor : inactiveBorderColor, baseBorderColor ) );
|
||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
||||
}
|
||||
|
||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
g.drawRect( x, y, width - 1, height - 1 );
|
||||
}
|
||||
|
||||
protected boolean isWindowMaximized( Component c ) {
|
||||
Container parent = c.getParent();
|
||||
return parent instanceof Frame
|
||||
? (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
|
||||
: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,46 +198,12 @@ public class FlatScrollBarUI
|
||||
|
||||
@Override
|
||||
protected JButton createDecreaseButton( int orientation ) {
|
||||
return createArrowButton( orientation );
|
||||
return new FlatScrollBarButton( orientation );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JButton createIncreaseButton( int orientation ) {
|
||||
return createArrowButton( orientation );
|
||||
}
|
||||
|
||||
private JButton createArrowButton( int orientation ) {
|
||||
FlatArrowButton button = new FlatArrowButton( orientation, arrowType, buttonArrowColor,
|
||||
buttonDisabledArrowColor, null, hoverButtonBackground, pressedButtonBackground )
|
||||
{
|
||||
@Override
|
||||
protected Color deriveBackground( Color background ) {
|
||||
return FlatUIUtils.deriveColor( background, scrollbar.getBackground() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
if( isShowButtons() ) {
|
||||
int w = UIScale.scale( scrollBarWidth );
|
||||
return new Dimension( w, w );
|
||||
} else
|
||||
return new Dimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return isShowButtons() ? super.getMinimumSize() : new Dimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
return isShowButtons() ? super.getMaximumSize() : new Dimension();
|
||||
}
|
||||
};
|
||||
button.setArrowWidth( FlatArrowButton.DEFAULT_ARROW_WIDTH - 2 );
|
||||
button.setFocusable( false );
|
||||
button.setRequestFocusEnabled( false );
|
||||
return button;
|
||||
return new FlatScrollBarButton( orientation );
|
||||
}
|
||||
|
||||
protected boolean isShowButtons() {
|
||||
@@ -377,4 +343,49 @@ public class FlatScrollBarUI
|
||||
scrollbar.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatScrollBarButton ------------------------------------------
|
||||
|
||||
protected class FlatScrollBarButton
|
||||
extends FlatArrowButton
|
||||
{
|
||||
protected FlatScrollBarButton( int direction ) {
|
||||
this( direction, arrowType, buttonArrowColor, buttonDisabledArrowColor,
|
||||
null, hoverButtonBackground, pressedButtonBackground );
|
||||
}
|
||||
|
||||
protected FlatScrollBarButton( int direction, String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground, Color pressedBackground )
|
||||
{
|
||||
super( direction, type, foreground, disabledForeground, hoverForeground, hoverBackground, pressedBackground );
|
||||
|
||||
setArrowWidth( FlatArrowButton.DEFAULT_ARROW_WIDTH - 2 );
|
||||
setFocusable( false );
|
||||
setRequestFocusEnabled( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color deriveBackground( Color background ) {
|
||||
return FlatUIUtils.deriveColor( background, scrollbar.getBackground() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
if( isShowButtons() ) {
|
||||
int w = UIScale.scale( scrollBarWidth );
|
||||
return new Dimension( w, w );
|
||||
} else
|
||||
return new Dimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return isShowButtons() ? super.getMinimumSize() : new Dimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
return isShowButtons() ? super.getMaximumSize() : new Dimension();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,10 +87,10 @@ public class FlatSplitPaneUI
|
||||
|
||||
//---- class FlatSplitPaneDivider -----------------------------------------
|
||||
|
||||
private class FlatSplitPaneDivider
|
||||
protected class FlatSplitPaneDivider
|
||||
extends BasicSplitPaneDivider
|
||||
{
|
||||
public FlatSplitPaneDivider( BasicSplitPaneUI ui ) {
|
||||
protected FlatSplitPaneDivider( BasicSplitPaneUI ui ) {
|
||||
super( ui );
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import javax.swing.JCheckBox;
|
||||
@@ -174,7 +175,11 @@ public class FlatTableUI
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
super.focusLost( e );
|
||||
toggleSelectionColors();
|
||||
|
||||
// use invokeLater for the case that the window is deactivated
|
||||
EventQueue.invokeLater( () -> {
|
||||
toggleSelectionColors();
|
||||
} );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.AbstractBorder;
|
||||
@@ -90,30 +91,31 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatTitlePane
|
||||
extends JComponent
|
||||
{
|
||||
private final Color activeBackground = UIManager.getColor( "TitlePane.background" );
|
||||
private final Color inactiveBackground = UIManager.getColor( "TitlePane.inactiveBackground" );
|
||||
private final Color activeForeground = UIManager.getColor( "TitlePane.foreground" );
|
||||
private final Color inactiveForeground = UIManager.getColor( "TitlePane.inactiveForeground" );
|
||||
private final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
||||
protected final Color activeBackground = UIManager.getColor( "TitlePane.background" );
|
||||
protected final Color inactiveBackground = UIManager.getColor( "TitlePane.inactiveBackground" );
|
||||
protected final Color activeForeground = UIManager.getColor( "TitlePane.foreground" );
|
||||
protected final Color inactiveForeground = UIManager.getColor( "TitlePane.inactiveForeground" );
|
||||
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
||||
|
||||
private final Insets menuBarMargins = UIManager.getInsets( "TitlePane.menuBarMargins" );
|
||||
private final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
||||
private final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
|
||||
protected final Insets menuBarMargins = UIManager.getInsets( "TitlePane.menuBarMargins" );
|
||||
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
||||
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
|
||||
|
||||
private final JRootPane rootPane;
|
||||
protected final JRootPane rootPane;
|
||||
|
||||
private JPanel leftPanel;
|
||||
private JLabel iconLabel;
|
||||
private JComponent menuBarPlaceholder;
|
||||
private JLabel titleLabel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton iconifyButton;
|
||||
private JButton maximizeButton;
|
||||
private JButton restoreButton;
|
||||
private JButton closeButton;
|
||||
protected JPanel leftPanel;
|
||||
protected JLabel iconLabel;
|
||||
protected JComponent menuBarPlaceholder;
|
||||
protected JLabel titleLabel;
|
||||
protected JPanel buttonPanel;
|
||||
protected JButton iconifyButton;
|
||||
protected JButton maximizeButton;
|
||||
protected JButton restoreButton;
|
||||
protected JButton closeButton;
|
||||
|
||||
protected Window window;
|
||||
|
||||
private final Handler handler;
|
||||
private Window window;
|
||||
|
||||
public FlatTitlePane( JRootPane rootPane ) {
|
||||
this.rootPane = rootPane;
|
||||
@@ -146,6 +148,10 @@ public class FlatTitlePane
|
||||
iconLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.iconMargins" ) ) );
|
||||
titleLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.titleMargins" ) ) );
|
||||
|
||||
//TODO
|
||||
// titleLabel.setHorizontalAlignment( JLabel.CENTER );
|
||||
// titleLabel.setHorizontalAlignment( JLabel.RIGHT );
|
||||
|
||||
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
||||
leftPanel.setOpaque( false );
|
||||
leftPanel.add( iconLabel );
|
||||
@@ -217,14 +223,17 @@ public class FlatTitlePane
|
||||
}
|
||||
|
||||
protected void activeChanged( boolean active ) {
|
||||
boolean hasEmbeddedMenuBar = rootPane.getJMenuBar() != null && isMenuBarEmbedded();
|
||||
Color background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground );
|
||||
Color foreground = FlatUIUtils.nonUIResource( active
|
||||
? (rootPane.getJMenuBar() != null && isMenuBarEmbedded() ? embeddedForeground : activeForeground)
|
||||
? (hasEmbeddedMenuBar ? embeddedForeground : activeForeground)
|
||||
: inactiveForeground );
|
||||
|
||||
setBackground( background );
|
||||
titleLabel.setForeground( foreground );
|
||||
|
||||
titleLabel.setHorizontalAlignment( hasEmbeddedMenuBar ? SwingConstants.CENTER : SwingConstants.LEADING );
|
||||
|
||||
// this is necessary because hover/pressed colors are derived from background color
|
||||
iconifyButton.setBackground( background );
|
||||
maximizeButton.setBackground( background );
|
||||
@@ -275,6 +284,8 @@ public class FlatTitlePane
|
||||
else {
|
||||
// no icon set on window --> use default icon
|
||||
Icon defaultIcon = UIManager.getIcon( "InternalFrame.icon" );
|
||||
if( defaultIcon != null && (defaultIcon.getIconWidth() == 0 || defaultIcon.getIconHeight() == 0) )
|
||||
defaultIcon = null;
|
||||
if( defaultIcon != null ) {
|
||||
if( defaultIcon instanceof ImageIcon )
|
||||
defaultIcon = new ScaledImageIcon( (ImageIcon) defaultIcon, iconSize.width, iconSize.height );
|
||||
@@ -385,6 +396,16 @@ public class FlatTitlePane
|
||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||
}
|
||||
|
||||
protected void repaintWindowBorder() {
|
||||
int width = rootPane.getWidth();
|
||||
int height = rootPane.getHeight();
|
||||
Insets insets = rootPane.getInsets();
|
||||
rootPane.repaint( 0, 0, width, insets.top ); // top
|
||||
rootPane.repaint( 0, 0, insets.left, height ); // left
|
||||
rootPane.repaint( 0, height - insets.bottom, width, insets.bottom ); // bottom
|
||||
rootPane.repaint( width - insets.right, 0, insets.right, height ); // right
|
||||
}
|
||||
|
||||
/**
|
||||
* Iconifies the window.
|
||||
*/
|
||||
@@ -613,6 +634,8 @@ public class FlatTitlePane
|
||||
|
||||
if( hasJBRCustomDecoration() )
|
||||
JBRWindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||
|
||||
repaintWindowBorder();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -622,6 +645,8 @@ public class FlatTitlePane
|
||||
|
||||
if( hasJBRCustomDecoration() )
|
||||
JBRWindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||
|
||||
repaintWindowBorder();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.CellRendererPane;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.LookAndFeel;
|
||||
@@ -75,6 +76,11 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Tree.dropCellBackground Color
|
||||
* @uiDefault Tree.dropCellForeground Color
|
||||
*
|
||||
* <!-- DefaultTreeCellEditor -->
|
||||
*
|
||||
* @uiDefault Tree.editorBorder Border
|
||||
* @uiDefault Tree.editorBorderSelectionColor Color
|
||||
*
|
||||
* <!-- FlatTreeUI -->
|
||||
*
|
||||
* @uiDefault Tree.border Border
|
||||
@@ -226,6 +232,11 @@ public class FlatTreeUI
|
||||
boolean isSelected = tree.isRowSelected( row );
|
||||
boolean isDropRow = isDropRow( row );
|
||||
|
||||
// if tree is used as cell renderer in another component (e.g. in Rhino JavaScript debugger),
|
||||
// check whether that component is focused to get correct selection colors
|
||||
if( !hasFocus && isSelected && tree.getParent() instanceof CellRendererPane )
|
||||
hasFocus = FlatUIUtils.isPermanentFocusOwner( tree.getParent().getParent() );
|
||||
|
||||
// wide selection background
|
||||
if( wideSelection && (isSelected || isDropRow) ) {
|
||||
// fill background
|
||||
|
||||
@@ -38,6 +38,7 @@ import java.awt.geom.RoundRectangle2D;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
@@ -139,8 +140,14 @@ public class FlatUIUtils
|
||||
return c instanceof JComponent && Boolean.TRUE.equals( ((JComponent)c).getClientProperty( "JComboBox.isTableCellEditor" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given component is the permanent focus owner and
|
||||
* is in the active window. Used to paint focus indicators.
|
||||
*/
|
||||
public static boolean isPermanentFocusOwner( Component c ) {
|
||||
return (KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() == c);
|
||||
KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
return keyboardFocusManager.getPermanentFocusOwner() == c &&
|
||||
keyboardFocusManager.getActiveWindow() == SwingUtilities.windowForComponent( c );
|
||||
}
|
||||
|
||||
public static boolean isRoundRect( Component c ) {
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static java.awt.Cursor.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
@@ -48,33 +46,43 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatWindowResizer
|
||||
extends JComponent
|
||||
implements PropertyChangeListener, WindowStateListener, ComponentListener
|
||||
{
|
||||
private final static Integer WINDOW_RESIZER_LAYER = JLayeredPane.DRAG_LAYER + 1;
|
||||
protected final static Integer WINDOW_RESIZER_LAYER = JLayeredPane.DRAG_LAYER + 1;
|
||||
|
||||
private final JRootPane rootPane;
|
||||
protected final JRootPane rootPane;
|
||||
|
||||
private final int borderDragThickness = FlatUIUtils.getUIInt( "RootPane.borderDragThickness", 5 );
|
||||
private final int cornerDragWidth = FlatUIUtils.getUIInt( "RootPane.cornerDragWidth", 16 );
|
||||
private final boolean honorMinimumSizeOnResize = UIManager.getBoolean( "RootPane.honorMinimumSizeOnResize" );
|
||||
protected final int borderDragThickness = FlatUIUtils.getUIInt( "RootPane.borderDragThickness", 5 );
|
||||
protected final int cornerDragWidth = FlatUIUtils.getUIInt( "RootPane.cornerDragWidth", 16 );
|
||||
protected final boolean honorFrameMinimumSizeOnResize = UIManager.getBoolean( "RootPane.honorFrameMinimumSizeOnResize" );
|
||||
protected final boolean honorDialogMinimumSizeOnResize = UIManager.getBoolean( "RootPane.honorDialogMinimumSizeOnResize" );
|
||||
|
||||
private Window window;
|
||||
protected final JComponent north;
|
||||
protected final JComponent south;
|
||||
protected final JComponent west;
|
||||
protected final JComponent east;
|
||||
|
||||
protected Window window;
|
||||
|
||||
public FlatWindowResizer( JRootPane rootPane ) {
|
||||
this.rootPane = rootPane;
|
||||
|
||||
setLayout( new BorderLayout() );
|
||||
add( createDragBorderComponent( NW_RESIZE_CURSOR, N_RESIZE_CURSOR, NE_RESIZE_CURSOR ), BorderLayout.NORTH );
|
||||
add( createDragBorderComponent( SW_RESIZE_CURSOR, S_RESIZE_CURSOR, SE_RESIZE_CURSOR ), BorderLayout.SOUTH );
|
||||
add( createDragBorderComponent( NW_RESIZE_CURSOR, W_RESIZE_CURSOR, SW_RESIZE_CURSOR ), BorderLayout.WEST );
|
||||
add( createDragBorderComponent( NE_RESIZE_CURSOR, E_RESIZE_CURSOR, SE_RESIZE_CURSOR ), BorderLayout.EAST );
|
||||
north = createDragBorderComponent( NW_RESIZE_CURSOR, N_RESIZE_CURSOR, NE_RESIZE_CURSOR );
|
||||
south = createDragBorderComponent( SW_RESIZE_CURSOR, S_RESIZE_CURSOR, SE_RESIZE_CURSOR );
|
||||
west = createDragBorderComponent( NW_RESIZE_CURSOR, W_RESIZE_CURSOR, SW_RESIZE_CURSOR );
|
||||
east = createDragBorderComponent( NE_RESIZE_CURSOR, E_RESIZE_CURSOR, SE_RESIZE_CURSOR );
|
||||
|
||||
JLayeredPane layeredPane = rootPane.getLayeredPane();
|
||||
layeredPane.add( north, WINDOW_RESIZER_LAYER );
|
||||
layeredPane.add( south, WINDOW_RESIZER_LAYER );
|
||||
layeredPane.add( west, WINDOW_RESIZER_LAYER );
|
||||
layeredPane.add( east, WINDOW_RESIZER_LAYER );
|
||||
|
||||
rootPane.addComponentListener( this );
|
||||
rootPane.getLayeredPane().add( this, WINDOW_RESIZER_LAYER );
|
||||
rootPane.addPropertyChangeListener( "ancestor", this );
|
||||
|
||||
if( rootPane.isDisplayable() )
|
||||
setBounds( 0, 0, rootPane.getWidth(), rootPane.getHeight() );
|
||||
addNotify();
|
||||
}
|
||||
|
||||
protected DragBorderComponent createDragBorderComponent( int leadingResizeDir, int centerResizeDir, int trailingResizeDir ) {
|
||||
@@ -82,14 +90,40 @@ public class FlatWindowResizer
|
||||
}
|
||||
|
||||
public void uninstall() {
|
||||
removeNotify();
|
||||
|
||||
rootPane.removeComponentListener( this );
|
||||
rootPane.getLayeredPane().remove( this );
|
||||
rootPane.removePropertyChangeListener( "ancestor", this );
|
||||
|
||||
JLayeredPane layeredPane = rootPane.getLayeredPane();
|
||||
layeredPane.remove( north );
|
||||
layeredPane.remove( south );
|
||||
layeredPane.remove( west );
|
||||
layeredPane.remove( east );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
public void doLayout() {
|
||||
if( !north.isVisible() )
|
||||
return;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = rootPane.getWidth();
|
||||
int height = rootPane.getHeight();
|
||||
if( width == 0 || height == 0 )
|
||||
return;
|
||||
|
||||
int thickness = UIScale.scale( borderDragThickness );
|
||||
int y2 = y + thickness;
|
||||
int height2 = height - (thickness * 2);
|
||||
|
||||
north.setBounds( x, y, width, thickness );
|
||||
south.setBounds( x, y + height - thickness, width, thickness );
|
||||
west.setBounds( x, y2, thickness, height2 );
|
||||
east.setBounds( x + width - thickness, y2, thickness, height2 );
|
||||
}
|
||||
|
||||
protected void addNotify() {
|
||||
Container parent = rootPane.getParent();
|
||||
window = (parent instanceof Window) ? (Window) parent : null;
|
||||
if( window instanceof Frame ) {
|
||||
@@ -100,10 +134,7 @@ public class FlatWindowResizer
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
|
||||
protected void removeNotify() {
|
||||
if( window instanceof Frame ) {
|
||||
window.removePropertyChangeListener( "resizable", this );
|
||||
window.removeWindowStateListener( this );
|
||||
@@ -113,25 +144,26 @@ public class FlatWindowResizer
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren( Graphics g ) {
|
||||
super.paintChildren( g );
|
||||
|
||||
// this is necessary because Dialog.setResizable() does not fire events
|
||||
if( window instanceof Dialog )
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
private void updateVisibility() {
|
||||
protected void updateVisibility() {
|
||||
boolean visible = isWindowResizable();
|
||||
if( visible == getComponent( 0 ).isVisible() )
|
||||
if( visible == north.isVisible() )
|
||||
return;
|
||||
|
||||
for( Component c : getComponents() )
|
||||
c.setVisible( visible );
|
||||
north.setVisible( visible );
|
||||
south.setVisible( visible );
|
||||
west.setVisible( visible );
|
||||
|
||||
// The east component is not hidden, instead its bounds are set to 0,0,1,1 and
|
||||
// it is disabled. This is necessary so that DragBorderComponent.paintComponent() is invoked.
|
||||
east.setEnabled( visible );
|
||||
if( visible ) {
|
||||
east.setVisible( true ); // necessary because it is initially invisible
|
||||
doLayout();
|
||||
} else
|
||||
east.setBounds( 0, 0, 1, 1 );
|
||||
}
|
||||
|
||||
private boolean isWindowResizable() {
|
||||
protected boolean isWindowResizable() {
|
||||
if( window instanceof Frame )
|
||||
return ((Frame)window).isResizable() && (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) == 0;
|
||||
if( window instanceof Dialog )
|
||||
@@ -141,7 +173,18 @@ public class FlatWindowResizer
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
updateVisibility();
|
||||
switch( e.getPropertyName() ) {
|
||||
case "ancestor":
|
||||
if( e.getNewValue() != null )
|
||||
addNotify();
|
||||
else
|
||||
removeNotify();
|
||||
break;
|
||||
|
||||
case "resizable":
|
||||
updateVisibility();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,8 +194,7 @@ public class FlatWindowResizer
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
setBounds( 0, 0, rootPane.getWidth(), rootPane.getHeight() );
|
||||
validate();
|
||||
doLayout();
|
||||
}
|
||||
|
||||
@Override public void componentMoved( ComponentEvent e ) {}
|
||||
@@ -200,13 +242,19 @@ public class FlatWindowResizer
|
||||
return new Dimension( thickness, thickness );
|
||||
}
|
||||
|
||||
/*debug
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
super.paintChildren( g );
|
||||
|
||||
// this is necessary because Dialog.setResizable() does not fire events
|
||||
if( window instanceof Dialog )
|
||||
updateVisibility();
|
||||
|
||||
/*debug
|
||||
g.setColor( java.awt.Color.red );
|
||||
g.drawRect( 0, 0, getWidth() - 1, getHeight() - 1 );
|
||||
}
|
||||
debug*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e ) {
|
||||
@@ -293,6 +341,9 @@ debug*/
|
||||
newBounds.height += deltaHeight;
|
||||
|
||||
// apply minimum window size
|
||||
boolean honorMinimumSizeOnResize =
|
||||
(honorFrameMinimumSizeOnResize && window instanceof Frame) ||
|
||||
(honorDialogMinimumSizeOnResize && window instanceof Dialog);
|
||||
Dimension minimumSize = honorMinimumSizeOnResize ? window.getMinimumSize() : null;
|
||||
if( minimumSize == null )
|
||||
minimumSize = UIScale.scale( new Dimension( 150, 50 ) );
|
||||
@@ -312,8 +363,7 @@ debug*/
|
||||
window.setBounds( newBounds );
|
||||
|
||||
// immediately layout drag border components
|
||||
FlatWindowResizer.this.setBounds( 0, 0, newBounds.width, newBounds.height );
|
||||
FlatWindowResizer.this.validate();
|
||||
FlatWindowResizer.this.doLayout();
|
||||
|
||||
if( Toolkit.getDefaultToolkit().isDynamicLayoutActive() ) {
|
||||
window.validate();
|
||||
|
||||
@@ -239,6 +239,12 @@ ProgressBar.selectionBackground=@foreground
|
||||
RadioButton.icon[filled].centerDiameter=5
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor=darken(@background,7%,derived)
|
||||
RootPane.inactiveBorderColor=darken(@background,5%,derived)
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.track=lighten(@background,1%,derived noAutoInverse)
|
||||
|
||||
@@ -36,7 +36,6 @@ Button.default.borderWidth=1
|
||||
#---- CheckBox ----
|
||||
|
||||
CheckBox.icon.style=filled
|
||||
CheckBox.icon[filled].focusWidth=2
|
||||
|
||||
|
||||
#---- Component ----
|
||||
|
||||
@@ -292,6 +292,7 @@ List.selectionInactiveForeground=@selectionInactiveForeground
|
||||
List.dropCellBackground=@dropCellBackground
|
||||
List.dropCellForeground=@dropCellForeground
|
||||
List.dropLineColor=@dropLineColor
|
||||
List.showCellFocusIndicator=false
|
||||
|
||||
|
||||
#---- Menu ----
|
||||
@@ -430,7 +431,8 @@ RadioButtonMenuItem.background=@menuBackground
|
||||
RootPane.border=com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder
|
||||
RootPane.borderDragThickness=5
|
||||
RootPane.cornerDragWidth=16
|
||||
RootPane.honorMinimumSizeOnResize=true
|
||||
RootPane.honorFrameMinimumSizeOnResize=false
|
||||
RootPane.honorDialogMinimumSizeOnResize=true
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
@@ -659,6 +661,7 @@ ToolTipManager.enableToolTipMode=activeApplication
|
||||
#---- Tree ----
|
||||
|
||||
Tree.border=1,1,1,1
|
||||
Tree.editorBorder=1,1,1,1,@cellFocusColor
|
||||
Tree.selectionInactiveBackground=@selectionInactiveBackground
|
||||
Tree.selectionInactiveForeground=@selectionInactiveForeground
|
||||
Tree.textBackground=$Tree.background
|
||||
@@ -671,6 +674,7 @@ Tree.rendererMargins=1,2,1,2
|
||||
Tree.wideSelection=true
|
||||
Tree.repaintWholeRow=true
|
||||
Tree.paintLines=false
|
||||
Tree.showCellFocusIndicator=false
|
||||
Tree.leftChildIndent=7
|
||||
Tree.rightChildIndent=11
|
||||
Tree.rowHeight=0
|
||||
|
||||
@@ -251,6 +251,12 @@ ProgressBar.selectionBackground=@foreground
|
||||
RadioButton.icon[filled].centerDiameter=5
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor=#707070
|
||||
RootPane.inactiveBorderColor=lighten($RootPane.activeBorderColor,20%,derived)
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.track=lighten(@background,1%,derived noAutoInverse)
|
||||
|
||||
@@ -7,6 +7,7 @@ package com.formdev.flatlaf.testing;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyVetoException;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.extras.TriStateCheckBox;
|
||||
import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -50,8 +51,10 @@ public class FlatInternalFrameTest
|
||||
maximizableCheckBox.isSelected(),
|
||||
iconifiableCheckBox.isSelected() );
|
||||
|
||||
if( iconCheckBox.isSelected() )
|
||||
if( iconCheckBox.getState() == TriStateCheckBox.State.SELECTED )
|
||||
internalFrame.setFrameIcon( new FlatFileViewFloppyDriveIcon() );
|
||||
else if( iconCheckBox.getState() == TriStateCheckBox.State.UNSELECTED )
|
||||
internalFrame.setFrameIcon( null );
|
||||
|
||||
if( menuBarCheckBox.isSelected() ) {
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
@@ -100,7 +103,7 @@ public class FlatInternalFrameTest
|
||||
closableCheckBox = new JCheckBox();
|
||||
iconifiableCheckBox = new JCheckBox();
|
||||
maximizableCheckBox = new JCheckBox();
|
||||
iconCheckBox = new JCheckBox();
|
||||
iconCheckBox = new TriStateCheckBox();
|
||||
menuBarCheckBox = new JCheckBox();
|
||||
titleLabel = new JLabel();
|
||||
titleField = new JTextField();
|
||||
@@ -192,7 +195,7 @@ public class FlatInternalFrameTest
|
||||
private JCheckBox closableCheckBox;
|
||||
private JCheckBox iconifiableCheckBox;
|
||||
private JCheckBox maximizableCheckBox;
|
||||
private JCheckBox iconCheckBox;
|
||||
private TriStateCheckBox iconCheckBox;
|
||||
private JCheckBox menuBarCheckBox;
|
||||
private JLabel titleLabel;
|
||||
private JTextField titleField;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "13.0.1" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "14" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -50,7 +50,7 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1,alignx left,growx 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
|
||||
name: "iconCheckBox"
|
||||
"text": "Frame icon"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
|
||||
@@ -120,6 +120,9 @@ public class UIDefaultsDump
|
||||
// }
|
||||
|
||||
// dumpIntelliJThemes( dir );
|
||||
|
||||
// dump UI keys
|
||||
UIDefaultsKeysDump.main( new String[0] );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unused" )
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.testing.uidefaults;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.*;
|
||||
|
||||
/**
|
||||
* Collects all FlatLaf UI defaults keys and dumps them to a file.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class UIDefaultsKeysDump
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
Locale.setDefault( Locale.ENGLISH );
|
||||
System.setProperty( "sun.java2d.uiScale", "1x" );
|
||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||
|
||||
File keysFile = new File( "../flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt" );
|
||||
|
||||
HashSet<String> keys = new HashSet<>();
|
||||
|
||||
collectKeys( FlatLightLaf.class.getName(), keys );
|
||||
collectKeys( FlatDarkLaf.class.getName(), keys );
|
||||
collectKeys( FlatIntelliJLaf.class.getName(), keys );
|
||||
collectKeys( FlatDarculaLaf.class.getName(), keys );
|
||||
|
||||
try( Writer fileWriter = new BufferedWriter( new FileWriter( keysFile ) ) ) {
|
||||
String[] sortedKeys = keys.toArray( new String[keys.size()] );
|
||||
Arrays.sort( sortedKeys );
|
||||
for( String key : sortedKeys ) {
|
||||
fileWriter.write( key );
|
||||
fileWriter.write( "\n" );
|
||||
}
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectKeys( String lookAndFeelClassName, HashSet<String> keys ) {
|
||||
try {
|
||||
UIManager.setLookAndFeel( lookAndFeelClassName );
|
||||
} catch( Exception ex ) {
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
UIDefaults defaults = UIManager.getLookAndFeel().getDefaults();
|
||||
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String )
|
||||
keys.add( (String) key );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,3 +348,5 @@ ToolTip.background=#eeeeff
|
||||
Tree.background=#fff0ff
|
||||
Tree.paintLines=true
|
||||
Tree.hash=#ff0000
|
||||
Tree.editorBorder=1,1,1,1,#f00
|
||||
Tree.editorBorderSelectionColor=#00f
|
||||
|
||||
@@ -475,6 +475,7 @@ List.selectionBackground #4b6eaf javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionInactiveBackground #0d293e javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionInactiveForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
List.showCellFocusIndicator false
|
||||
List.timeFactor 1000
|
||||
ListUI com.formdev.flatlaf.ui.FlatListUI
|
||||
|
||||
@@ -752,6 +753,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor #4d5154 com.formdev.flatlaf.util.DerivedColor [UI] darken(7% autoInverse)
|
||||
RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI]
|
||||
RootPane.borderDragThickness 5
|
||||
RootPane.cornerDragWidth 16
|
||||
@@ -764,7 +766,9 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object;
|
||||
[5] press
|
||||
[6] ctrl released ENTER
|
||||
[7] release
|
||||
RootPane.honorMinimumSizeOnResize true
|
||||
RootPane.honorDialogMinimumSizeOnResize true
|
||||
RootPane.honorFrameMinimumSizeOnResize false
|
||||
RootPane.inactiveBorderColor #484c4e com.formdev.flatlaf.util.DerivedColor [UI] darken(5% autoInverse)
|
||||
RootPaneUI com.formdev.flatlaf.ui.FlatRootPaneUI
|
||||
|
||||
|
||||
@@ -1187,7 +1191,7 @@ Tree.drawsFocusBorderAroundIcon false
|
||||
Tree.dropCellBackground [lazy] #3c588b javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.dropCellForeground [lazy] #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.dropLineColor [lazy] #6d8ac0 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.editorBorder [lazy] line: #000000 java.awt.Color 1 false 1,1,1,1 true javax.swing.plaf.BorderUIResource$LineBorderUIResource [UI]
|
||||
Tree.editorBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatLineBorder [UI] lineColor=#000000 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
Tree.expandedIcon [lazy] 11,11 com.formdev.flatlaf.icons.FlatTreeExpandedIcon [UI]
|
||||
Tree.font [active] $defaultFont [UI]
|
||||
Tree.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1213,6 +1217,7 @@ Tree.selectionBorderColor #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionInactiveBackground #0d293e javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionInactiveForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.showCellFocusIndicator false
|
||||
Tree.textBackground #45494a javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.textForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.timeFactor 1000
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
|
||||
+ CheckBox.icon.style filled
|
||||
|
||||
+ CheckBox.icon[filled].focusWidth 2
|
||||
|
||||
- CheckBox.icon[filled].selectedFocusedCheckmarkColor #e3f1fa javax.swing.plaf.ColorUIResource [UI]
|
||||
|
||||
- ComboBox.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRoundBorder [UI]
|
||||
|
||||
@@ -480,6 +480,7 @@ List.selectionBackground #2675bf javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionInactiveBackground #d4d4d4 javax.swing.plaf.ColorUIResource [UI]
|
||||
List.selectionInactiveForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
List.showCellFocusIndicator false
|
||||
List.timeFactor 1000
|
||||
ListUI com.formdev.flatlaf.ui.FlatListUI
|
||||
|
||||
@@ -757,6 +758,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor #707070 javax.swing.plaf.ColorUIResource [UI]
|
||||
RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI]
|
||||
RootPane.borderDragThickness 5
|
||||
RootPane.cornerDragWidth 16
|
||||
@@ -769,7 +771,9 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object;
|
||||
[5] press
|
||||
[6] ctrl released ENTER
|
||||
[7] release
|
||||
RootPane.honorMinimumSizeOnResize true
|
||||
RootPane.honorDialogMinimumSizeOnResize true
|
||||
RootPane.honorFrameMinimumSizeOnResize false
|
||||
RootPane.inactiveBorderColor #a3a3a3 com.formdev.flatlaf.util.DerivedColor [UI] lighten(20% autoInverse)
|
||||
RootPaneUI com.formdev.flatlaf.ui.FlatRootPaneUI
|
||||
|
||||
|
||||
@@ -1192,7 +1196,7 @@ Tree.drawsFocusBorderAroundIcon false
|
||||
Tree.dropCellBackground [lazy] #3f8fd9 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.dropCellForeground [lazy] #ffffff javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.dropLineColor [lazy] #6aa7e1 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.editorBorder [lazy] line: #000000 java.awt.Color 1 false 1,1,1,1 true javax.swing.plaf.BorderUIResource$LineBorderUIResource [UI]
|
||||
Tree.editorBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatLineBorder [UI] lineColor=#000000 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
Tree.expandedIcon [lazy] 11,11 com.formdev.flatlaf.icons.FlatTreeExpandedIcon [UI]
|
||||
Tree.font [active] $defaultFont [UI]
|
||||
Tree.foreground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1218,6 +1222,7 @@ Tree.selectionBorderColor #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionInactiveBackground #d4d4d4 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.selectionInactiveForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.showCellFocusIndicator false
|
||||
Tree.textBackground #ffffff javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.textForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||
Tree.timeFactor 1000
|
||||
|
||||
@@ -20,6 +20,8 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( project( ":flatlaf-extras" ) )
|
||||
|
||||
implementation( "com.fifesoft:rsyntaxtextarea:3.1.0" )
|
||||
implementation( "com.fifesoft:rsyntaxtextarea:3.1.1" )
|
||||
implementation( "com.fifesoft:autocomplete:3.1.0" )
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
import com.formdev.flatlaf.UIDefaultsLoader.ValueType;
|
||||
|
||||
/**
|
||||
* Enable accessing package private methods of {@link UIDefaultsLoader}.
|
||||
*
|
||||
@@ -23,6 +27,40 @@ package com.formdev.flatlaf;
|
||||
*/
|
||||
public class UIDefaultsLoaderAccessor
|
||||
{
|
||||
public static Object UNKNOWN = ValueType.UNKNOWN;
|
||||
public static Object STRING = ValueType.STRING;
|
||||
public static Object BOOLEAN = ValueType.BOOLEAN;
|
||||
public static Object CHARACTER = ValueType.CHARACTER;
|
||||
public static Object INTEGER = ValueType.INTEGER;
|
||||
public static Object FLOAT = ValueType.FLOAT;
|
||||
public static Object BORDER = ValueType.BORDER;
|
||||
public static Object ICON = ValueType.ICON;
|
||||
public static Object INSETS = ValueType.INSETS;
|
||||
public static Object DIMENSION = ValueType.DIMENSION;
|
||||
public static Object COLOR = ValueType.COLOR;
|
||||
public static Object SCALEDINTEGER = ValueType.SCALEDINTEGER;
|
||||
public static Object SCALEDFLOAT = ValueType.SCALEDFLOAT;
|
||||
public static Object SCALEDINSETS = ValueType.SCALEDINSETS;
|
||||
public static Object SCALEDDIMENSION = ValueType.SCALEDDIMENSION;
|
||||
public static Object INSTANCE = ValueType.INSTANCE;
|
||||
public static Object CLASS = ValueType.CLASS;
|
||||
public static Object GRAYFILTER = ValueType.GRAYFILTER;
|
||||
public static Object NULL = ValueType.NULL;
|
||||
public static Object LAZY = ValueType.LAZY;
|
||||
|
||||
public static String resolveValue( String value, Function<String, String> propertiesGetter ) {
|
||||
return UIDefaultsLoader.resolveValue( value, propertiesGetter );
|
||||
}
|
||||
|
||||
public static Object parseValue( String key, String value, Object[] resultValueType,
|
||||
Function<String, String> resolver )
|
||||
{
|
||||
ValueType[] resultValueType2 = new ValueType[1];
|
||||
Object result = UIDefaultsLoader.parseValue( key, value, resultValueType2, resolver, Collections.emptyList() );
|
||||
resultValueType[0] = resultValueType2[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int parseColorRGBA( String value ) {
|
||||
return UIDefaultsLoader.parseColorRGBA( value );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.themeeditor;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import org.fife.ui.autocomplete.BasicCompletion;
|
||||
import org.fife.ui.autocomplete.Completion;
|
||||
import org.fife.ui.autocomplete.CompletionProvider;
|
||||
import org.fife.ui.autocomplete.CompletionProviderBase;
|
||||
import org.fife.ui.autocomplete.DefaultCompletionProvider;
|
||||
import org.fife.ui.autocomplete.FunctionCompletion;
|
||||
import org.fife.ui.autocomplete.ParameterizedCompletion;
|
||||
import org.fife.ui.autocomplete.ParameterizedCompletion.Parameter;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class FlatCompletionProvider
|
||||
extends CompletionProviderBase
|
||||
{
|
||||
private KeyCompletionProvider keyProvider;
|
||||
private ReferenceCompletionProvider referenceProvider;
|
||||
private ValueCompletionProvider valueProvider;
|
||||
|
||||
FlatCompletionProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlreadyEnteredText( JTextComponent comp ) {
|
||||
CompletionProvider provider = getProviderFor( comp );
|
||||
return (provider != null) ? provider.getAlreadyEnteredText( comp ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Completion> getCompletionsAt( JTextComponent comp, Point p ) {
|
||||
CompletionProvider provider = getProviderFor( comp );
|
||||
return (provider != null) ? provider.getCompletionsAt( comp, p ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterizedCompletion> getParameterizedCompletions( JTextComponent comp ) {
|
||||
CompletionProvider provider = getProviderFor( comp );
|
||||
return (provider != null) ? provider.getParameterizedCompletions( comp ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Completion> getCompletionsImpl( JTextComponent comp ) {
|
||||
CompletionProvider provider = getProviderFor( comp );
|
||||
return (provider != null) ? provider.getCompletions( comp ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoActivateOkay( JTextComponent comp ) {
|
||||
CompletionProvider provider = getProviderFor( comp );
|
||||
return (provider != null) ? provider.isAutoActivateOkay( comp ) : null;
|
||||
}
|
||||
|
||||
private CompletionProvider getProviderFor( JTextComponent comp ) {
|
||||
RSyntaxTextArea rsta = (RSyntaxTextArea) comp;
|
||||
try {
|
||||
int caretPosition = rsta.getCaretPosition();
|
||||
int currentLine = rsta.getLineOfOffset( caretPosition );
|
||||
int lineStart = rsta.getLineStartOffset( currentLine );
|
||||
int lineEnd = rsta.getLineEndOffset( currentLine );
|
||||
|
||||
if( caretPosition <= lineStart ) {
|
||||
// caret is at the start of the line
|
||||
String line = rsta.getText( lineStart, lineEnd - lineStart );
|
||||
if( line.trim().startsWith( "#" ) )
|
||||
return null;
|
||||
}
|
||||
|
||||
String lineBeforeCaret = rsta.getText( lineStart, caretPosition - lineStart );
|
||||
if( lineBeforeCaret.trim().startsWith( "#" ) )
|
||||
return null;
|
||||
|
||||
// key
|
||||
if( lineBeforeCaret.indexOf( '=' ) < 0 )
|
||||
return getKeyProvider();
|
||||
|
||||
// value
|
||||
for( int i = lineBeforeCaret.length() - 1; i >= 0; i-- ) {
|
||||
switch( lineBeforeCaret.charAt( i ) ) {
|
||||
case '=':
|
||||
case '(':
|
||||
return getValueProvider();
|
||||
|
||||
case '$':
|
||||
case '@':
|
||||
return getReferenceProvider();
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '#': // colors
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
} catch( BadLocationException ex ) {
|
||||
// ignore
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private CompletionProvider getKeyProvider() {
|
||||
if( keyProvider == null )
|
||||
keyProvider = KeyCompletionProvider.getInstance();
|
||||
return keyProvider;
|
||||
}
|
||||
|
||||
private CompletionProvider getReferenceProvider() {
|
||||
if( referenceProvider == null )
|
||||
referenceProvider = new ReferenceCompletionProvider();
|
||||
return referenceProvider;
|
||||
}
|
||||
|
||||
private CompletionProvider getValueProvider() {
|
||||
if( valueProvider == null )
|
||||
valueProvider = new ValueCompletionProvider();
|
||||
return valueProvider;
|
||||
}
|
||||
|
||||
//---- class KeyCompletionProvider ----------------------------------------
|
||||
|
||||
/**
|
||||
* A completion provider for keys, which always uses all known/predefined keys.
|
||||
*/
|
||||
private static final class KeyCompletionProvider
|
||||
extends BaseCompletionProvider
|
||||
{
|
||||
private static KeyCompletionProvider instance;
|
||||
|
||||
static KeyCompletionProvider getInstance() {
|
||||
if( instance == null )
|
||||
instance = new KeyCompletionProvider();
|
||||
return instance;
|
||||
}
|
||||
|
||||
KeyCompletionProvider() {
|
||||
setAutoActivationRules( true, "." );
|
||||
|
||||
// load all keys
|
||||
HashSet<String> keys = new HashSet<>();
|
||||
try {
|
||||
try( InputStream in = getClass().getResourceAsStream( "/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt" ) ) {
|
||||
if( in != null ) {
|
||||
try( BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ) ) ) {
|
||||
String key;
|
||||
while( (key = reader.readLine()) != null ) {
|
||||
keys.add( key );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace(); // TODO
|
||||
}
|
||||
|
||||
// collect key parts
|
||||
HashSet<String> keyParts = new HashSet<>();
|
||||
for( String key : keys ) {
|
||||
int delimIndex = key.length() + 1;
|
||||
while( (delimIndex = key.lastIndexOf( '.', delimIndex - 1 )) >= 0 ) {
|
||||
String part = key.substring( 0, delimIndex );
|
||||
if( !keys.contains( part ) )
|
||||
keyParts.add( part );
|
||||
}
|
||||
}
|
||||
|
||||
// add key parts
|
||||
addWordCompletions( keyParts.toArray( new String[keyParts.size()] ) );
|
||||
|
||||
// add all keys
|
||||
addWordCompletions( keys.toArray( new String[keys.size()] ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidChar( char ch ) {
|
||||
return super.isValidChar( ch ) || ch == '.';
|
||||
}
|
||||
}
|
||||
|
||||
//---- class BaseCompletionProvider ---------------------------------------
|
||||
|
||||
//TODO remove if https://github.com/bobbylight/AutoComplete/issues/77 is fixed
|
||||
private static class BaseCompletionProvider
|
||||
extends DefaultCompletionProvider
|
||||
{
|
||||
private boolean autoActivateAfterLetters;
|
||||
private String autoActivateChars;
|
||||
|
||||
@Override
|
||||
public boolean isAutoActivateOkay( JTextComponent comp ) {
|
||||
int caretPosition = comp.getCaretPosition();
|
||||
if( caretPosition <= 0 )
|
||||
return false;
|
||||
|
||||
try {
|
||||
char ch = comp.getText( caretPosition - 1, 1 ).charAt( 0 );
|
||||
return (autoActivateAfterLetters && Character.isLetter( ch )) ||
|
||||
(autoActivateChars != null && autoActivateChars.indexOf( ch ) >= 0);
|
||||
} catch( BadLocationException | IndexOutOfBoundsException ex ) {
|
||||
// ignore
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoActivationRules( boolean letters, String others ) {
|
||||
autoActivateAfterLetters = letters;
|
||||
autoActivateChars = others;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class ReferenceCompletionProvider ----------------------------------
|
||||
|
||||
/**
|
||||
* A completion provider for references within values. Only keys defined
|
||||
* in current properties file and in base properties files are used.
|
||||
*/
|
||||
private static class ReferenceCompletionProvider
|
||||
extends BaseCompletionProvider
|
||||
{
|
||||
private Set<String> lastKeys;
|
||||
|
||||
ReferenceCompletionProvider() {
|
||||
setAutoActivationRules( true, "$@." );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidChar( char ch ) {
|
||||
return super.isValidChar( ch ) || ch == '.' || ch == '$' || ch == '@';
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Completion> getCompletionsImpl( JTextComponent comp ) {
|
||||
updateCompletions( comp );
|
||||
return super.getCompletionsImpl( comp );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Completion> getCompletionsAt( JTextComponent comp, Point pt ) {
|
||||
updateCompletions( comp );
|
||||
return super.getCompletionsAt( comp, pt );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterizedCompletion> getParameterizedCompletions( JTextComponent comp ) {
|
||||
updateCompletions( comp );
|
||||
return super.getParameterizedCompletions( comp );
|
||||
}
|
||||
|
||||
private void updateCompletions( JTextComponent comp ) {
|
||||
FlatSyntaxTextArea fsta = (FlatSyntaxTextArea) comp;
|
||||
Set<String> keys = fsta.propertiesSupport.getAllKeys();
|
||||
if( keys == lastKeys )
|
||||
return;
|
||||
|
||||
completions.clear();
|
||||
for( String key : keys ) {
|
||||
if( key.startsWith( "*." ) )
|
||||
continue;
|
||||
|
||||
if( !key.startsWith( "@" ) )
|
||||
key = "$".concat( key );
|
||||
|
||||
completions.add( new BasicCompletion( this, key ) );
|
||||
}
|
||||
Collections.sort(completions);
|
||||
}
|
||||
}
|
||||
|
||||
//---- class ValueCompletionProvider --------------------------------------
|
||||
|
||||
/**
|
||||
* A completion provider for values.
|
||||
*/
|
||||
private static class ValueCompletionProvider
|
||||
extends BaseCompletionProvider
|
||||
{
|
||||
ValueCompletionProvider() {
|
||||
setAutoActivationRules( true, null );
|
||||
setParameterizedCompletionParams( '(', ",", ')' );
|
||||
|
||||
addFunction( "rgb",
|
||||
"red", "0-255 or 0-100%",
|
||||
"green", "0-255 or 0-100%",
|
||||
"blue", "0-255 or 0-100%" );
|
||||
addFunction( "rgba",
|
||||
"red", "0-255 or 0-100%",
|
||||
"green", "0-255 or 0-100%",
|
||||
"blue", "0-255 or 0-100%",
|
||||
"alpha", "0-255 or 0-100%" );
|
||||
|
||||
addFunction( "hsl",
|
||||
"hue", "0-360 representing degrees",
|
||||
"saturation", "0-100%",
|
||||
"lightness", "0-100%" );
|
||||
addFunction( "hsla",
|
||||
"hue", "0-360 representing degrees",
|
||||
"saturation", "0-100%",
|
||||
"lightness", "0-100%",
|
||||
"alpha", "0-100%" );
|
||||
|
||||
String[] hslIncreaseDecreaseParams = {
|
||||
"color", "a color (e.g. #f00), a reference (e.g. $Other.key) or a color function",
|
||||
"amount", "0-100%",
|
||||
"options", "(optional) [relative] [autoInverse] [noAutoInverse] [lazy] [derived]"
|
||||
};
|
||||
addFunction( "lighten", hslIncreaseDecreaseParams );
|
||||
addFunction( "darken", hslIncreaseDecreaseParams );
|
||||
addFunction( "saturate", hslIncreaseDecreaseParams );
|
||||
addFunction( "desaturate", hslIncreaseDecreaseParams );
|
||||
}
|
||||
|
||||
private void addFunction( String name, String... paramNamesAndDescs ) {
|
||||
List<Parameter> params = new ArrayList<>();
|
||||
for( int i = 0; i < paramNamesAndDescs.length; i += 2 ) {
|
||||
boolean endParam = i + 2 >= paramNamesAndDescs.length;
|
||||
Parameter param = new Parameter( null, paramNamesAndDescs[i], endParam );
|
||||
param.setDescription( paramNamesAndDescs[i + 1] );
|
||||
params.add( param );
|
||||
}
|
||||
|
||||
FunctionCompletion f = new FunctionCompletion( this, name, null ) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDefinitionString().replace( "(", " (" ).replace( ",", ", " );
|
||||
}
|
||||
};
|
||||
|
||||
f.setParams( params );
|
||||
addCompletion( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class FlatOccurrenceMarker
|
||||
// make a copy of the token because it is overwritten in getTokenListForLine()
|
||||
Token t2 = new TokenImpl( t );
|
||||
|
||||
// check whether token occurres more than once
|
||||
// check whether token occurs more than once
|
||||
boolean mark = false;
|
||||
for( int i = 0; i < lineCount && !mark; i++ ) {
|
||||
Token temp = doc.getTokenListForLine( i );
|
||||
|
||||
@@ -34,6 +34,7 @@ class FlatSyntaxTextArea
|
||||
{
|
||||
private boolean useColorOfColorTokens;
|
||||
|
||||
final FlatThemePropertiesSupport propertiesSupport = new FlatThemePropertiesSupport( this );
|
||||
private final Map<String, Color> parsedColorsMap = new HashMap<>();
|
||||
|
||||
FlatSyntaxTextArea() {
|
||||
|
||||
@@ -103,11 +103,18 @@ class FlatThemeEditorOverlay
|
||||
g.setColor( color );
|
||||
g.fillRect( px, r.y, pw, r.height );
|
||||
|
||||
// if color is semi-transparent paint also none-transparent color
|
||||
int alpha = color.getAlpha();
|
||||
if( alpha != 255 && pw > r.height * 2 ) {
|
||||
g.setColor( new Color( color.getRGB() ) );
|
||||
g.fillRect( px + pw - r.height, r.y, r.height, r.height );
|
||||
}
|
||||
|
||||
// paint text
|
||||
int textX = px - maxTextWidth;
|
||||
if( textX > r.x + gap) {
|
||||
float[] hsl = HSLColor.fromRGB( color );
|
||||
String hslStr = String.format( "HSL %d %d %d",
|
||||
String hslStr = String.format( "HSL %3d %2d %2d",
|
||||
Math.round( hsl[0] ), Math.round( hsl[1] ), Math.round( hsl[2] ) );
|
||||
g.setColor( textArea.getForeground() );
|
||||
FlatUIUtils.drawString( textArea, g, hslStr, textX,
|
||||
@@ -120,6 +127,10 @@ class FlatThemeEditorOverlay
|
||||
}
|
||||
|
||||
private Color getColorInLine( FlatSyntaxTextArea textArea, int line ) {
|
||||
Object value = textArea.propertiesSupport.getParsedValueAtLine( line );
|
||||
if( value instanceof Color )
|
||||
return (Color) value;
|
||||
|
||||
Token token = textArea.getTokenListForLine( line );
|
||||
for( Token t = token; t != null && t.isPaintable(); t = t.getNextToken() ) {
|
||||
if( t.getType() == FlatThemeTokenMaker.TOKEN_COLOR ) {
|
||||
|
||||
@@ -19,10 +19,15 @@ package com.formdev.flatlaf.themeeditor;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import javax.swing.JLayer;
|
||||
import javax.swing.JPanel;
|
||||
import org.fife.ui.autocomplete.AutoCompletion;
|
||||
import org.fife.ui.autocomplete.CompletionProvider;
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
||||
import org.fife.ui.rsyntaxtextarea.FileLocation;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
|
||||
@@ -59,8 +64,8 @@ class FlatThemeEditorPane
|
||||
// textArea.setUseColorOfColorTokens( true );
|
||||
|
||||
// theme
|
||||
try {
|
||||
Theme theme = Theme.load( getClass().getResourceAsStream( "light.xml" ) );
|
||||
try( InputStream in = getClass().getResourceAsStream( "light.xml" ) ) {
|
||||
Theme theme = Theme.load( in );
|
||||
theme.apply( textArea );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
@@ -72,6 +77,16 @@ class FlatThemeEditorPane
|
||||
scheme.getStyle( FlatThemeTokenMaker.TOKEN_COLOR ).background = new Color( 0x0a000000, true );
|
||||
scheme.getStyle( FlatThemeTokenMaker.TOKEN_VARIABLE ).background = new Color( 0x1800cc00, true );
|
||||
|
||||
// autocomplete
|
||||
CompletionProvider provider = new FlatCompletionProvider();
|
||||
AutoCompletion ac = new AutoCompletion( provider );
|
||||
ac.setAutoCompleteSingleChoices( false );
|
||||
ac.setAutoActivationEnabled( true );
|
||||
ac.setParameterAssistanceEnabled( true );
|
||||
ac.setChoicesWindowSize( UIScale.scale( 300 ), UIScale.scale( 400 ) );
|
||||
ac.setDescriptionWindowSize( UIScale.scale( 300 ), UIScale.scale( 400 ) );
|
||||
ac.install( textArea );
|
||||
|
||||
// create overlay layer
|
||||
JLayer<FlatSyntaxTextArea> overlay = new JLayer<>( textArea, new FlatThemeEditorOverlay() );
|
||||
|
||||
@@ -94,7 +109,19 @@ class FlatThemeEditorPane
|
||||
return font.deriveFont( (float) newFontSize );
|
||||
}
|
||||
|
||||
public void load( FileLocation loc ) throws IOException {
|
||||
void setBaseFiles( List<File> baseFiles ) {
|
||||
textArea.propertiesSupport.setBaseFiles( baseFiles );
|
||||
}
|
||||
|
||||
void load( FileLocation loc ) throws IOException {
|
||||
textArea.load( loc, StandardCharsets.ISO_8859_1 );
|
||||
}
|
||||
|
||||
void save() {
|
||||
try {
|
||||
textArea.save();
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace(); // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,19 @@
|
||||
|
||||
package com.formdev.flatlaf.themeeditor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import org.fife.ui.rsyntaxtextarea.FileLocation;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import com.formdev.flatlaf.extras.FlatInspector;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -37,17 +44,29 @@ public class FlatThemeFileEditor
|
||||
? args[0]
|
||||
: "theme-editor-test.properties" ); // TODO
|
||||
|
||||
List<File> baseFiles = new ArrayList<>();
|
||||
for( int i = 1; i < args.length; i++ )
|
||||
baseFiles.add( new File( args[i] ) );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatLightLaf.install();
|
||||
FlatInspector.install( "ctrl alt shift X" );
|
||||
|
||||
FlatThemeFileEditor frame = new FlatThemeFileEditor();
|
||||
|
||||
frame.themeEditorArea.setBaseFiles( baseFiles );
|
||||
try {
|
||||
frame.themeEditorArea.load( FileLocation.create( file ) );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
int menuShortcutKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||
((JComponent)frame.getContentPane()).registerKeyboardAction(
|
||||
e -> frame.themeEditorArea.save(),
|
||||
KeyStroke.getKeyStroke( KeyEvent.VK_S, menuShortcutKeyMask ),
|
||||
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
|
||||
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
frame.setSize( Math.min( UIScale.scale( 800 ), screenSize.width ),
|
||||
screenSize.height - UIScale.scale( 100 ) );
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.themeeditor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import com.formdev.flatlaf.UIDefaultsLoaderAccessor;
|
||||
|
||||
/**
|
||||
* Supports parsing content of text area in FlatLaf properties syntax.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class FlatThemePropertiesSupport
|
||||
implements DocumentListener
|
||||
{
|
||||
private final FlatSyntaxTextArea textArea;
|
||||
private final Function<String, String> propertiesGetter;
|
||||
private final Function<String, String> resolver;
|
||||
private Properties propertiesCache;
|
||||
private final Map<Integer, Object> parsedValueCache = new HashMap<>();
|
||||
|
||||
private File[] baseFiles;
|
||||
private long[] baseFilesLastModified;
|
||||
private Properties[] basePropertiesCache;
|
||||
|
||||
private Set<String> allKeysCache;
|
||||
|
||||
FlatThemePropertiesSupport( FlatSyntaxTextArea textArea ) {
|
||||
this.textArea = textArea;
|
||||
|
||||
propertiesGetter = key -> {
|
||||
return getProperty( key );
|
||||
};
|
||||
resolver = v -> {
|
||||
return resolveValue( v );
|
||||
};
|
||||
|
||||
textArea.getDocument().addDocumentListener( this );
|
||||
}
|
||||
|
||||
void setBaseFiles( List<File> baseFiles ) {
|
||||
int size = baseFiles.size();
|
||||
this.baseFiles = baseFiles.toArray( new File[size] );
|
||||
|
||||
baseFilesLastModified = new long[size];
|
||||
basePropertiesCache = new Properties[size];
|
||||
}
|
||||
|
||||
private String resolveValue( String value ) {
|
||||
return UIDefaultsLoaderAccessor.resolveValue( value, propertiesGetter );
|
||||
}
|
||||
|
||||
Object getParsedValueAtLine( int line ) {
|
||||
Integer lineKey = line;
|
||||
Object parsedValue = parsedValueCache.get( lineKey );
|
||||
if( parsedValue != null )
|
||||
return !(parsedValue instanceof Exception) ? parsedValue : null;
|
||||
|
||||
KeyValue keyValue = getKeyValueAtLine( line );
|
||||
if( keyValue == null )
|
||||
return null;
|
||||
|
||||
try {
|
||||
Object[] resultValueType = new Object[1];
|
||||
String value = resolveValue( keyValue.value );
|
||||
parsedValue = UIDefaultsLoaderAccessor.parseValue( keyValue.key, value, resultValueType, resolver );
|
||||
parsedValueCache.put( lineKey, parsedValue );
|
||||
return parsedValue;
|
||||
} catch( Exception ex ) {
|
||||
System.out.println( ex.getMessage() ); //TODO
|
||||
parsedValueCache.put( lineKey, ex );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private KeyValue getKeyValueAtLine( int line ) {
|
||||
try {
|
||||
int startOffset = textArea.getLineStartOffset( line );
|
||||
int endOffset = textArea.getLineEndOffset( line );
|
||||
String text = textArea.getText( startOffset, endOffset - startOffset );
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.load( new StringReader( text ) );
|
||||
if( properties.isEmpty() )
|
||||
return null;
|
||||
|
||||
String key = (String) properties.keys().nextElement();
|
||||
String value = properties.getProperty( key );
|
||||
return new KeyValue( key, value );
|
||||
} catch( BadLocationException | IOException ex ) {
|
||||
// ignore
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getProperty( String key ) {
|
||||
// look in current text area
|
||||
String value = getProperties().getProperty( key );
|
||||
if( value != null )
|
||||
return value;
|
||||
|
||||
if( baseFiles == null )
|
||||
return null;
|
||||
|
||||
// look in base properties files
|
||||
for( int i = 0; i < baseFiles.length; i++ ) {
|
||||
value = getBaseProperties( i ).getProperty( key );
|
||||
if( value != null )
|
||||
return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Properties getProperties() {
|
||||
if( propertiesCache != null )
|
||||
return propertiesCache;
|
||||
|
||||
propertiesCache = new Properties();
|
||||
try {
|
||||
propertiesCache.load( new StringReader( textArea.getText() ) );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace(); //TODO
|
||||
}
|
||||
return propertiesCache;
|
||||
}
|
||||
|
||||
private Properties getBaseProperties( int index ) {
|
||||
long lastModified = baseFiles[index].lastModified();
|
||||
if( baseFilesLastModified[index] != lastModified || basePropertiesCache[index] == null ) {
|
||||
// (re)load base properties file
|
||||
baseFilesLastModified[index] = lastModified;
|
||||
basePropertiesCache[index] = new Properties();
|
||||
try( InputStream in = new FileInputStream( baseFiles[index] ) ) {
|
||||
basePropertiesCache[index].load( in );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace(); //TODO
|
||||
}
|
||||
}
|
||||
|
||||
return basePropertiesCache[index];
|
||||
}
|
||||
|
||||
Set<String> getAllKeys() {
|
||||
if( allKeysCache != null )
|
||||
return allKeysCache;
|
||||
|
||||
allKeysCache = new HashSet<>();
|
||||
|
||||
for( Object key : getProperties().keySet() )
|
||||
allKeysCache.add( (String) key );
|
||||
|
||||
for( int i = 0; i < baseFiles.length; i++ ) {
|
||||
for( Object key : getBaseProperties( i ).keySet() )
|
||||
allKeysCache.add( (String) key );
|
||||
}
|
||||
|
||||
return allKeysCache;
|
||||
}
|
||||
|
||||
private void clearCache() {
|
||||
propertiesCache = null;
|
||||
parsedValueCache.clear();
|
||||
allKeysCache = null;
|
||||
}
|
||||
|
||||
//---- interface DocumentListener ----
|
||||
|
||||
@Override
|
||||
public void insertUpdate( DocumentEvent e ) {
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate( DocumentEvent e ) {
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate( DocumentEvent e ) {
|
||||
}
|
||||
|
||||
//---- class KeyValue -----------------------------------------------------
|
||||
|
||||
static class CacheLineInfo {
|
||||
Object parsedValue;
|
||||
Object valueType;
|
||||
Exception parseError;
|
||||
|
||||
Color origColor;
|
||||
}
|
||||
|
||||
//---- class KeyValue -----------------------------------------------------
|
||||
|
||||
static class KeyValue {
|
||||
final String key;
|
||||
final String value;
|
||||
|
||||
KeyValue( String key, String value ) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,921 @@
|
||||
Actions.Blue
|
||||
Actions.Green
|
||||
Actions.Grey
|
||||
Actions.GreyInline
|
||||
Actions.Red
|
||||
Actions.Yellow
|
||||
AuditoryCues.allAuditoryCues
|
||||
AuditoryCues.cueList
|
||||
AuditoryCues.noAuditoryCues
|
||||
BusyLabelUI
|
||||
Button.arc
|
||||
Button.background
|
||||
Button.border
|
||||
Button.borderColor
|
||||
Button.darkShadow
|
||||
Button.default.background
|
||||
Button.default.boldText
|
||||
Button.default.borderColor
|
||||
Button.default.borderWidth
|
||||
Button.default.focusColor
|
||||
Button.default.focusedBackground
|
||||
Button.default.focusedBorderColor
|
||||
Button.default.foreground
|
||||
Button.default.hoverBackground
|
||||
Button.default.hoverBorderColor
|
||||
Button.default.pressedBackground
|
||||
Button.defaultButtonFollowsFocus
|
||||
Button.disabledBackground
|
||||
Button.disabledBorderColor
|
||||
Button.disabledText
|
||||
Button.focusInputMap
|
||||
Button.focusedBackground
|
||||
Button.focusedBorderColor
|
||||
Button.font
|
||||
Button.foreground
|
||||
Button.highlight
|
||||
Button.hoverBackground
|
||||
Button.hoverBorderColor
|
||||
Button.iconTextGap
|
||||
Button.light
|
||||
Button.margin
|
||||
Button.minimumWidth
|
||||
Button.pressedBackground
|
||||
Button.rollover
|
||||
Button.shadow
|
||||
Button.textIconGap
|
||||
Button.textShiftOffset
|
||||
Button.toolbar.hoverBackground
|
||||
Button.toolbar.margin
|
||||
Button.toolbar.pressedBackground
|
||||
Button.toolbar.spacingInsets
|
||||
ButtonUI
|
||||
Caret.width
|
||||
CheckBox.arc
|
||||
CheckBox.background
|
||||
CheckBox.border
|
||||
CheckBox.disabledText
|
||||
CheckBox.focusInputMap
|
||||
CheckBox.font
|
||||
CheckBox.foreground
|
||||
CheckBox.icon
|
||||
CheckBox.icon.background
|
||||
CheckBox.icon.borderColor
|
||||
CheckBox.icon.checkmarkColor
|
||||
CheckBox.icon.disabledBackground
|
||||
CheckBox.icon.disabledBorderColor
|
||||
CheckBox.icon.disabledCheckmarkColor
|
||||
CheckBox.icon.focusedBackground
|
||||
CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.hoverBackground
|
||||
CheckBox.icon.hoverBorderColor
|
||||
CheckBox.icon.pressedBackground
|
||||
CheckBox.icon.selectedBackground
|
||||
CheckBox.icon.selectedBorderColor
|
||||
CheckBox.icon.selectedFocusedBorderColor
|
||||
CheckBox.icon.style
|
||||
CheckBox.iconTextGap
|
||||
CheckBox.icon[filled].checkmarkColor
|
||||
CheckBox.icon[filled].selectedBackground
|
||||
CheckBox.icon[filled].selectedBorderColor
|
||||
CheckBox.icon[filled].selectedFocusedBackground
|
||||
CheckBox.icon[filled].selectedFocusedBorderColor
|
||||
CheckBox.icon[filled].selectedFocusedCheckmarkColor
|
||||
CheckBox.icon[filled].selectedHoverBackground
|
||||
CheckBox.icon[filled].selectedPressedBackground
|
||||
CheckBox.margin
|
||||
CheckBox.rollover
|
||||
CheckBox.textIconGap
|
||||
CheckBox.textShiftOffset
|
||||
CheckBoxMenuItem.acceleratorFont
|
||||
CheckBoxMenuItem.acceleratorForeground
|
||||
CheckBoxMenuItem.acceleratorSelectionForeground
|
||||
CheckBoxMenuItem.arrowIcon
|
||||
CheckBoxMenuItem.background
|
||||
CheckBoxMenuItem.border
|
||||
CheckBoxMenuItem.borderPainted
|
||||
CheckBoxMenuItem.checkIcon
|
||||
CheckBoxMenuItem.disabledForeground
|
||||
CheckBoxMenuItem.font
|
||||
CheckBoxMenuItem.foreground
|
||||
CheckBoxMenuItem.margin
|
||||
CheckBoxMenuItem.opaque
|
||||
CheckBoxMenuItem.selectionBackground
|
||||
CheckBoxMenuItem.selectionForeground
|
||||
CheckBoxMenuItemUI
|
||||
CheckBoxUI
|
||||
ColorChooser.background
|
||||
ColorChooser.font
|
||||
ColorChooser.foreground
|
||||
ColorChooser.swatchesDefaultRecentColor
|
||||
ColorChooser.swatchesRecentSwatchSize
|
||||
ColorChooser.swatchesSwatchSize
|
||||
ColorChooserUI
|
||||
ComboBox.ancestorInputMap
|
||||
ComboBox.background
|
||||
ComboBox.border
|
||||
ComboBox.buttonArrowColor
|
||||
ComboBox.buttonBackground
|
||||
ComboBox.buttonDarkShadow
|
||||
ComboBox.buttonDisabledArrowColor
|
||||
ComboBox.buttonEditableBackground
|
||||
ComboBox.buttonHighlight
|
||||
ComboBox.buttonHoverArrowColor
|
||||
ComboBox.buttonShadow
|
||||
ComboBox.buttonStyle
|
||||
ComboBox.disabledBackground
|
||||
ComboBox.disabledForeground
|
||||
ComboBox.editorColumns
|
||||
ComboBox.font
|
||||
ComboBox.foreground
|
||||
ComboBox.isEnterSelectablePopup
|
||||
ComboBox.maximumRowCount
|
||||
ComboBox.minimumWidth
|
||||
ComboBox.noActionOnKeyNavigation
|
||||
ComboBox.padding
|
||||
ComboBox.selectionBackground
|
||||
ComboBox.selectionForeground
|
||||
ComboBox.timeFactor
|
||||
ComboBoxUI
|
||||
Component.arc
|
||||
Component.arrowType
|
||||
Component.borderColor
|
||||
Component.custom.borderColor
|
||||
Component.disabledBorderColor
|
||||
Component.error.borderColor
|
||||
Component.error.focusedBorderColor
|
||||
Component.focusColor
|
||||
Component.focusWidth
|
||||
Component.focusedBorderColor
|
||||
Component.grayFilter
|
||||
Component.hideMnemonics
|
||||
Component.innerFocusWidth
|
||||
Component.innerOutlineWidth
|
||||
Component.linkColor
|
||||
Component.minimumWidth
|
||||
Component.warning.borderColor
|
||||
Component.warning.focusedBorderColor
|
||||
DatePickerUI
|
||||
Desktop.ancestorInputMap
|
||||
Desktop.background
|
||||
Desktop.minOnScreenInsets
|
||||
DesktopIcon.background
|
||||
DesktopIcon.border
|
||||
DesktopIcon.closeIcon
|
||||
DesktopIcon.closeSize
|
||||
DesktopIcon.foreground
|
||||
DesktopIcon.iconSize
|
||||
DesktopIconUI
|
||||
DesktopPaneUI
|
||||
EditorPane.background
|
||||
EditorPane.border
|
||||
EditorPane.caretBlinkRate
|
||||
EditorPane.caretForeground
|
||||
EditorPane.disabledBackground
|
||||
EditorPane.focusInputMap
|
||||
EditorPane.font
|
||||
EditorPane.foreground
|
||||
EditorPane.inactiveBackground
|
||||
EditorPane.inactiveForeground
|
||||
EditorPane.margin
|
||||
EditorPane.selectionBackground
|
||||
EditorPane.selectionForeground
|
||||
EditorPaneUI
|
||||
FileChooser.ancestorInputMap
|
||||
FileChooser.detailsViewIcon
|
||||
FileChooser.homeFolderIcon
|
||||
FileChooser.listViewIcon
|
||||
FileChooser.newFolderIcon
|
||||
FileChooser.readOnly
|
||||
FileChooser.upFolderIcon
|
||||
FileChooser.useSystemExtensionHiding
|
||||
FileChooser.usesSingleFilePane
|
||||
FileChooserUI
|
||||
FileView.computerIcon
|
||||
FileView.directoryIcon
|
||||
FileView.fileIcon
|
||||
FileView.floppyDriveIcon
|
||||
FileView.hardDriveIcon
|
||||
FormattedTextField.background
|
||||
FormattedTextField.border
|
||||
FormattedTextField.caretBlinkRate
|
||||
FormattedTextField.caretForeground
|
||||
FormattedTextField.disabledBackground
|
||||
FormattedTextField.focusInputMap
|
||||
FormattedTextField.font
|
||||
FormattedTextField.foreground
|
||||
FormattedTextField.inactiveBackground
|
||||
FormattedTextField.inactiveForeground
|
||||
FormattedTextField.margin
|
||||
FormattedTextField.placeholderForeground
|
||||
FormattedTextField.selectionBackground
|
||||
FormattedTextField.selectionForeground
|
||||
FormattedTextFieldUI
|
||||
HeaderUI
|
||||
HelpButton.background
|
||||
HelpButton.borderColor
|
||||
HelpButton.disabledBackground
|
||||
HelpButton.disabledBorderColor
|
||||
HelpButton.disabledQuestionMarkColor
|
||||
HelpButton.focusedBackground
|
||||
HelpButton.focusedBorderColor
|
||||
HelpButton.hoverBackground
|
||||
HelpButton.hoverBorderColor
|
||||
HelpButton.icon
|
||||
HelpButton.pressedBackground
|
||||
HelpButton.questionMarkColor
|
||||
Hyperlink.disabledText
|
||||
Hyperlink.linkColor
|
||||
Hyperlink.visitedColor
|
||||
HyperlinkUI
|
||||
InternalFrame.activeBorderColor
|
||||
InternalFrame.activeDropShadowInsets
|
||||
InternalFrame.activeDropShadowOpacity
|
||||
InternalFrame.activeTitleBackground
|
||||
InternalFrame.activeTitleForeground
|
||||
InternalFrame.border
|
||||
InternalFrame.borderColor
|
||||
InternalFrame.borderDarkShadow
|
||||
InternalFrame.borderHighlight
|
||||
InternalFrame.borderLight
|
||||
InternalFrame.borderLineWidth
|
||||
InternalFrame.borderMargins
|
||||
InternalFrame.borderShadow
|
||||
InternalFrame.buttonHoverBackground
|
||||
InternalFrame.buttonPressedBackground
|
||||
InternalFrame.buttonSize
|
||||
InternalFrame.closeHoverBackground
|
||||
InternalFrame.closeHoverForeground
|
||||
InternalFrame.closeIcon
|
||||
InternalFrame.closePressedBackground
|
||||
InternalFrame.closePressedForeground
|
||||
InternalFrame.dropShadowPainted
|
||||
InternalFrame.icon
|
||||
InternalFrame.iconifyIcon
|
||||
InternalFrame.inactiveBorderColor
|
||||
InternalFrame.inactiveDropShadowInsets
|
||||
InternalFrame.inactiveDropShadowOpacity
|
||||
InternalFrame.inactiveTitleBackground
|
||||
InternalFrame.inactiveTitleForeground
|
||||
InternalFrame.maximizeIcon
|
||||
InternalFrame.minimizeIcon
|
||||
InternalFrame.titleFont
|
||||
InternalFrameTitlePane.border
|
||||
InternalFrameTitlePane.closeButtonOpacity
|
||||
InternalFrameTitlePane.iconifyButtonOpacity
|
||||
InternalFrameTitlePane.maximizeButtonOpacity
|
||||
InternalFrameUI
|
||||
JXBusyLabel.baseColor
|
||||
JXBusyLabel.highlightColor
|
||||
JXDatePicker.border
|
||||
JXHeader.background
|
||||
JXHeader.startBackground
|
||||
JXMonthView.arrowColor
|
||||
JXMonthView.background
|
||||
JXMonthView.daysOfTheWeekForeground
|
||||
JXMonthView.disabledArrowColor
|
||||
JXMonthView.flaggedDayForeground
|
||||
JXMonthView.leadingDayForeground
|
||||
JXMonthView.monthDownFileName
|
||||
JXMonthView.monthStringBackground
|
||||
JXMonthView.monthStringForeground
|
||||
JXMonthView.monthUpFileName
|
||||
JXMonthView.selectedBackground
|
||||
JXMonthView.trailingDayForeground
|
||||
JXMonthView.unselectableDayForeground
|
||||
JXMonthView.weekOfTheYearForeground
|
||||
JXTitledPanel.borderColor
|
||||
JXTitledPanel.captionInsets
|
||||
JXTitledPanel.titleBackground
|
||||
JXTitledPanel.titleForeground
|
||||
JideTabbedPane.background
|
||||
JideTabbedPane.contentBorderInsets
|
||||
JideTabbedPane.foreground
|
||||
JideTabbedPane.shadow
|
||||
JideTabbedPane.tabAreaBackground
|
||||
JideTabbedPane.tabAreaInsets
|
||||
JideTabbedPane.tabInsets
|
||||
JideTabbedPane.tabRunOverlay
|
||||
JideTabbedPaneUI
|
||||
Label.background
|
||||
Label.disabledForeground
|
||||
Label.disabledShadow
|
||||
Label.font
|
||||
Label.foreground
|
||||
LabelUI
|
||||
List.background
|
||||
List.border
|
||||
List.cellFocusColor
|
||||
List.cellMargins
|
||||
List.cellNoFocusBorder
|
||||
List.cellRenderer
|
||||
List.dropCellBackground
|
||||
List.dropCellForeground
|
||||
List.dropLineColor
|
||||
List.focusCellHighlightBorder
|
||||
List.focusInputMap
|
||||
List.focusInputMap.RightToLeft
|
||||
List.focusSelectedCellHighlightBorder
|
||||
List.font
|
||||
List.foreground
|
||||
List.noFocusBorder
|
||||
List.selectionBackground
|
||||
List.selectionForeground
|
||||
List.selectionInactiveBackground
|
||||
List.selectionInactiveForeground
|
||||
List.showCellFocusIndicator
|
||||
List.timeFactor
|
||||
ListUI
|
||||
Menu.acceleratorFont
|
||||
Menu.acceleratorForeground
|
||||
Menu.acceleratorSelectionForeground
|
||||
Menu.arrowIcon
|
||||
Menu.background
|
||||
Menu.border
|
||||
Menu.borderPainted
|
||||
Menu.cancelMode
|
||||
Menu.crossMenuMnemonic
|
||||
Menu.disabledForeground
|
||||
Menu.font
|
||||
Menu.foreground
|
||||
Menu.icon.arrowColor
|
||||
Menu.icon.disabledArrowColor
|
||||
Menu.margin
|
||||
Menu.menuPopupOffsetX
|
||||
Menu.menuPopupOffsetY
|
||||
Menu.opaque
|
||||
Menu.preserveTopLevelSelection
|
||||
Menu.selectionBackground
|
||||
Menu.selectionForeground
|
||||
Menu.shortcutKeys
|
||||
Menu.submenuPopupOffsetX
|
||||
Menu.submenuPopupOffsetY
|
||||
MenuBar.background
|
||||
MenuBar.border
|
||||
MenuBar.borderColor
|
||||
MenuBar.font
|
||||
MenuBar.foreground
|
||||
MenuBar.highlight
|
||||
MenuBar.hoverBackground
|
||||
MenuBar.itemMargins
|
||||
MenuBar.shadow
|
||||
MenuBar.windowBindings
|
||||
MenuBarUI
|
||||
MenuItem.acceleratorArrowGap
|
||||
MenuItem.acceleratorDelimiter
|
||||
MenuItem.acceleratorFont
|
||||
MenuItem.acceleratorForeground
|
||||
MenuItem.acceleratorSelectionForeground
|
||||
MenuItem.arrowIcon
|
||||
MenuItem.background
|
||||
MenuItem.border
|
||||
MenuItem.borderPainted
|
||||
MenuItem.checkBackground
|
||||
MenuItem.checkMargins
|
||||
MenuItem.disabledForeground
|
||||
MenuItem.font
|
||||
MenuItem.foreground
|
||||
MenuItem.iconTextGap
|
||||
MenuItem.margin
|
||||
MenuItem.minimumIconSize
|
||||
MenuItem.minimumWidth
|
||||
MenuItem.opaque
|
||||
MenuItem.selectionBackground
|
||||
MenuItem.selectionForeground
|
||||
MenuItem.textAcceleratorGap
|
||||
MenuItem.textNoAcceleratorGap
|
||||
MenuItem.underlineSelectionBackground
|
||||
MenuItem.underlineSelectionCheckBackground
|
||||
MenuItem.underlineSelectionColor
|
||||
MenuItem.underlineSelectionHeight
|
||||
MenuItemCheckBox.icon.checkmarkColor
|
||||
MenuItemCheckBox.icon.disabledCheckmarkColor
|
||||
MenuItemUI
|
||||
MenuUI
|
||||
MonthViewUI
|
||||
Objects.BlackText
|
||||
Objects.Blue
|
||||
Objects.Green
|
||||
Objects.GreenAndroid
|
||||
Objects.Grey
|
||||
Objects.Pink
|
||||
Objects.Purple
|
||||
Objects.Red
|
||||
Objects.RedStatus
|
||||
Objects.Yellow
|
||||
Objects.YellowDark
|
||||
OptionPane.background
|
||||
OptionPane.border
|
||||
OptionPane.buttonAreaBorder
|
||||
OptionPane.buttonClickThreshhold
|
||||
OptionPane.buttonMinimumWidth
|
||||
OptionPane.buttonOrientation
|
||||
OptionPane.buttonPadding
|
||||
OptionPane.errorIcon
|
||||
OptionPane.font
|
||||
OptionPane.foreground
|
||||
OptionPane.iconMessageGap
|
||||
OptionPane.informationIcon
|
||||
OptionPane.maxCharactersPerLine
|
||||
OptionPane.messageAreaBorder
|
||||
OptionPane.messagePadding
|
||||
OptionPane.minimumSize
|
||||
OptionPane.questionIcon
|
||||
OptionPane.sameSizeButtons
|
||||
OptionPane.setButtonMargin
|
||||
OptionPane.warningIcon
|
||||
OptionPane.windowBindings
|
||||
OptionPaneUI
|
||||
Panel.background
|
||||
Panel.font
|
||||
Panel.foreground
|
||||
PanelUI
|
||||
PasswordField.background
|
||||
PasswordField.border
|
||||
PasswordField.capsLockIcon
|
||||
PasswordField.capsLockIconColor
|
||||
PasswordField.caretBlinkRate
|
||||
PasswordField.caretForeground
|
||||
PasswordField.disabledBackground
|
||||
PasswordField.echoChar
|
||||
PasswordField.focusInputMap
|
||||
PasswordField.font
|
||||
PasswordField.foreground
|
||||
PasswordField.inactiveBackground
|
||||
PasswordField.inactiveForeground
|
||||
PasswordField.margin
|
||||
PasswordField.placeholderForeground
|
||||
PasswordField.selectionBackground
|
||||
PasswordField.selectionForeground
|
||||
PasswordFieldUI
|
||||
Popup.dropShadowColor
|
||||
Popup.dropShadowInsets
|
||||
Popup.dropShadowOpacity
|
||||
Popup.dropShadowPainted
|
||||
PopupMenu.background
|
||||
PopupMenu.border
|
||||
PopupMenu.borderColor
|
||||
PopupMenu.borderInsets
|
||||
PopupMenu.consumeEventOnClose
|
||||
PopupMenu.font
|
||||
PopupMenu.foreground
|
||||
PopupMenu.selectedWindowInputMapBindings
|
||||
PopupMenu.selectedWindowInputMapBindings.RightToLeft
|
||||
PopupMenuSeparator.height
|
||||
PopupMenuSeparator.stripeIndent
|
||||
PopupMenuSeparator.stripeWidth
|
||||
PopupMenuSeparatorUI
|
||||
PopupMenuUI
|
||||
ProgressBar.arc
|
||||
ProgressBar.background
|
||||
ProgressBar.border
|
||||
ProgressBar.cellLength
|
||||
ProgressBar.cellSpacing
|
||||
ProgressBar.cycleTime
|
||||
ProgressBar.font
|
||||
ProgressBar.foreground
|
||||
ProgressBar.horizontalSize
|
||||
ProgressBar.repaintInterval
|
||||
ProgressBar.selectionBackground
|
||||
ProgressBar.selectionForeground
|
||||
ProgressBar.verticalSize
|
||||
ProgressBarUI
|
||||
RadioButton.background
|
||||
RadioButton.border
|
||||
RadioButton.darkShadow
|
||||
RadioButton.disabledText
|
||||
RadioButton.focusInputMap
|
||||
RadioButton.font
|
||||
RadioButton.foreground
|
||||
RadioButton.highlight
|
||||
RadioButton.icon
|
||||
RadioButton.icon.centerDiameter
|
||||
RadioButton.iconTextGap
|
||||
RadioButton.icon[filled].centerDiameter
|
||||
RadioButton.light
|
||||
RadioButton.margin
|
||||
RadioButton.rollover
|
||||
RadioButton.shadow
|
||||
RadioButton.textIconGap
|
||||
RadioButton.textShiftOffset
|
||||
RadioButtonMenuItem.acceleratorFont
|
||||
RadioButtonMenuItem.acceleratorForeground
|
||||
RadioButtonMenuItem.acceleratorSelectionForeground
|
||||
RadioButtonMenuItem.arrowIcon
|
||||
RadioButtonMenuItem.background
|
||||
RadioButtonMenuItem.border
|
||||
RadioButtonMenuItem.borderPainted
|
||||
RadioButtonMenuItem.checkIcon
|
||||
RadioButtonMenuItem.disabledForeground
|
||||
RadioButtonMenuItem.font
|
||||
RadioButtonMenuItem.foreground
|
||||
RadioButtonMenuItem.margin
|
||||
RadioButtonMenuItem.opaque
|
||||
RadioButtonMenuItem.selectionBackground
|
||||
RadioButtonMenuItem.selectionForeground
|
||||
RadioButtonMenuItemUI
|
||||
RadioButtonUI
|
||||
Resizable.resizeBorder
|
||||
RootPane.activeBorderColor
|
||||
RootPane.ancestorInputMap
|
||||
RootPane.border
|
||||
RootPane.borderDragThickness
|
||||
RootPane.cornerDragWidth
|
||||
RootPane.defaultButtonWindowKeyBindings
|
||||
RootPane.honorDialogMinimumSizeOnResize
|
||||
RootPane.honorFrameMinimumSizeOnResize
|
||||
RootPane.inactiveBorderColor
|
||||
RootPaneUI
|
||||
ScrollBar.allowsAbsolutePositioning
|
||||
ScrollBar.ancestorInputMap
|
||||
ScrollBar.ancestorInputMap.RightToLeft
|
||||
ScrollBar.background
|
||||
ScrollBar.buttonArrowColor
|
||||
ScrollBar.buttonDisabledArrowColor
|
||||
ScrollBar.foreground
|
||||
ScrollBar.hoverButtonBackground
|
||||
ScrollBar.hoverThumbColor
|
||||
ScrollBar.hoverThumbWithTrack
|
||||
ScrollBar.hoverTrackColor
|
||||
ScrollBar.maximumThumbSize
|
||||
ScrollBar.minimumThumbSize
|
||||
ScrollBar.pressedButtonBackground
|
||||
ScrollBar.pressedThumbColor
|
||||
ScrollBar.pressedThumbWithTrack
|
||||
ScrollBar.showButtons
|
||||
ScrollBar.squareButtons
|
||||
ScrollBar.thumb
|
||||
ScrollBar.thumbArc
|
||||
ScrollBar.thumbDarkShadow
|
||||
ScrollBar.thumbHighlight
|
||||
ScrollBar.thumbInsets
|
||||
ScrollBar.thumbShadow
|
||||
ScrollBar.track
|
||||
ScrollBar.trackArc
|
||||
ScrollBar.trackHighlight
|
||||
ScrollBar.trackInsets
|
||||
ScrollBar.width
|
||||
ScrollBarUI
|
||||
ScrollPane.ancestorInputMap
|
||||
ScrollPane.ancestorInputMap.RightToLeft
|
||||
ScrollPane.background
|
||||
ScrollPane.border
|
||||
ScrollPane.fillUpperCorner
|
||||
ScrollPane.font
|
||||
ScrollPane.foreground
|
||||
ScrollPane.smoothScrolling
|
||||
ScrollPaneUI
|
||||
Separator.background
|
||||
Separator.foreground
|
||||
Separator.height
|
||||
Separator.highlight
|
||||
Separator.shadow
|
||||
Separator.stripeIndent
|
||||
Separator.stripeWidth
|
||||
SeparatorUI
|
||||
Slider.background
|
||||
Slider.disabledForeground
|
||||
Slider.focus
|
||||
Slider.focusInputMap
|
||||
Slider.focusInputMap.RightToLeft
|
||||
Slider.focusInsets
|
||||
Slider.font
|
||||
Slider.foreground
|
||||
Slider.highlight
|
||||
Slider.horizontalSize
|
||||
Slider.hoverColor
|
||||
Slider.minimumHorizontalSize
|
||||
Slider.minimumVerticalSize
|
||||
Slider.onlyLeftMouseButtonDrag
|
||||
Slider.shadow
|
||||
Slider.thumbColor
|
||||
Slider.thumbWidth
|
||||
Slider.tickColor
|
||||
Slider.trackColor
|
||||
Slider.trackWidth
|
||||
Slider.verticalSize
|
||||
SliderUI
|
||||
Spinner.ancestorInputMap
|
||||
Spinner.arrowButtonSize
|
||||
Spinner.background
|
||||
Spinner.border
|
||||
Spinner.buttonArrowColor
|
||||
Spinner.buttonBackground
|
||||
Spinner.buttonDisabledArrowColor
|
||||
Spinner.buttonHoverArrowColor
|
||||
Spinner.buttonStyle
|
||||
Spinner.disabledBackground
|
||||
Spinner.disabledForeground
|
||||
Spinner.editorAlignment
|
||||
Spinner.editorBorderPainted
|
||||
Spinner.font
|
||||
Spinner.foreground
|
||||
Spinner.padding
|
||||
SpinnerUI
|
||||
SplitPane.ancestorInputMap
|
||||
SplitPane.background
|
||||
SplitPane.centerOneTouchButtons
|
||||
SplitPane.continuousLayout
|
||||
SplitPane.darkShadow
|
||||
SplitPane.dividerSize
|
||||
SplitPane.highlight
|
||||
SplitPane.oneTouchButtonOffset
|
||||
SplitPane.oneTouchButtonSize
|
||||
SplitPane.shadow
|
||||
SplitPaneDivider.draggingColor
|
||||
SplitPaneDivider.oneTouchArrowColor
|
||||
SplitPaneDivider.oneTouchHoverArrowColor
|
||||
SplitPaneUI
|
||||
TabbedPane.ancestorInputMap
|
||||
TabbedPane.background
|
||||
TabbedPane.contentAreaColor
|
||||
TabbedPane.contentOpaque
|
||||
TabbedPane.contentSeparatorHeight
|
||||
TabbedPane.darkShadow
|
||||
TabbedPane.disabledForeground
|
||||
TabbedPane.disabledUnderlineColor
|
||||
TabbedPane.focus
|
||||
TabbedPane.focusColor
|
||||
TabbedPane.focusInputMap
|
||||
TabbedPane.font
|
||||
TabbedPane.foreground
|
||||
TabbedPane.hasFullBorder
|
||||
TabbedPane.highlight
|
||||
TabbedPane.hoverColor
|
||||
TabbedPane.labelShift
|
||||
TabbedPane.light
|
||||
TabbedPane.selectedLabelShift
|
||||
TabbedPane.selectedTabPadInsets
|
||||
TabbedPane.selectionFollowsFocus
|
||||
TabbedPane.shadow
|
||||
TabbedPane.tabAreaInsets
|
||||
TabbedPane.tabHeight
|
||||
TabbedPane.tabInsets
|
||||
TabbedPane.tabRunOverlay
|
||||
TabbedPane.tabSelectionHeight
|
||||
TabbedPane.tabsOpaque
|
||||
TabbedPane.tabsOverlapBorder
|
||||
TabbedPane.textIconGap
|
||||
TabbedPane.underlineColor
|
||||
TabbedPaneUI
|
||||
Table.ancestorInputMap
|
||||
Table.ancestorInputMap.RightToLeft
|
||||
Table.ascendingSortIcon
|
||||
Table.background
|
||||
Table.cellFocusColor
|
||||
Table.cellMargins
|
||||
Table.cellNoFocusBorder
|
||||
Table.descendingSortIcon
|
||||
Table.dropCellBackground
|
||||
Table.dropCellForeground
|
||||
Table.dropLineColor
|
||||
Table.dropLineShortColor
|
||||
Table.focusCellBackground
|
||||
Table.focusCellForeground
|
||||
Table.focusCellHighlightBorder
|
||||
Table.focusSelectedCellHighlightBorder
|
||||
Table.font
|
||||
Table.foreground
|
||||
Table.gridColor
|
||||
Table.intercellSpacing
|
||||
Table.rowHeight
|
||||
Table.scrollPaneBorder
|
||||
Table.selectionBackground
|
||||
Table.selectionForeground
|
||||
Table.selectionInactiveBackground
|
||||
Table.selectionInactiveForeground
|
||||
Table.showHorizontalLines
|
||||
Table.showVerticalLines
|
||||
Table.sortIconColor
|
||||
TableHeader.ancestorInputMap
|
||||
TableHeader.background
|
||||
TableHeader.bottomSeparatorColor
|
||||
TableHeader.cellBorder
|
||||
TableHeader.focusCellBackground
|
||||
TableHeader.font
|
||||
TableHeader.foreground
|
||||
TableHeader.height
|
||||
TableHeader.separatorColor
|
||||
TableHeaderUI
|
||||
TableUI
|
||||
TaskPane.background
|
||||
TaskPane.borderColor
|
||||
TaskPane.contentInsets
|
||||
TaskPane.specialTitleBackground
|
||||
TaskPane.specialTitleForeground
|
||||
TaskPane.specialTitleOver
|
||||
TaskPane.titleBackgroundGradientStart
|
||||
TaskPane.titleForeground
|
||||
TaskPane.titleOver
|
||||
TaskPaneContainer.background
|
||||
TaskPaneContainer.border
|
||||
TextArea.background
|
||||
TextArea.border
|
||||
TextArea.caretBlinkRate
|
||||
TextArea.caretForeground
|
||||
TextArea.disabledBackground
|
||||
TextArea.focusInputMap
|
||||
TextArea.font
|
||||
TextArea.foreground
|
||||
TextArea.inactiveBackground
|
||||
TextArea.inactiveForeground
|
||||
TextArea.margin
|
||||
TextArea.selectionBackground
|
||||
TextArea.selectionForeground
|
||||
TextAreaUI
|
||||
TextComponent.arc
|
||||
TextComponent.selectAllOnFocusPolicy
|
||||
TextField.background
|
||||
TextField.border
|
||||
TextField.caretBlinkRate
|
||||
TextField.caretForeground
|
||||
TextField.darkShadow
|
||||
TextField.disabledBackground
|
||||
TextField.focusInputMap
|
||||
TextField.font
|
||||
TextField.foreground
|
||||
TextField.highlight
|
||||
TextField.inactiveBackground
|
||||
TextField.inactiveForeground
|
||||
TextField.light
|
||||
TextField.margin
|
||||
TextField.placeholderForeground
|
||||
TextField.selectionBackground
|
||||
TextField.selectionForeground
|
||||
TextField.shadow
|
||||
TextFieldUI
|
||||
TextPane.background
|
||||
TextPane.border
|
||||
TextPane.caretBlinkRate
|
||||
TextPane.caretForeground
|
||||
TextPane.disabledBackground
|
||||
TextPane.focusInputMap
|
||||
TextPane.font
|
||||
TextPane.foreground
|
||||
TextPane.inactiveBackground
|
||||
TextPane.inactiveForeground
|
||||
TextPane.margin
|
||||
TextPane.selectionBackground
|
||||
TextPane.selectionForeground
|
||||
TextPaneUI
|
||||
TitlePane.background
|
||||
TitlePane.buttonHoverBackground
|
||||
TitlePane.buttonMaximizedHeight
|
||||
TitlePane.buttonPressedBackground
|
||||
TitlePane.buttonSize
|
||||
TitlePane.closeHoverBackground
|
||||
TitlePane.closeHoverForeground
|
||||
TitlePane.closeIcon
|
||||
TitlePane.closePressedBackground
|
||||
TitlePane.closePressedForeground
|
||||
TitlePane.embeddedForeground
|
||||
TitlePane.foreground
|
||||
TitlePane.iconMargins
|
||||
TitlePane.iconSize
|
||||
TitlePane.iconifyIcon
|
||||
TitlePane.inactiveBackground
|
||||
TitlePane.inactiveForeground
|
||||
TitlePane.maximizeIcon
|
||||
TitlePane.menuBarEmbedded
|
||||
TitlePane.menuBarMargins
|
||||
TitlePane.restoreIcon
|
||||
TitlePane.titleMargins
|
||||
TitledBorder.border
|
||||
TitledBorder.font
|
||||
TitledBorder.titleColor
|
||||
TitledPanelUI
|
||||
ToggleButton.background
|
||||
ToggleButton.border
|
||||
ToggleButton.darkShadow
|
||||
ToggleButton.disabledBackground
|
||||
ToggleButton.disabledSelectedBackground
|
||||
ToggleButton.disabledText
|
||||
ToggleButton.focusInputMap
|
||||
ToggleButton.font
|
||||
ToggleButton.foreground
|
||||
ToggleButton.highlight
|
||||
ToggleButton.iconTextGap
|
||||
ToggleButton.light
|
||||
ToggleButton.margin
|
||||
ToggleButton.pressedBackground
|
||||
ToggleButton.rollover
|
||||
ToggleButton.selectedBackground
|
||||
ToggleButton.selectedForeground
|
||||
ToggleButton.shadow
|
||||
ToggleButton.tab.disabledUnderlineColor
|
||||
ToggleButton.tab.focusBackground
|
||||
ToggleButton.tab.hoverBackground
|
||||
ToggleButton.tab.underlineColor
|
||||
ToggleButton.tab.underlineHeight
|
||||
ToggleButton.textIconGap
|
||||
ToggleButton.textShiftOffset
|
||||
ToggleButton.toolbar.hoverBackground
|
||||
ToggleButton.toolbar.pressedBackground
|
||||
ToggleButton.toolbar.selectedBackground
|
||||
ToggleButtonUI
|
||||
ToolBar.ancestorInputMap
|
||||
ToolBar.background
|
||||
ToolBar.border
|
||||
ToolBar.borderMargins
|
||||
ToolBar.darkShadow
|
||||
ToolBar.dockingBackground
|
||||
ToolBar.dockingForeground
|
||||
ToolBar.floatingBackground
|
||||
ToolBar.floatingForeground
|
||||
ToolBar.font
|
||||
ToolBar.foreground
|
||||
ToolBar.gripColor
|
||||
ToolBar.highlight
|
||||
ToolBar.isRollover
|
||||
ToolBar.light
|
||||
ToolBar.separatorColor
|
||||
ToolBar.separatorWidth
|
||||
ToolBar.shadow
|
||||
ToolBar.spacingBorder
|
||||
ToolBarSeparatorUI
|
||||
ToolBarUI
|
||||
ToolTip.background
|
||||
ToolTip.border
|
||||
ToolTip.font
|
||||
ToolTip.foreground
|
||||
ToolTipManager.enableToolTipMode
|
||||
ToolTipUI
|
||||
Tree.ancestorInputMap
|
||||
Tree.background
|
||||
Tree.border
|
||||
Tree.changeSelectionWithFocus
|
||||
Tree.closedIcon
|
||||
Tree.collapsedIcon
|
||||
Tree.drawsFocusBorderAroundIcon
|
||||
Tree.dropCellBackground
|
||||
Tree.dropCellForeground
|
||||
Tree.dropLineColor
|
||||
Tree.editorBorder
|
||||
Tree.expandedIcon
|
||||
Tree.focusInputMap
|
||||
Tree.focusInputMap.RightToLeft
|
||||
Tree.font
|
||||
Tree.foreground
|
||||
Tree.hash
|
||||
Tree.icon.closedColor
|
||||
Tree.icon.collapsedColor
|
||||
Tree.icon.expandedColor
|
||||
Tree.icon.leafColor
|
||||
Tree.icon.openColor
|
||||
Tree.leafIcon
|
||||
Tree.leftChildIndent
|
||||
Tree.lineTypeDashed
|
||||
Tree.openIcon
|
||||
Tree.paintLines
|
||||
Tree.rendererFillBackground
|
||||
Tree.rendererMargins
|
||||
Tree.repaintWholeRow
|
||||
Tree.rightChildIndent
|
||||
Tree.rowHeight
|
||||
Tree.scrollsOnExpand
|
||||
Tree.selectionBackground
|
||||
Tree.selectionBorderColor
|
||||
Tree.selectionForeground
|
||||
Tree.selectionInactiveBackground
|
||||
Tree.selectionInactiveForeground
|
||||
Tree.showCellFocusIndicator
|
||||
Tree.textBackground
|
||||
Tree.textForeground
|
||||
Tree.timeFactor
|
||||
Tree.wideSelection
|
||||
TreeUI
|
||||
Viewport.background
|
||||
Viewport.font
|
||||
Viewport.foreground
|
||||
ViewportUI
|
||||
activeCaption
|
||||
activeCaptionBorder
|
||||
activeCaptionText
|
||||
control
|
||||
controlDkShadow
|
||||
controlHighlight
|
||||
controlLtHighlight
|
||||
controlShadow
|
||||
controlText
|
||||
defaultFont
|
||||
desktop
|
||||
html.missingImage
|
||||
html.pendingImage
|
||||
inactiveCaption
|
||||
inactiveCaptionBorder
|
||||
inactiveCaptionText
|
||||
info
|
||||
infoText
|
||||
laf.scaleFactor
|
||||
menu
|
||||
menuText
|
||||
scrollbar
|
||||
swingx/TaskPaneUI
|
||||
text
|
||||
textHighlight
|
||||
textHighlightText
|
||||
textInactiveText
|
||||
textText
|
||||
window
|
||||
windowBorder
|
||||
windowText
|
||||
@@ -33,8 +33,8 @@ Prop.lazy=lazy(Prop.string)
|
||||
|
||||
Prop.colorFunc1=rgb(12,34,56)
|
||||
Prop.colorFunc2=rgba(12,34,56,78)
|
||||
Prop.colorFunc3=hsl(12,34,56)
|
||||
Prop.colorFunc4=hsla(12,34,56,78)
|
||||
Prop.colorFunc3=hsl(12,34%,56%)
|
||||
Prop.colorFunc4=hsla(12,34%,56%,78%)
|
||||
|
||||
Prop.colorFunc5=lighten(#fe1289,20%)
|
||||
Prop.colorFunc6=darken(#fe1289,20%)
|
||||
|
||||
Reference in New Issue
Block a user