mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 14:37:13 -06:00
UI defaults inspector:
- show computed derived colors - also show base colors and default colors - indicate derived colors with magenta bar on right side in value column
This commit is contained in:
@@ -21,11 +21,14 @@ import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
@@ -45,6 +48,7 @@ import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
import com.formdev.flatlaf.ui.FlatMarginBorder;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.ScaledEmptyBorder;
|
||||
@@ -72,6 +76,7 @@ public class FlatUIDefaultsInspector
|
||||
private final PropertyChangeListener lafListener = this::lafChanged;
|
||||
private final PropertyChangeListener lafDefaultsListener = this::lafDefaultsChanged;
|
||||
private boolean refreshPending;
|
||||
private Properties derivedColorKeys;
|
||||
|
||||
/**
|
||||
* Installs a key listener into the application that allows enabling and disabling
|
||||
@@ -298,6 +303,7 @@ public class FlatUIDefaultsInspector
|
||||
Set<Entry<Object, Object>> defaultsSet = defaults.entrySet();
|
||||
ArrayList<Item> items = new ArrayList<>( defaultsSet.size() );
|
||||
HashSet<Object> keys = new HashSet<>( defaultsSet.size() );
|
||||
Color[] pBaseColor = new Color[1];
|
||||
for( Entry<Object,Object> e : defaultsSet ) {
|
||||
Object key = e.getKey();
|
||||
|
||||
@@ -314,6 +320,13 @@ public class FlatUIDefaultsInspector
|
||||
if( !keys.add( key ) )
|
||||
continue;
|
||||
|
||||
// resolve derived color
|
||||
if( value instanceof DerivedColor ) {
|
||||
Color resolvedColor = resolveDerivedColor( defaults, (String) key, (DerivedColor) value, pBaseColor );
|
||||
if( resolvedColor != value )
|
||||
value = new Color[] { resolvedColor, pBaseColor[0], (Color) value };
|
||||
}
|
||||
|
||||
// check whether key was overridden using UIManager.put(key,value)
|
||||
Object lafValue = null;
|
||||
if( defaults.containsKey( key ) )
|
||||
@@ -326,6 +339,51 @@ public class FlatUIDefaultsInspector
|
||||
return items.toArray( new Item[items.size()] );
|
||||
}
|
||||
|
||||
private Color resolveDerivedColor( UIDefaults defaults, String key, Color color, Color[] pBaseColor ) {
|
||||
if( pBaseColor != null )
|
||||
pBaseColor[0] = null;
|
||||
|
||||
if( !(color instanceof DerivedColor) )
|
||||
return color;
|
||||
|
||||
if( derivedColorKeys == null )
|
||||
derivedColorKeys = loadDerivedColorKeys();
|
||||
|
||||
Object baseKey = derivedColorKeys.get( key );
|
||||
if( baseKey == null )
|
||||
return color;
|
||||
|
||||
// this is for keys that may be defined as derived colors, but do not derive them at runtime
|
||||
if( "null".equals( baseKey ) )
|
||||
return color;
|
||||
|
||||
Color baseColor = defaults.getColor( baseKey );
|
||||
if( baseColor == null )
|
||||
return color;
|
||||
|
||||
if( baseColor instanceof DerivedColor )
|
||||
baseColor = resolveDerivedColor( defaults, (String) baseKey, baseColor, null );
|
||||
|
||||
if( pBaseColor != null )
|
||||
pBaseColor[0] = baseColor;
|
||||
|
||||
Color newColor = FlatUIUtils.deriveColor( color, baseColor );
|
||||
|
||||
// creating a new color instance to drop Color.frgbvalue from newColor
|
||||
// and avoid rounding issues/differences
|
||||
return new Color( newColor.getRGB(), true );
|
||||
}
|
||||
|
||||
private Properties loadDerivedColorKeys() {
|
||||
Properties properties = new Properties();
|
||||
try( InputStream in = getClass().getResourceAsStream( "/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties" ) ) {
|
||||
properties.load( in );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static void updateWindowTitle( JFrame frame ) {
|
||||
String title = frame.getTitle();
|
||||
String sep = " - ";
|
||||
@@ -382,7 +440,7 @@ public class FlatUIDefaultsInspector
|
||||
return "Boolean";
|
||||
if( value instanceof Border )
|
||||
return "Border";
|
||||
if( value instanceof Color )
|
||||
if( value instanceof Color || value instanceof Color[] )
|
||||
return "Color";
|
||||
if( value instanceof Dimension )
|
||||
return "Dimension";
|
||||
@@ -590,8 +648,8 @@ public class FlatUIDefaultsInspector
|
||||
}
|
||||
|
||||
static String valueAsString( Object value ) {
|
||||
if( value instanceof Color ) {
|
||||
Color color = (Color) value;
|
||||
if( value instanceof Color || value instanceof Color[] ) {
|
||||
Color color = (value instanceof Color[]) ? ((Color[])value)[0] : (Color) value;
|
||||
HSLColor hslColor = new HSLColor( color );
|
||||
if( color.getAlpha() == 255 ) {
|
||||
return String.format( "%s rgb(%d, %d, %d) hsl(%d, %d, %d)",
|
||||
@@ -628,7 +686,7 @@ public class FlatUIDefaultsInspector
|
||||
if( border instanceof FlatLineBorder ) {
|
||||
FlatLineBorder lineBorder = (FlatLineBorder) border;
|
||||
return valueAsString( lineBorder.getUnscaledBorderInsets() )
|
||||
+ " " + Item.color2hex( lineBorder.getLineColor() )
|
||||
+ " " + color2hex( lineBorder.getLineColor() )
|
||||
+ " " + lineBorder.getLineThickness()
|
||||
+ " " + border.getClass().getName();
|
||||
} else if( border instanceof EmptyBorder ) {
|
||||
@@ -898,7 +956,7 @@ public class FlatUIDefaultsInspector
|
||||
init( table, item.key, isSelected, row );
|
||||
|
||||
// reset background, foreground and icon
|
||||
if( !(item.value instanceof Color) ) {
|
||||
if( !(item.value instanceof Color) && !(item.value instanceof Color[]) ) {
|
||||
setBackground( null );
|
||||
setForeground( null );
|
||||
}
|
||||
@@ -910,8 +968,8 @@ public class FlatUIDefaultsInspector
|
||||
|
||||
super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
|
||||
|
||||
if( item.value instanceof Color ) {
|
||||
Color color = (Color) item.value;
|
||||
if( item.value instanceof Color || item.value instanceof Color[] ) {
|
||||
Color color = (item.value instanceof Color[]) ? ((Color[])item.value)[0] : (Color) item.value;
|
||||
boolean isDark = new HSLColor( color ).getLuminance() < 70;
|
||||
setBackground( color );
|
||||
setForeground( isDark ? Color.white : Color.black );
|
||||
@@ -933,10 +991,31 @@ public class FlatUIDefaultsInspector
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
if( item.value instanceof Color ) {
|
||||
// fill background
|
||||
g.setColor( getBackground() );
|
||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||
if( item.value instanceof Color || item.value instanceof Color[] ) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color background = getBackground();
|
||||
|
||||
// paint color
|
||||
fillRect( g, background, 0, 0, width, height );
|
||||
|
||||
if( item.value instanceof Color[] ) {
|
||||
// paint base color
|
||||
int width2 = height * 2;
|
||||
fillRect( g, ((Color[])item.value)[1], width - width2, 0, width2, height );
|
||||
|
||||
// paint default color
|
||||
Color defaultColor = ((Color[])item.value)[2];
|
||||
if( defaultColor != null && !defaultColor.equals( background ) ) {
|
||||
int width3 = height / 2;
|
||||
fillRect( g, defaultColor, width - width3, 0, width3, height );
|
||||
}
|
||||
|
||||
// paint "derived color" indicator
|
||||
int width4 = height / 4;
|
||||
g.setColor( Color.magenta );
|
||||
g.fillRect( width - width4, 0, width4, height );
|
||||
}
|
||||
|
||||
// layout text
|
||||
FontMetrics fm = getFontMetrics( getFont() );
|
||||
@@ -967,6 +1046,17 @@ public class FlatUIDefaultsInspector
|
||||
|
||||
paintSeparator( g );
|
||||
}
|
||||
|
||||
private void fillRect( Graphics g, Color color, int x, int y, int width, int height ) {
|
||||
// fill white if color is translucent
|
||||
if( color.getAlpha() != 255 ) {
|
||||
g.setColor( Color.white );
|
||||
g.fillRect( x, y, width, height );
|
||||
}
|
||||
|
||||
g.setColor( color );
|
||||
g.fillRect( x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class SafeIcon -----------------------------------------------------
|
||||
|
||||
@@ -25,4 +25,6 @@ module com.formdev.flatlaf.extras {
|
||||
|
||||
exports com.formdev.flatlaf.extras;
|
||||
exports com.formdev.flatlaf.extras.components;
|
||||
|
||||
opens com.formdev.flatlaf.extras.resources;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
#
|
||||
# Copyright 2021 FormDev Software GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#
|
||||
# This file lists UI keys of colors, which are computed at runtime.
|
||||
#
|
||||
# Colors marked as `derived` in properties files are computed at runtime based on
|
||||
# a variable base color (usually the current background color of a component).
|
||||
# This works only for a limited set of UI keys.
|
||||
#
|
||||
# The property key is the UI key of a color, which is computed at runtime.
|
||||
# The property value is the UI key of the base color.
|
||||
#
|
||||
# This file is not used at runtime.
|
||||
# It is only used in tooling (e.g. UI Defaults Inspector or UIDefaultsDump).
|
||||
#
|
||||
|
||||
|
||||
#---- system colors ----
|
||||
|
||||
scrollbar = null
|
||||
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.focusedBackground = Button.background
|
||||
Button.hoverBackground = Button.background
|
||||
Button.pressedBackground = Button.background
|
||||
Button.selectedBackground = Button.background
|
||||
Button.disabledBackground = Button.background
|
||||
Button.disabledSelectedBackground = Button.background
|
||||
|
||||
Button.default.focusedBackground = Button.default.background
|
||||
Button.default.hoverBackground = Button.default.background
|
||||
Button.default.pressedBackground = Button.default.background
|
||||
|
||||
Button.toolbar.hoverBackground = Button.background
|
||||
Button.toolbar.pressedBackground = Button.background
|
||||
Button.toolbar.selectedBackground = Button.background
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
|
||||
CheckBox.icon.disabledBackground = CheckBox.icon.background
|
||||
CheckBox.icon.focusedBackground = CheckBox.icon.background
|
||||
CheckBox.icon.hoverBackground = CheckBox.icon.background
|
||||
CheckBox.icon.pressedBackground = CheckBox.icon.background
|
||||
CheckBox.icon.selectedFocusedBackground = CheckBox.icon.selectedBackground
|
||||
CheckBox.icon.selectedHoverBackground = CheckBox.icon.selectedBackground
|
||||
CheckBox.icon.selectedPressedBackground = CheckBox.icon.selectedBackground
|
||||
|
||||
CheckBox.icon[filled].disabledBackground = CheckBox.icon[filled].background
|
||||
CheckBox.icon[filled].focusedBackground = CheckBox.icon[filled].background
|
||||
CheckBox.icon[filled].hoverBackground = CheckBox.icon[filled].background
|
||||
CheckBox.icon[filled].pressedBackground = CheckBox.icon[filled].background
|
||||
CheckBox.icon[filled].selectedFocusedBackground = CheckBox.icon[filled].selectedBackground
|
||||
CheckBox.icon[filled].selectedHoverBackground = CheckBox.icon[filled].selectedBackground
|
||||
CheckBox.icon[filled].selectedPressedBackground = CheckBox.icon[filled].selectedBackground
|
||||
|
||||
|
||||
#---- CheckBoxMenuItem ----
|
||||
|
||||
CheckBoxMenuItem.selectionBackground = CheckBoxMenuItem.background
|
||||
|
||||
|
||||
#---- ComboBox ----
|
||||
|
||||
ComboBox.buttonDisabledArrowColor = ComboBox.buttonArrowColor
|
||||
ComboBox.buttonHoverArrowColor = ComboBox.buttonArrowColor
|
||||
ComboBox.buttonPressedArrowColor = ComboBox.buttonArrowColor
|
||||
|
||||
|
||||
#---- Component ----
|
||||
|
||||
Component.custom.borderColor = null
|
||||
|
||||
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.disabledBackground = HelpButton.background
|
||||
HelpButton.focusedBackground = HelpButton.background
|
||||
HelpButton.hoverBackground = HelpButton.background
|
||||
HelpButton.pressedBackground = HelpButton.background
|
||||
|
||||
|
||||
#---- InternalFrame ----
|
||||
|
||||
InternalFrame.buttonHoverBackground = InternalFrame.activeTitleBackground
|
||||
InternalFrame.buttonPressedBackground = InternalFrame.activeTitleBackground
|
||||
|
||||
|
||||
#---- Menu ----
|
||||
|
||||
Menu.selectionBackground = Menu.background
|
||||
|
||||
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.hoverBackground = Menu.background
|
||||
MenuBar.underlineSelectionBackground = Menu.background
|
||||
|
||||
|
||||
#---- MenuItem ----
|
||||
|
||||
MenuItem.checkBackground = MenuItem.selectionBackground
|
||||
MenuItem.underlineSelectionBackground = MenuItem.background
|
||||
MenuItem.underlineSelectionCheckBackground = MenuItem.selectionBackground
|
||||
MenuItem.selectionBackground = MenuItem.background
|
||||
|
||||
|
||||
#---- RadioButtonMenuItem ----
|
||||
|
||||
RadioButtonMenuItem.selectionBackground = RadioButtonMenuItem.background
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.activeBorderColor = Panel.background
|
||||
RootPane.inactiveBorderColor = Panel.background
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.track = ScrollBar.background
|
||||
ScrollBar.thumb = ScrollBar.track
|
||||
ScrollBar.hoverTrackColor = ScrollBar.track
|
||||
ScrollBar.hoverThumbColor = ScrollBar.thumb
|
||||
ScrollBar.pressedTrackColor = ScrollBar.track
|
||||
ScrollBar.pressedThumbColor = ScrollBar.thumb
|
||||
|
||||
ScrollBar.buttonDisabledArrowColor = ScrollBar.buttonArrowColor
|
||||
ScrollBar.hoverButtonBackground = ScrollBar.background
|
||||
ScrollBar.pressedButtonBackground = ScrollBar.background
|
||||
|
||||
|
||||
#---- ScrollPane ----
|
||||
|
||||
ScrollPane.background = null
|
||||
|
||||
|
||||
#---- Slider ----
|
||||
|
||||
Slider.focusedColor = Component.focusColor
|
||||
Slider.hoverThumbColor = Slider.thumbColor
|
||||
Slider.pressedThumbColor = Slider.thumbColor
|
||||
Slider.disabledThumbColor = Slider.thumbColor
|
||||
|
||||
|
||||
#---- Spinner ----
|
||||
|
||||
Spinner.buttonDisabledArrowColor = Spinner.buttonArrowColor
|
||||
Spinner.buttonHoverArrowColor = Spinner.buttonArrowColor
|
||||
Spinner.buttonPressedArrowColor = Spinner.buttonArrowColor
|
||||
|
||||
|
||||
#---- SplitPaneDivider ----
|
||||
|
||||
SplitPaneDivider.oneTouchHoverArrowColor = SplitPaneDivider.oneTouchArrowColor
|
||||
SplitPaneDivider.oneTouchPressedArrowColor = SplitPaneDivider.oneTouchArrowColor
|
||||
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.selectedBackground = TabbedPane.background
|
||||
TabbedPane.hoverColor = TabbedPane.background
|
||||
TabbedPane.focusColor = TabbedPane.background
|
||||
|
||||
TabbedPane.closeBackground = TabbedPane.background
|
||||
TabbedPane.closeHoverBackground = TabbedPane.background
|
||||
TabbedPane.closePressedBackground = TabbedPane.background
|
||||
|
||||
TabbedPane.closeForeground = TabbedPane.foreground
|
||||
TabbedPane.closeHoverForeground = TabbedPane.foreground
|
||||
TabbedPane.closePressedForeground = TabbedPane.foreground
|
||||
|
||||
TabbedPane.buttonHoverBackground = TabbedPane.background
|
||||
TabbedPane.buttonPressedBackground = TabbedPane.background
|
||||
|
||||
|
||||
#---- TitlePane ----
|
||||
|
||||
TitlePane.buttonHoverBackground = TitlePane.background
|
||||
TitlePane.buttonPressedBackground = TitlePane.background
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.focusedBackground = ToggleButton.background
|
||||
ToggleButton.hoverBackground = ToggleButton.background
|
||||
ToggleButton.pressedBackground = ToggleButton.background
|
||||
ToggleButton.selectedBackground = ToggleButton.background
|
||||
ToggleButton.disabledBackground = ToggleButton.background
|
||||
ToggleButton.disabledSelectedBackground = ToggleButton.background
|
||||
|
||||
ToggleButton.toolbar.hoverBackground = ToggleButton.background
|
||||
ToggleButton.toolbar.pressedBackground = ToggleButton.background
|
||||
ToggleButton.toolbar.selectedBackground = ToggleButton.background
|
||||
|
||||
ToggleButton.tab.hoverBackground = null
|
||||
@@ -381,6 +381,9 @@ MenuBar.highlight
|
||||
MenuBar.hoverBackground
|
||||
MenuBar.itemMargins
|
||||
MenuBar.shadow
|
||||
MenuBar.underlineSelectionBackground
|
||||
MenuBar.underlineSelectionColor
|
||||
MenuBar.underlineSelectionHeight
|
||||
MenuBar.windowBindings
|
||||
MenuBarUI
|
||||
MenuItem.acceleratorArrowGap
|
||||
@@ -566,6 +569,7 @@ ScrollBar.minimumThumbSize
|
||||
ScrollBar.pressedButtonBackground
|
||||
ScrollBar.pressedThumbColor
|
||||
ScrollBar.pressedThumbWithTrack
|
||||
ScrollBar.pressedTrackColor
|
||||
ScrollBar.showButtons
|
||||
ScrollBar.squareButtons
|
||||
ScrollBar.thumb
|
||||
@@ -699,6 +703,8 @@ TabbedPane.labelShift
|
||||
TabbedPane.light
|
||||
TabbedPane.scrollButtonsPlacement
|
||||
TabbedPane.scrollButtonsPolicy
|
||||
TabbedPane.selectedBackground
|
||||
TabbedPane.selectedForeground
|
||||
TabbedPane.selectedLabelShift
|
||||
TabbedPane.selectedTabPadInsets
|
||||
TabbedPane.selectionFollowsFocus
|
||||
|
||||
Reference in New Issue
Block a user