Compare commits

..

23 Commits
2.2 ... 2.3

Author SHA1 Message Date
Karl Tauber
69851b7f3a release 2.3 2022-05-28 17:53:54 +02:00
Karl Tauber
92b53bf0df Merge PR #522: File chooser shortcuts panel 2022-05-28 17:46:12 +02:00
Karl Tauber
93e0496fd2 ToggleButton: button style "tab": added missing foreground colors for hover, focused and selected states (issue #535) 2022-05-28 15:09:04 +02:00
Karl Tauber
5151951f46 Button and ToggleButton: added missing foreground colors for hover, pressed, focused and selected states (issue #535) 2022-05-28 14:54:31 +02:00
Karl Tauber
58dbccec2d Table: optionally paint alternating rows below table if table is smaller than scroll pane (issue #504) 2022-05-25 11:18:22 +02:00
Karl Tauber
90de14d013 Native library: refactored loading of Windows native library from FlatWindowsNativeWindowBorder to FlatNativeLibrary to make it easier to add native libraries for other platforms (for issues #204 and #482) 2022-05-17 20:24:28 +02:00
Karl Tauber
5f961618bf Demo and Theme Editor: updated macOS related comments 2022-05-13 13:54:10 +02:00
Karl Tauber
37c375e2fa Theme Editor:
- support "themes" sub-directory
- added "generate Java class" checkbox to "New" dialog
2022-05-10 11:01:45 +02:00
Karl Tauber
1758c175ed FlatLafUIKeys.txt: added some missing UI defaults 2022-05-09 23:30:34 +02:00
Karl Tauber
96f2a02cfa UIDefaultsLoader: added over() color function to convert a translucent color into a solid color based on any background color 2022-05-09 23:28:40 +02:00
Karl Tauber
96d4bda6c8 Demo: hide accent color buttons (instead of disabling them) if not supported by selected theme 2022-05-09 22:51:38 +02:00
Karl Tauber
02cf6050a1 updates for PR #530:
- added @since tags
- changed `FlatToggleButton.setTabUnderlinePlacement()` implementation so that is behaves similar to `FlatTabbedPane.setTabIconPlacement()`
2022-05-09 22:28:34 +02:00
Karl Tauber
38cf32a2e9 Merge PR #530: ToggleButton: made underline placement configurable 2022-05-09 22:08:42 +02:00
Karl Tauber
2ae7589d14 Merge PR #525: Create Bundle_es.properties 2022-05-09 21:28:47 +02:00
Julien Fischer
bcb2e1f0a1 ToggleButton: made underline placement configurable
Supported values: TOP, LEFT, BOTTOM, or RIGHT
2022-05-06 12:07:50 +02:00
Karl Tauber
14932d3f07 Theme Editor: on macOS use apple.awt.fullWindowContent and apple.awt.transparentTitleBar 2022-05-05 13:20:23 +02:00
Karl Tauber
c3b9dc397d Demo: on macOS use apple.awt.fullWindowContent and apple.awt.transparentTitleBar 2022-05-01 11:45:36 +02:00
Karl Tauber
58b653f55d updated sigtest for FlatLaf 2.2
(generated in clean workspace with gradle task `sigtestGenerate`)
2022-05-01 11:44:51 +02:00
Jesús Marín
1dcdc42dde Create Bundle_es.properties
Flatlaf Spanish translation
2022-04-29 14:51:11 +01:00
Karl Tauber
58a0a16985 IntelliJ Themes: fixed TitledBorder text color in "Monokai Pro" theme (issue #524) 2022-04-28 15:16:26 +02:00
Karl Tauber
a117243f14 FileChooser: use large system icons in shortcuts panel also in Java 8 to 16 2022-04-26 22:50:34 +02:00
Karl Tauber
22411060be FileChooser: improve layout for shortcuts panel (give it full height) 2022-04-25 23:49:15 +02:00
Karl Tauber
045263ae58 FileChooser: added (optional) shortcuts panel (issue #100) 2022-04-25 23:06:10 +02:00
32 changed files with 1046 additions and 94 deletions

View File

@@ -1,6 +1,28 @@
FlatLaf Change Log
==================
## 2.3
#### New features and improvements
- FileChooser: Added (optional) shortcuts panel. On Windows it contains "Recent
Items", "Desktop", "Documents", "This PC" and "Network". On macOS and Linux it
is empty/hidden. (issue #100)
- Button and ToggleButton: Added missing foreground colors for hover, pressed,
focused and selected states. (issue #535)
- Table: Optionally paint alternating rows below table if table is smaller than
scroll pane. Set UI value `Table.paintOutsideAlternateRows` to `true`.
Requires that `Table.alternateRowColor` is set to a color. (issue #504)
- ToggleButton: Made the underline placement of tab-style toggle buttons
configurable. (PR #530; issue #529)
- Added spanish translation. (PR #525)
#### Fixed bugs
- IntelliJ Themes: Fixed `TitledBorder` text color in "Monokai Pro" theme.
(issue #524)
## 2.2
#### New features and improvements
@@ -141,7 +163,7 @@ FlatLaf Change Log
- Possibility to hide window title bar icon (for single window set client
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
value `TitlePane.showIcon` to `false`).
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
- OptionPane: Hide window title bar icon by default. Can be made visibly by
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
- No longer show the Java "duke/cup" icon if no window icon image is set.
(issue #416)

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
val releaseVersion = "2.2"
val developmentVersion = "2.3-SNAPSHOT"
val releaseVersion = "2.3"
val developmentVersion = "2.4-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion

View File

@@ -1,5 +1,5 @@
#Signature file v4.1
#Version 2.1
#Version 2.2
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
@@ -30,6 +30,9 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY = "JTextFiel
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
fld public final static java.lang.String SQUARE_SIZE = "JButton.squareSize"
fld public final static java.lang.String STYLE = "FlatLaf.style"
fld public final static java.lang.String STYLE_CLASS = "FlatLaf.styleClass"

View File

@@ -992,7 +992,22 @@ public interface FlatClientProperties
//---- JToggleButton ------------------------------------------------------
/**
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
* Placement of underline if toggle button type is {@link #BUTTON_TYPE_TAB}
* <p>
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
* <strong>Value type</strong> {@link java.lang.Integer}<br>
* <strong>SupportedValues:</strong>
* {@link SwingConstants#BOTTOM} (default)
* {@link SwingConstants#TOP},
* {@link SwingConstants#LEFT} or
* {@link SwingConstants#RIGHT}
*
* @since 2.3
*/
String TAB_BUTTON_UNDERLINE_PLACEMENT = "JToggleButton.tab.underlinePlacement";
/**
* Thickness of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
* <p>
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
* <strong>Value type</strong> {@link java.lang.Integer}

View File

@@ -466,6 +466,10 @@ class UIDefaultsLoader
if( knownValueTypes == null ) {
// create lazy
knownValueTypes = new HashMap<>();
// system colors
knownValueTypes.put( "activeCaptionBorder", ValueType.COLOR );
knownValueTypes.put( "inactiveCaptionBorder", ValueType.COLOR );
knownValueTypes.put( "windowBorder", ValueType.COLOR );
// SplitPane
knownValueTypes.put( "SplitPane.dividerSize", ValueType.INTEGER );
knownValueTypes.put( "SplitPaneDivider.gripDotSize", ValueType.INTEGER );
@@ -780,6 +784,7 @@ class UIDefaultsLoader
case "tint": return parseColorMix( "#fff", params, resolver, reportError );
case "shade": return parseColorMix( "#000", params, resolver, reportError );
case "contrast": return parseColorContrast( params, resolver, reportError );
case "over": return parseColorOver( params, resolver, reportError );
}
} finally {
parseColorDepth--;
@@ -847,7 +852,7 @@ class UIDefaultsLoader
int lightness = parsePercentage( params.get( 2 ) );
int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100;
float[] hsl = new float[] { hue, saturation, lightness };
float[] hsl = { hue, saturation, lightness };
return new ColorUIResource( HSLColor.toRGB( hsl, alpha / 100f ) );
}
@@ -1041,6 +1046,33 @@ class UIDefaultsLoader
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError );
}
/**
* Syntax: over(foreground,background)
* - foreground: a foreground color (e.g. #f00) or a color function;
* the alpha of this color is used as weight to mix the two colors
* - background: a background color (e.g. #f00) or a color function
*/
private static Object parseColorOver( List<String> params, Function<String, String> resolver, boolean reportError ) {
String foregroundStr = params.get( 0 );
String backgroundStr = params.get( 1 );
// parse foreground color
ColorUIResource foreground = (ColorUIResource) parseColorOrFunction( resolver.apply( foregroundStr ), resolver, reportError );
if( foreground == null || foreground.getAlpha() == 255 )
return foreground;
Color foreground2 = new Color( foreground.getRGB() );
// parse background color
ColorUIResource background = (ColorUIResource) parseColorOrFunction( resolver.apply( backgroundStr ), resolver, reportError );
if( background == null )
return foreground2;
// create new color
float weight = foreground.getAlpha() / 255f;
return new ColorUIResource( ColorFunctions.mix( foreground2, background, weight ) );
}
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
boolean derived, Function<String, String> resolver, boolean reportError )
{

View File

@@ -78,20 +78,27 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
* @uiDefault Button.focusedBackground Color optional
* @uiDefault Button.focusedForeground Color optional
* @uiDefault Button.hoverBackground Color optional
* @uiDefault Button.hoverForeground Color optional
* @uiDefault Button.pressedBackground Color optional
* @uiDefault Button.pressedForeground Color optional
* @uiDefault Button.selectedBackground Color
* @uiDefault Button.selectedForeground Color
* @uiDefault Button.disabledBackground Color optional
* @uiDefault Button.disabledText Color
* @uiDefault Button.disabledSelectedBackground Color
* @uiDefault Button.disabledSelectedForeground Color optional
* @uiDefault Button.default.background Color
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
* @uiDefault Button.default.foreground Color
* @uiDefault Button.default.focusedBackground Color optional
* @uiDefault Button.default.focusedForeground Color optional
* @uiDefault Button.default.hoverBackground Color optional
* @uiDefault Button.default.hoverForeground Color optional
* @uiDefault Button.default.pressedBackground Color optional
* @uiDefault Button.default.pressedForeground Color optional
* @uiDefault Button.default.boldText boolean
* @uiDefault Button.paintShadow boolean default is false
* @uiDefault Button.shadowWidth int default is 2
@@ -99,8 +106,13 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault Button.default.shadowColor Color optional
* @uiDefault Button.toolbar.spacingInsets Insets
* @uiDefault Button.toolbar.hoverBackground Color
* @uiDefault Button.toolbar.hoverForeground Color optional
* @uiDefault Button.toolbar.pressedBackground Color
* @uiDefault Button.toolbar.pressedForeground Color optional
* @uiDefault Button.toolbar.selectedBackground Color
* @uiDefault Button.toolbar.selectedForeground Color optional
* @uiDefault Button.toolbar.disabledSelectedBackground Color optional
* @uiDefault Button.toolbar.disabledSelectedForeground Color optional
*
* @author Karl Tauber
*/
@@ -117,20 +129,27 @@ public class FlatButtonUI
protected Color startBackground;
protected Color endBackground;
@Styleable protected Color focusedBackground;
/** @since 2.3 */ @Styleable protected Color focusedForeground;
@Styleable protected Color hoverBackground;
/** @since 2.3 */ @Styleable protected Color hoverForeground;
@Styleable protected Color pressedBackground;
/** @since 2.3 */ @Styleable protected Color pressedForeground;
@Styleable protected Color selectedBackground;
@Styleable protected Color selectedForeground;
@Styleable protected Color disabledBackground;
@Styleable protected Color disabledText;
@Styleable protected Color disabledSelectedBackground;
/** @since 2.3 */ @Styleable protected Color disabledSelectedForeground;
@Styleable(dot=true) protected Color defaultBackground;
protected Color defaultEndBackground;
@Styleable(dot=true) protected Color defaultForeground;
@Styleable(dot=true) protected Color defaultFocusedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultFocusedForeground;
@Styleable(dot=true) protected Color defaultHoverBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultHoverForeground;
@Styleable(dot=true) protected Color defaultPressedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultPressedForeground;
@Styleable(dot=true) protected boolean defaultBoldText;
@Styleable protected boolean paintShadow;
@@ -139,8 +158,13 @@ public class FlatButtonUI
@Styleable(dot=true) protected Color defaultShadowColor;
@Styleable(dot=true) protected Color toolbarHoverBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarHoverForeground;
@Styleable(dot=true) protected Color toolbarPressedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarPressedForeground;
@Styleable(dot=true) protected Color toolbarSelectedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarSelectedForeground;
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedForeground;
// only used via styling (not in UI defaults, but has likewise client properties)
/** @since 2 */ @Styleable protected String buttonType;
@@ -190,20 +214,27 @@ public class FlatButtonUI
startBackground = UIManager.getColor( prefix + "startBackground" );
endBackground = UIManager.getColor( prefix + "endBackground" );
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
focusedForeground = UIManager.getColor( prefix + "focusedForeground" );
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
hoverForeground = UIManager.getColor( prefix + "hoverForeground" );
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
pressedForeground = UIManager.getColor( prefix + "pressedForeground" );
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
disabledText = UIManager.getColor( prefix + "disabledText" );
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
disabledSelectedForeground = UIManager.getColor( prefix + "disabledSelectedForeground" );
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
defaultForeground = UIManager.getColor( "Button.default.foreground" );
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
defaultFocusedForeground = UIManager.getColor( "Button.default.focusedForeground" );
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
defaultHoverForeground = UIManager.getColor( "Button.default.hoverForeground" );
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
defaultPressedForeground = UIManager.getColor( "Button.default.pressedForeground" );
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
@@ -212,8 +243,13 @@ public class FlatButtonUI
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
toolbarHoverForeground = UIManager.getColor( prefix + "toolbar.hoverForeground" );
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
toolbarPressedForeground = UIManager.getColor( prefix + "toolbar.pressedForeground" );
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
toolbarSelectedForeground = UIManager.getColor( prefix + "toolbar.selectedForeground" );
toolbarDisabledSelectedBackground = UIManager.getColor( prefix + "toolbar.disabledSelectedBackground" );
toolbarDisabledSelectedForeground = UIManager.getColor( prefix + "toolbar.disabledSelectedForeground" );
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
defaultMargin = UIManager.getInsets( prefix + "margin" );
@@ -532,6 +568,8 @@ public class FlatButtonUI
}
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
if(foreground == null)
foreground=Color.red;
FontMetrics fm = b.getFontMetrics( b.getFont() );
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
@@ -545,11 +583,14 @@ public class FlatButtonUI
// selected state
if( ((AbstractButton)c).isSelected() ) {
// in toolbar use same background colors for disabled and enabled because
// in toolbar, if toolbarDisabledSelectedBackground is null,
// use same background colors for disabled and enabled because
// we assume that toolbar icon is shown disabled
return buttonStateColor( c,
toolBarButton ? toolbarSelectedBackground : selectedBackground,
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
toolBarButton
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
: disabledSelectedBackground,
null,
null,
toolBarButton ? toolbarPressedBackground : pressedBackground );
@@ -614,18 +655,48 @@ public class FlatButtonUI
}
protected Color getForeground( JComponent c ) {
if( !c.isEnabled() )
return disabledText;
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
return selectedForeground;
// selected state
if( ((AbstractButton)c).isSelected() ) {
return buttonStateColor( c,
toolBarButton
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : c.getForeground())
: selectedForeground,
toolBarButton
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
null,
null,
toolBarButton ? toolbarPressedForeground : pressedForeground );
}
// toolbar button
if( toolBarButton ) {
return buttonStateColor( c,
c.getForeground(),
disabledText,
null,
toolbarHoverForeground,
toolbarPressedForeground );
}
boolean def = isDefaultButton( c );
return buttonStateColor( c,
getForegroundBase( c, def ),
disabledText,
isCustomForeground( c.getForeground() ) ? null : (def ? defaultFocusedForeground : focusedForeground),
def ? defaultHoverForeground : hoverForeground,
def ? defaultPressedForeground : pressedForeground );
}
/** @since 2.3 */
protected Color getForegroundBase( JComponent c, boolean def ) {
// use component foreground if explicitly set
Color fg = c.getForeground();
if( isCustomForeground( fg ) )
return fg;
boolean def = isDefaultButton( c );
return def ? defaultForeground : fg;
}

View File

@@ -19,11 +19,21 @@ package com.formdev.flatlaf.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Method;
import java.util.function.Function;
import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -34,12 +44,16 @@ import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalFileChooserUI;
import javax.swing.table.TableCellRenderer;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.ScaledImageIcon;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -133,12 +147,21 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault FileChooser.listViewActionLabelText String
* @uiDefault FileChooser.detailsViewActionLabelText String
*
* <!-- FlatFileChooserUI -->
*
* @uiDefault FileChooser.shortcuts.buttonSize Dimension optional; default is 84,64
* @uiDefault FileChooser.shortcuts.iconSize Dimension optional; default is 32,32
* @uiDefault FileChooser.shortcuts.filesFunction Function<File[], File[]>
* @uiDefault FileChooser.shortcuts.displayNameFunction Function<File, String>
* @uiDefault FileChooser.shortcuts.iconFunction Function<File, Icon>
*
* @author Karl Tauber
*/
public class FlatFileChooserUI
extends MetalFileChooserUI
{
private final FlatFileView fileView = new FlatFileView();
private FlatShortcutsPanel shortcutsPanel;
public static ComponentUI createUI( JComponent c ) {
return new FlatFileChooserUI( (JFileChooser) c );
@@ -153,6 +176,25 @@ public class FlatFileChooserUI
super.installComponents( fc );
patchUI( fc );
if( !UIManager.getBoolean( "FileChooser.noPlacesBar" ) ) { // same as in Windows L&F
FlatShortcutsPanel panel = createShortcutsPanel( fc );
if( panel.getComponentCount() > 0 ) {
shortcutsPanel = panel;
fc.add( shortcutsPanel, BorderLayout.LINE_START );
fc.addPropertyChangeListener( shortcutsPanel );
}
}
}
@Override
public void uninstallComponents( JFileChooser fc ) {
super.uninstallComponents( fc );
if( shortcutsPanel != null ) {
fc.removePropertyChangeListener( shortcutsPanel );
shortcutsPanel = null;
}
}
private void patchUI( JFileChooser fc ) {
@@ -192,6 +234,25 @@ public class FlatFileChooserUI
} catch( ArrayIndexOutOfBoundsException ex ) {
// ignore
}
// put north, center and south components into a new panel so that
// the shortcuts panel (at west) gets full height
LayoutManager layout = fc.getLayout();
if( layout instanceof BorderLayout ) {
BorderLayout borderLayout = (BorderLayout) layout;
borderLayout.setHgap( 8 );
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
if( north != null && center != null && south != null ) {
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
p.add( north, BorderLayout.NORTH );
p.add( center, BorderLayout.CENTER );
p.add( south, BorderLayout.SOUTH );
fc.add( p, BorderLayout.CENTER );
}
}
}
@Override
@@ -250,9 +311,19 @@ public class FlatFileChooserUI
return p;
}
/** @since 2.3 */
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
return new FlatShortcutsPanel( fc );
}
@Override
public Dimension getPreferredSize( JComponent c ) {
return UIScale.scale( super.getPreferredSize( c ) );
Dimension prefSize = super.getPreferredSize( c );
Dimension minSize = getMinimumSize( c );
int shortcutsPanelWidth = (shortcutsPanel != null) ? shortcutsPanel.getPreferredSize().width : 0;
return new Dimension(
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
Math.max( prefSize.height, minSize.height ) );
}
@Override
@@ -316,4 +387,234 @@ public class FlatFileChooserUI
return icon;
}
}
//---- class FlatShortcutsPanel -------------------------------------------
/** @since 2.3 */
public static class FlatShortcutsPanel
extends JToolBar
implements PropertyChangeListener
{
private final JFileChooser fc;
private final Dimension buttonSize;
private final Dimension iconSize;
private final Function<File[], File[]> filesFunction;
private final Function<File, String> displayNameFunction;
private final Function<File, Icon> iconFunction;
protected final File[] files;
protected final JToggleButton[] buttons;
protected final ButtonGroup buttonGroup;
@SuppressWarnings( "unchecked" )
public FlatShortcutsPanel( JFileChooser fc ) {
super( JToolBar.VERTICAL );
this.fc = fc;
setFloatable( false );
buttonSize = UIScale.scale( getUIDimension( "FileChooser.shortcuts.buttonSize", 84, 64 ) );
iconSize = getUIDimension( "FileChooser.shortcuts.iconSize", 32, 32 );
filesFunction = (Function<File[], File[]>) UIManager.get( "FileChooser.shortcuts.filesFunction" );
displayNameFunction = (Function<File, String>) UIManager.get( "FileChooser.shortcuts.displayNameFunction" );
iconFunction = (Function<File, Icon>) UIManager.get( "FileChooser.shortcuts.iconFunction" );
FileSystemView fsv = fc.getFileSystemView();
File[] files = getChooserShortcutPanelFiles( fsv );
if( filesFunction != null )
files = filesFunction.apply( files );
this.files = files;
// create toolbar buttons
buttons = new JToggleButton[files.length];
buttonGroup = new ButtonGroup();
for( int i = 0; i < files.length; i++ ) {
// wrap drive path
if( fsv.isFileSystemRoot( files[i] ) )
files[i] = fsv.createFileObject( files[i].getAbsolutePath() );
File file = files[i];
String name = getDisplayName( fsv, file );
Icon icon = getIcon( fsv, file );
// remove path from name
int lastSepIndex = name.lastIndexOf( File.separatorChar );
if( lastSepIndex >= 0 && lastSepIndex < name.length() - 1 )
name = name.substring( lastSepIndex + 1 );
// scale icon (if necessary)
if( icon instanceof ImageIcon )
icon = new ScaledImageIcon( (ImageIcon) icon, iconSize.width, iconSize.height );
else if( icon != null )
icon = new ShortcutIcon( icon, iconSize.width, iconSize.height );
// create button
JToggleButton button = createButton( name, icon );
button.addActionListener( e -> {
fc.setCurrentDirectory( file );
} );
add( button );
buttonGroup.add( button );
buttons[i] = button;
}
directoryChanged( fc.getCurrentDirectory() );
}
private Dimension getUIDimension( String key, int defaultWidth, int defaultHeight ) {
Dimension size = UIManager.getDimension( key );
if( size == null )
size = new Dimension( defaultWidth, defaultHeight );
return size;
}
protected JToggleButton createButton( String name, Icon icon ) {
JToggleButton button = new JToggleButton( name, icon );
button.setVerticalTextPosition( SwingConstants.BOTTOM );
button.setHorizontalTextPosition( SwingConstants.CENTER );
button.setAlignmentX( Component.CENTER_ALIGNMENT );
button.setIconTextGap( 0 );
button.setPreferredSize( buttonSize );
button.setMaximumSize( buttonSize );
return button;
}
protected File[] getChooserShortcutPanelFiles( FileSystemView fsv ) {
try {
if( SystemInfo.isJava_12_orLater ) {
Method m = fsv.getClass().getMethod( "getChooserShortcutPanelFiles" );
File[] files = (File[]) m.invoke( fsv );
// on macOS and Linux, files consists only of the user home directory
if( files.length == 1 && files[0].equals( new File( System.getProperty( "user.home" ) ) ) )
files = new File[0];
return files;
} else if( SystemInfo.isWindows ) {
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
Method m = cls.getMethod( "get", String.class );
return (File[]) m.invoke( null, "fileChooserShortcutPanelFolders" );
}
} catch( IllegalAccessException ex ) {
// do not log because access may be denied via VM option '--illegal-access=deny'
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
// fallback
return new File[0];
}
protected String getDisplayName( FileSystemView fsv, File file ) {
if( displayNameFunction != null ) {
String name = displayNameFunction.apply( file );
if( name != null )
return name;
}
return fsv.getSystemDisplayName( file );
}
protected Icon getIcon( FileSystemView fsv, File file ) {
if( iconFunction != null ) {
Icon icon = iconFunction.apply( file );
if( icon != null )
return icon;
}
// Java 17+ supports getting larger system icons
try {
if( SystemInfo.isJava_17_orLater ) {
Method m = fsv.getClass().getMethod( "getSystemIcon", File.class, int.class, int.class );
return (Icon) m.invoke( fsv, file, iconSize.width, iconSize.height );
} else if( iconSize.width > 16 || iconSize.height > 16 ) {
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
if( cls.isInstance( file ) ) {
Method m = file.getClass().getMethod( "getIcon", boolean.class );
m.setAccessible( true );
Image image = (Image) m.invoke( file, true );
if( image != null )
return new ImageIcon( image );
}
}
} catch( IllegalAccessException ex ) {
// do not log because access may be denied via VM option '--illegal-access=deny'
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
// get system icon in default size 16x16
return fsv.getSystemIcon( file );
}
protected void directoryChanged( File file ) {
if( file != null ) {
String absolutePath = file.getAbsolutePath();
for( int i = 0; i < files.length; i++ ) {
// also compare path because otherwise selecting "Documents"
// in "Look in" combobox would not select "Documents" shortcut item
if( files[i].equals( file ) || files[i].getAbsolutePath().equals( absolutePath ) ) {
buttons[i].setSelected( true );
return;
}
}
}
buttonGroup.clearSelection();
}
@Override
public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
directoryChanged( fc.getCurrentDirectory() );
break;
}
}
}
//---- class ShortcutIcon -------------------------------------------------
private static class ShortcutIcon
implements Icon
{
private final Icon icon;
private final int iconWidth;
private final int iconHeight;
ShortcutIcon( Icon icon, int iconWidth, int iconHeight ) {
this.icon = icon;
this.iconWidth = iconWidth;
this.iconHeight = iconHeight;
}
@Override
public void paintIcon( Component c, Graphics g, int x, int y ) {
Graphics2D g2 = (Graphics2D) g.create();
try {
// set rendering hint for the case that the icon is a bitmap (not used for vector icons)
g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
double scale = (double) getIconWidth() / (double) icon.getIconWidth();
g2.translate( x, y );
g2.scale( scale, scale );
icon.paintIcon( c, g2, 0, 0 );
} finally {
g2.dispose();
}
}
@Override
public int getIconWidth() {
return UIScale.scale( iconWidth );
}
@Override
public int getIconHeight() {
return UIScale.scale( iconHeight );
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2022 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.ui;
import java.io.File;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.NativeLibrary;
import com.formdev.flatlaf.util.SystemInfo;
/**
* Helper class to load FlatLaf native library (.dll, .so or .dylib),
* if available for current operating system and CPU architecture.
*
* @author Karl Tauber
* @since 2.3
*/
class FlatNativeLibrary
{
private static NativeLibrary nativeLibrary;
/**
* Loads native library (if available) and returns whether loaded successfully.
* Returns {@code false} if no native library is available.
*/
static synchronized boolean isLoaded() {
initialize();
return (nativeLibrary != null) ? nativeLibrary.isLoaded() : false;
}
private static void initialize() {
if( nativeLibrary != null )
return;
String libraryName;
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
// Windows: requires Windows 10 (x86 or x86_64)
libraryName = "flatlaf-windows-x86";
if( SystemInfo.isX86_64 )
libraryName += "_64";
// load jawt native library
loadJAWT();
} else
return; // no native library available for current OS or CPU architecture
// load native library
nativeLibrary = createNativeLibrary( libraryName );
}
private static NativeLibrary createNativeLibrary( String libraryName ) {
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
if( libraryPath != null ) {
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
if( libraryFile.exists() )
return new NativeLibrary( libraryFile, true );
else
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
}
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
}
private static void loadJAWT() {
if( SystemInfo.isJava_9_orLater )
return;
// In Java 8, load jawt.dll (part of JRE) explicitly because it
// is not found when running application with <jdk>/bin/java.exe.
// When using <jdk>/jre/bin/java.exe, it is found.
// jawt.dll is located in <jdk>/jre/bin/.
// Java 9 and later do not have this problem.
try {
System.loadLibrary( "jawt" );
} catch( UnsatisfiedLinkError ex ) {
// log error only if native library jawt.dll not already loaded
String message = ex.getMessage();
if( message == null || !message.contains( "already loaded in another classloader" ) )
LoggingFacade.INSTANCE.logSevere( null, ex );
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
}
}

View File

@@ -80,6 +80,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault Table.intercellSpacing Dimension
* @uiDefault Table.selectionInactiveBackground Color
* @uiDefault Table.selectionInactiveForeground Color
* @uiDefault Table.paintOutsideAlternateRows boolean
*
* <!-- FlatTableCellBorder -->
*
@@ -95,7 +96,7 @@ import com.formdev.flatlaf.util.UIScale;
*/
public class FlatTableUI
extends BasicTableUI
implements StyleableUI
implements StyleableUI, FlatViewportUI.ViewportPainter
{
protected boolean showHorizontalLines;
protected boolean showVerticalLines;
@@ -421,4 +422,38 @@ public class FlatTableUI
? (viewport != rowHeader)
: (viewport == rowHeader || rowHeader == null);
}
/** @since 2.3 */
@Override
public void paintViewport( Graphics g, JComponent c, JViewport viewport ) {
int viewportWidth = viewport.getWidth();
int viewportHeight = viewport.getHeight();
// fill viewport background in same color as table background
if( viewport.isOpaque() ) {
g.setColor( table.getBackground() );
g.fillRect( 0, 0, viewportWidth, viewportHeight );
}
// paint alternating empty rows
boolean paintOutside = UIManager.getBoolean( "Table.paintOutsideAlternateRows" );
Color alternateColor;
if( paintOutside && (alternateColor = UIManager.getColor( "Table.alternateRowColor" )) != null ) {
g.setColor( alternateColor );
int rowCount = table.getRowCount();
// paint alternating empty rows below the table
int tableHeight = table.getHeight();
if( tableHeight < viewportHeight ) {
int tableWidth = table.getWidth();
int rowHeight = table.getRowHeight();
for( int y = tableHeight, row = rowCount; y < viewportHeight; y += rowHeight, row++ ) {
if( row % 2 != 0 )
g.fillRect( 0, y, tableWidth, rowHeight );
}
}
}
}
}

View File

@@ -22,10 +22,7 @@ import java.awt.Component;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.util.Map;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
@@ -51,15 +48,29 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault ToggleButton.iconTextGap int
* @uiDefault ToggleButton.startBackground Color optional; if set, a gradient paint is used and ToggleButton.background is ignored
* @uiDefault ToggleButton.endBackground Color optional; if set, a gradient paint is used
* @uiDefault ToggleButton.pressedBackground Color
* @uiDefault ToggleButton.focusedBackground Color optional
* @uiDefault ToggleButton.focusedForeground Color optional
* @uiDefault ToggleButton.hoverBackground Color optional
* @uiDefault ToggleButton.hoverForeground Color optional
* @uiDefault ToggleButton.pressedBackground Color optional
* @uiDefault ToggleButton.pressedForeground Color optional
* @uiDefault ToggleButton.selectedBackground Color
* @uiDefault ToggleButton.selectedForeground Color
* @uiDefault ToggleButton.disabledBackground Color optional
* @uiDefault ToggleButton.disabledText Color
* @uiDefault ToggleButton.disabledSelectedBackground Color
* @uiDefault ToggleButton.disabledSelectedForeground Color optional
* @uiDefault Button.paintShadow boolean default is false
* @uiDefault Button.shadowWidth int default is 2
* @uiDefault Button.shadowColor Color optional
* @uiDefault ToggleButton.toolbar.hoverBackground Color
* @uiDefault ToggleButton.toolbar.hoverForeground Color optional
* @uiDefault ToggleButton.toolbar.pressedBackground Color
* @uiDefault ToggleButton.toolbar.pressedForeground Color optional
* @uiDefault ToggleButton.toolbar.selectedBackground Color
* @uiDefault ToggleButton.toolbar.selectedForeground Color optional
* @uiDefault ToggleButton.toolbar.disabledSelectedBackground Color optional
* @uiDefault ToggleButton.toolbar.disabledSelectedForeground Color optional
*
* <!-- FlatToggleButtonUI -->
*
@@ -67,8 +78,11 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault ToggleButton.tab.underlineColor Color
* @uiDefault ToggleButton.tab.disabledUnderlineColor Color
* @uiDefault ToggleButton.tab.selectedBackground Color optional
* @uiDefault ToggleButton.tab.selectedForeground Color optional
* @uiDefault ToggleButton.tab.hoverBackground Color
* @uiDefault ToggleButton.tab.hoverForeground Color optional
* @uiDefault ToggleButton.tab.focusBackground Color
* @uiDefault ToggleButton.tab.focusForeground Color optional
*
*
* @author Karl Tauber
@@ -80,8 +94,11 @@ public class FlatToggleButtonUI
@Styleable(dot=true) protected Color tabUnderlineColor;
@Styleable(dot=true) protected Color tabDisabledUnderlineColor;
@Styleable(dot=true) protected Color tabSelectedBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color tabSelectedForeground;
@Styleable(dot=true) protected Color tabHoverBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color tabHoverForeground;
@Styleable(dot=true) protected Color tabFocusBackground;
/** @since 2.3 */ @Styleable(dot=true) protected Color tabFocusForeground;
private boolean defaults_initialized = false;
@@ -114,8 +131,11 @@ public class FlatToggleButtonUI
tabUnderlineColor = UIManager.getColor( "ToggleButton.tab.underlineColor" );
tabDisabledUnderlineColor = UIManager.getColor( "ToggleButton.tab.disabledUnderlineColor" );
tabSelectedBackground = UIManager.getColor( "ToggleButton.tab.selectedBackground" );
tabSelectedForeground = UIManager.getColor( "ToggleButton.tab.selectedForeground" );
tabHoverBackground = UIManager.getColor( "ToggleButton.tab.hoverBackground" );
tabHoverForeground = UIManager.getColor( "ToggleButton.tab.hoverForeground" );
tabFocusBackground = UIManager.getColor( "ToggleButton.tab.focusBackground" );
tabFocusForeground = UIManager.getColor( "ToggleButton.tab.focusForeground" );
defaults_initialized = true;
}
@@ -142,6 +162,7 @@ public class FlatToggleButtonUI
b.repaint();
break;
case TAB_BUTTON_UNDERLINE_PLACEMENT:
case TAB_BUTTON_UNDERLINE_HEIGHT:
case TAB_BUTTON_UNDERLINE_COLOR:
case TAB_BUTTON_SELECTED_BACKGROUND:
@@ -196,13 +217,42 @@ public class FlatToggleButtonUI
// paint underline if selected
if( selected ) {
int underlineHeight = UIScale.scale( clientPropertyInt( c, TAB_BUTTON_UNDERLINE_HEIGHT, tabUnderlineHeight ) );
int underlineThickness = UIScale.scale( clientPropertyInt( c, TAB_BUTTON_UNDERLINE_HEIGHT, tabUnderlineHeight ) );
g.setColor( c.isEnabled()
? clientPropertyColor( c, TAB_BUTTON_UNDERLINE_COLOR, tabUnderlineColor )
: tabDisabledUnderlineColor );
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
int placement = clientPropertyInt( c, TAB_BUTTON_UNDERLINE_PLACEMENT, SwingConstants.BOTTOM );
switch (placement) {
case SwingConstants.TOP:
g.fillRect( 0, 0, width, underlineThickness );
break;
case SwingConstants.LEFT:
g.fillRect( 0, 0, underlineThickness, height );
break;
case SwingConstants.RIGHT:
g.fillRect( width - underlineThickness, 0, underlineThickness, height );
break;
case SwingConstants.BOTTOM:
default:
g.fillRect( 0, height - underlineThickness, width, underlineThickness );
}
}
} else
super.paintBackground( g, c );
}
@Override
protected Color getForeground( JComponent c ) {
if( isTabButton( c ) ) {
if( !c.isEnabled() )
return disabledText;
if( tabSelectedForeground != null && ((AbstractButton)c).isSelected() )
return tabSelectedForeground;
return buttonStateColor( c, c.getForeground(), disabledText,
tabFocusForeground, tabHoverForeground, null );
} else
return super.getForeground( c );
}
}

View File

@@ -18,8 +18,8 @@ package com.formdev.flatlaf.ui;
import java.awt.Component;
import java.awt.Graphics;
import java.lang.reflect.Method;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicViewportUI;
@@ -43,15 +43,28 @@ public class FlatViewportUI
}
@Override
public void update( Graphics g, JComponent c ) {
Component view = ((JViewport)c).getView();
if( c.isOpaque() && view instanceof JTable ) {
// paint viewport background in same color as table background
g.setColor( view.getBackground() );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
public void paint( Graphics g, JComponent c ) {
super.paint( g, c );
paint( g, c );
} else
super.update( g, c );
Component view = ((JViewport)c).getView();
if( view instanceof JComponent ) {
try {
Method m = view.getClass().getMethod( "getUI" );
Object ui = m.invoke( view );
if( ui instanceof ViewportPainter )
((ViewportPainter)ui).paintViewport( g, (JComponent) view, (JViewport) c );
} catch( Exception ex ) {
// ignore
}
}
}
//---- interface ViewportPainter ------------------------------------------
/**
* @since 2.3
*/
public interface ViewportPainter {
void paintViewport( Graphics g, JComponent c, JViewport viewport );
}
}

View File

@@ -27,7 +27,6 @@ import java.awt.Window;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
@@ -38,9 +37,7 @@ import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.NativeLibrary;
import com.formdev.flatlaf.util.SystemInfo;
//
@@ -84,7 +81,6 @@ class FlatWindowsNativeWindowBorder
private Color colorizationColor;
private int colorizationColorBalance;
private static NativeLibrary nativeLibrary;
private static FlatWindowsNativeWindowBorder instance;
static FlatNativeWindowBorder.Provider getInstance() {
@@ -96,31 +92,8 @@ class FlatWindowsNativeWindowBorder
if( !SystemInfo.isX86 && !SystemInfo.isX86_64 )
return null;
// load native library
if( nativeLibrary == null ) {
if( !SystemInfo.isJava_9_orLater ) {
// In Java 8, load jawt.dll (part of JRE) explicitly because it
// is not found when running application with <jdk>/bin/java.exe.
// When using <jdk>/jre/bin/java.exe, it is found.
// jawt.dll is located in <jdk>/jre/bin/.
// Java 9 and later does not have this problem.
try {
System.loadLibrary( "jawt" );
} catch( UnsatisfiedLinkError ex ) {
// log error only if native library jawt.dll not already loaded
String message = ex.getMessage();
if( message == null || !message.contains( "already loaded in another classloader" ) )
LoggingFacade.INSTANCE.logSevere( null, ex );
} catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
}
nativeLibrary = createNativeLibrary();
}
// check whether native library was successfully loaded
if( !nativeLibrary.isLoaded() )
if( !FlatNativeLibrary.isLoaded() )
return null;
// create new instance
@@ -129,23 +102,6 @@ class FlatWindowsNativeWindowBorder
return instance;
}
private static NativeLibrary createNativeLibrary() {
String libraryName = "flatlaf-windows-x86";
if( SystemInfo.isX86_64 )
libraryName += "_64";
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
if( libraryPath != null ) {
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
if( libraryFile.exists() )
return new NativeLibrary( libraryFile, true );
else
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
}
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
}
private FlatWindowsNativeWindowBorder() {
}

View File

@@ -50,6 +50,7 @@ public class SystemInfo
public static final long javaVersion;
public static final boolean isJava_9_orLater;
public static final boolean isJava_11_orLater;
/** @since 2.3 */ public static final boolean isJava_12_orLater;
public static final boolean isJava_15_orLater;
/** @since 2 */ public static final boolean isJava_17_orLater;
/** @since 2 */ public static final boolean isJava_18_orLater;
@@ -66,6 +67,9 @@ public class SystemInfo
/** @since 1.1.2 */ public static final boolean isWebswing;
/** @since 1.1.1 */ public static final boolean isWinPE;
// features
/** @since 2.3 */ public static final boolean isMacFullWindowContentSupported;
static {
// platforms
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
@@ -92,6 +96,7 @@ public class SystemInfo
javaVersion = scanVersion( System.getProperty( "java.version" ) );
isJava_9_orLater = (javaVersion >= toVersion( 9, 0, 0, 0 ));
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
isJava_12_orLater = (javaVersion >= toVersion( 12, 0, 0, 0 ));
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
isJava_18_orLater = (javaVersion >= toVersion( 18, 0, 0, 0 ));
@@ -108,6 +113,12 @@ public class SystemInfo
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
isWebswing = (System.getProperty( "webswing.rootDir" ) != null);
isWinPE = isWindows && "X:\\Windows\\System32".equalsIgnoreCase( System.getProperty( "user.dir" ) );
// features
// available since Java 12; backported to Java 11.0.8 and 8u292
isMacFullWindowContentSupported =
javaVersion >= toVersion( 11, 0, 8, 0 ) ||
(javaVersion >= toVersion( 1, 8, 0, 292 ) && !isJava_9_orLater);
}
public static long scanVersion( String version ) {

View File

@@ -829,6 +829,7 @@ ToggleButton.tab.underlineHeight = 2
ToggleButton.tab.underlineColor = $TabbedPane.underlineColor
ToggleButton.tab.disabledUnderlineColor = $TabbedPane.disabledUnderlineColor
ToggleButton.tab.selectedBackground = $?TabbedPane.selectedBackground
ToggleButton.tab.selectedForeground = $?TabbedPane.selectedForeground
ToggleButton.tab.hoverBackground = $TabbedPane.hoverColor
ToggleButton.tab.focusBackground = $TabbedPane.focusColor

View File

@@ -201,6 +201,8 @@ ToggleButton.endBackground = $ToggleButton.background
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
[Monokai_Pro]TitledBorder.titleColor = @foreground
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10

View File

@@ -0,0 +1,65 @@
#
# 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.
#
#---- FileChooser ----
#fields
FileChooser.lookInLabel.textAndMnemonic = Buscar &en:
FileChooser.saveInLabelText = Guardar en:
FileChooser.fileNameLabel.textAndMnemonic = &Nombre de fichero:
FileChooser.folderNameLabel.textAndMnemonic = &Nombre de carpeta:
FileChooser.filesOfTypeLabel.textAndMnemonic = Ficheros de &Tipo:
# toolbar
FileChooser.upFolderToolTipText = Subir un nivel
FileChooser.upFolderAccessibleName = Subir
FileChooser.homeFolderToolTipText = Inicio
FileChooser.homeFolderAccessibleName = Inicio
FileChooser.newFolderToolTipText = Crear nueva carpeta
FileChooser.newFolderAccessibleName = Nueva carpeta
FileChooser.listViewButtonToolTipText = Lista
FileChooser.listViewButtonAccessibleName = Lista
FileChooser.detailsViewButtonToolTipText = Detalles
FileChooser.detailsViewButtonAccessibleName = Detalles
# details table header
FileChooser.fileNameHeaderText = Nombre
FileChooser.fileSizeHeaderText = Tama\u00F1o
FileChooser.fileTypeHeaderText = Tipo
FileChooser.fileDateHeaderText = Modificado
FileChooser.fileAttrHeaderText = Atributos
# popup menu
FileChooser.viewMenuLabelText = Ver
FileChooser.refreshActionLabelText = Refrescar
FileChooser.newFolderActionLabelText = Nueva carpeta
FileChooser.listViewActionLabelText = Lista
FileChooser.detailsViewActionLabelText = Detalles
#---- SplitPaneDivider ----
SplitPaneDivider.collapseLeftToolTipText = Contraer Panel Izquierdo
SplitPaneDivider.collapseRightToolTipText = Contraer panel Derecho
SplitPaneDivider.collapseTopToolTipText = Contraer panel Superior
SplitPaneDivider.collapseBottomToolTipText = Contraer Panel Inferior
SplitPaneDivider.expandLeftToolTipText = Expandir Panel Izquierdo
SplitPaneDivider.expandRightToolTipText = Expandir Panel Derecho
SplitPaneDivider.expandTopToolTipText = Expandir Panel Superior
SplitPaneDivider.expandBottomToolTipText = Expandir Panel Inferior
#---- TabbedPane ----
TabbedPane.moreTabsButtonToolTipText = Mostrar Pesta\u00F1as Ocultas

View File

@@ -96,19 +96,26 @@ public class TestFlatStyleableInfo
"minimumWidth", int.class,
"focusedBackground", Color.class,
"focusedForeground", Color.class,
"hoverBackground", Color.class,
"hoverForeground", Color.class,
"pressedBackground", Color.class,
"pressedForeground", Color.class,
"selectedBackground", Color.class,
"selectedForeground", Color.class,
"disabledBackground", Color.class,
"disabledText", Color.class,
"disabledSelectedBackground", Color.class,
"disabledSelectedForeground", Color.class,
"default.background", Color.class,
"default.foreground", Color.class,
"default.focusedBackground", Color.class,
"default.focusedForeground", Color.class,
"default.hoverBackground", Color.class,
"default.hoverForeground", Color.class,
"default.pressedBackground", Color.class,
"default.pressedForeground", Color.class,
"default.boldText", boolean.class,
"paintShadow", boolean.class,
@@ -118,8 +125,13 @@ public class TestFlatStyleableInfo
"toolbar.spacingInsets", Insets.class,
"toolbar.hoverBackground", Color.class,
"toolbar.hoverForeground", Color.class,
"toolbar.pressedBackground", Color.class,
"toolbar.pressedForeground", Color.class,
"toolbar.selectedBackground", Color.class,
"toolbar.selectedForeground", Color.class,
"toolbar.disabledSelectedBackground", Color.class,
"toolbar.disabledSelectedForeground", Color.class,
"buttonType", String.class,
"squareSize", boolean.class,
@@ -863,8 +875,11 @@ public class TestFlatStyleableInfo
"tab.underlineColor", Color.class,
"tab.disabledUnderlineColor", Color.class,
"tab.selectedBackground", Color.class,
"tab.selectedForeground", Color.class,
"tab.hoverBackground", Color.class,
"tab.focusBackground", Color.class
"tab.hoverForeground", Color.class,
"tab.focusBackground", Color.class,
"tab.focusForeground", Color.class
);
// FlatToggleButtonUI extends FlatButtonUI

View File

@@ -221,19 +221,26 @@ public class TestFlatStyling
ui.applyStyle( b, "minimumWidth: 100" );
ui.applyStyle( b, "focusedBackground: #fff" );
ui.applyStyle( b, "focusedForeground: #fff" );
ui.applyStyle( b, "hoverBackground: #fff" );
ui.applyStyle( b, "hoverForeground: #fff" );
ui.applyStyle( b, "pressedBackground: #fff" );
ui.applyStyle( b, "pressedForeground: #fff" );
ui.applyStyle( b, "selectedBackground: #fff" );
ui.applyStyle( b, "selectedForeground: #fff" );
ui.applyStyle( b, "disabledBackground: #fff" );
ui.applyStyle( b, "disabledText: #fff" );
ui.applyStyle( b, "disabledSelectedBackground: #fff" );
ui.applyStyle( b, "disabledSelectedForeground: #fff" );
ui.applyStyle( b, "default.background: #fff" );
ui.applyStyle( b, "default.foreground: #fff" );
ui.applyStyle( b, "default.focusedBackground: #fff" );
ui.applyStyle( b, "default.focusedForeground: #fff" );
ui.applyStyle( b, "default.hoverBackground: #fff" );
ui.applyStyle( b, "default.hoverForeground: #fff" );
ui.applyStyle( b, "default.pressedBackground: #fff" );
ui.applyStyle( b, "default.pressedForeground: #fff" );
ui.applyStyle( b, "default.boldText: true" );
ui.applyStyle( b, "paintShadow: true" );
@@ -243,8 +250,13 @@ public class TestFlatStyling
ui.applyStyle( b, "toolbar.spacingInsets: 1,2,3,4" );
ui.applyStyle( b, "toolbar.hoverBackground: #fff" );
ui.applyStyle( b, "toolbar.hoverForeground: #fff" );
ui.applyStyle( b, "toolbar.pressedBackground: #fff" );
ui.applyStyle( b, "toolbar.pressedForeground: #fff" );
ui.applyStyle( b, "toolbar.selectedBackground: #fff" );
ui.applyStyle( b, "toolbar.selectedForeground: #fff" );
ui.applyStyle( b, "toolbar.disabledSelectedBackground: #fff" );
ui.applyStyle( b, "toolbar.disabledSelectedForeground: #fff" );
ui.applyStyle( b, "buttonType: help" );
ui.applyStyle( b, "squareSize: true" );
@@ -1073,8 +1085,11 @@ public class TestFlatStyling
ui.applyStyle( b, "tab.underlineColor: #fff" );
ui.applyStyle( b, "tab.disabledUnderlineColor: #fff" );
ui.applyStyle( b, "tab.selectedBackground: #fff" );
ui.applyStyle( b, "tab.selectedForeground: #fff" );
ui.applyStyle( b, "tab.hoverBackground: #fff" );
ui.applyStyle( b, "tab.hoverForeground: #fff" );
ui.applyStyle( b, "tab.focusBackground: #fff" );
ui.applyStyle( b, "tab.focusForeground: #fff" );
}
@Test

View File

@@ -38,8 +38,8 @@ import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.demo.HintManager.Hint;
import com.formdev.flatlaf.demo.extras.*;
import com.formdev.flatlaf.demo.intellijthemes.*;
import com.formdev.flatlaf.extras.FlatDesktop;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.formdev.flatlaf.extras.FlatDesktop;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.extras.components.FlatButton;
@@ -82,13 +82,33 @@ class DemoFrame
if( tabIndex >= 0 && tabIndex < tabbedPane.getTabCount() && tabIndex != tabbedPane.getSelectedIndex() )
tabbedPane.setSelectedIndex( tabIndex );
// hide some menu items on macOS
// macOS (see https://www.formdev.com/flatlaf/macos/)
if( SystemInfo.isMacOS ) {
// hide menu items that are in macOS application menu
exitMenuItem.setVisible( false );
aboutMenuItem.setVisible( false );
// do not use HTML text on macOS
// do not use HTML text in menu items because this is not supported in macOS screen menu
htmlMenuItem.setText( "some text" );
if( SystemInfo.isMacFullWindowContentSupported ) {
// expand window content into window title bar and make title bar transparent
getRootPane().putClientProperty( "apple.awt.fullWindowContent", true );
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", true );
// hide window title
if( SystemInfo.isJava_17_orLater )
getRootPane().putClientProperty( "apple.awt.windowTitleVisible", false );
else
setTitle( null );
// add gap to left side of toolbar
toolBar.add( Box.createHorizontalStrut( 70 ), 0 );
}
// enable full screen mode for this window (for Java 8 - 10; not necessary for Java 11+)
if( !SystemInfo.isJava_11_orLater )
getRootPane().putClientProperty( "apple.awt.fullscreenable", true );
}
// integrate into macOS screen menu
@@ -433,9 +453,9 @@ class DemoFrame
lafClass == FlatIntelliJLaf.class ||
lafClass == FlatDarculaLaf.class;
accentColorLabel.setEnabled( isAccentColorSupported );
accentColorLabel.setVisible( isAccentColorSupported );
for( int i = 0; i < accentColorButtons.length; i++ )
accentColorButtons[i].setEnabled( isAccentColorSupported );
accentColorButtons[i].setVisible( isAccentColorSupported );
}
private void initComponents() {

View File

@@ -36,7 +36,7 @@ public class FlatLafDemo
static boolean screenshotsMode = Boolean.parseBoolean( System.getProperty( "flatlaf.demo.screenshotsMode" ) );
public static void main( String[] args ) {
// macOS
// macOS (see https://www.formdev.com/flatlaf/macos/)
if( SystemInfo.isMacOS ) {
// enable screen menu bar
// (moves menu bar from JFrame window to top of screen)
@@ -51,6 +51,7 @@ public class FlatLafDemo
// - "system": use current macOS appearance (light or dark)
// - "NSAppearanceNameAqua": use light appearance
// - "NSAppearanceNameDarkAqua": use dark appearance
// (needs to be set on main thread; setting it on AWT thread does not work)
System.setProperty( "apple.awt.application.appearance", "system" );
}

View File

@@ -18,7 +18,7 @@ package com.formdev.flatlaf.extras.components;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.Color;
import javax.swing.JToggleButton;
import javax.swing.*;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
/**
@@ -116,16 +116,37 @@ public class FlatToggleButton
putClientProperty( OUTLINE, outline );
}
/**
* Returns placement of underline if toggle button type is {@link ButtonType#tab}.
* If underline placement is not specified, returns {@link #BOTTOM} as the default
* value.
*
* @since 2.3
*/
public int getTabUnderlinePlacement() {
return getClientPropertyInt( TAB_BUTTON_UNDERLINE_PLACEMENT, BOTTOM );
}
/**
* Returns height of underline if toggle button type is {@link ButtonType#tab}.
* Specifies placement of underline if toggle button type is {@link ButtonType#tab}.
*
* @param placement One of the following constants defined in SwingConstants:
* {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, or {@link #RIGHT}.
* @since 2.3
*/
public void setTabUnderlinePlacement( int placement ) {
putClientProperty( TAB_BUTTON_UNDERLINE_PLACEMENT, (placement >= 0) ? placement : null );
}
/**
* Returns thickness of underline if toggle button type is {@link ButtonType#tab}.
*/
public int getTabUnderlineHeight() {
return getClientPropertyInt( TAB_BUTTON_UNDERLINE_HEIGHT, "ToggleButton.tab.underlineHeight" );
}
/**
* Specifies height of underline if toggle button type is {@link ButtonType#tab}.
* Specifies thickness of underline if toggle button type is {@link ButtonType#tab}.
*/
public void setTabUnderlineHeight( int tabUnderlineHeight ) {
putClientProperty( TAB_BUTTON_UNDERLINE_HEIGHT, (tabUnderlineHeight >= 0) ? tabUnderlineHeight : null );

View File

@@ -73,43 +73,57 @@ Button.default.endBorderColor #0000ff HSL 240 100 50 javax.swing.plaf.Colo
Button.default.focusColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.focusedBackground #00ffff HSL 180 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.focusedBorderColor #537699 HSL 210 30 46 javax.swing.plaf.ColorUIResource [UI]
Button.default.focusedForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.foreground #880000 HSL 0 100 27 javax.swing.plaf.ColorUIResource [UI]
Button.default.hoverBackground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.hoverBorderColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.hoverForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.pressedBackground #ffc800 HSL 47 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.pressedForeground #0080ff HSL 210 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.default.startBackground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
Button.default.startBorderColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.defaultButtonFollowsFocus false
Button.disabledBackground #e0e0e0 HSL 0 0 88 javax.swing.plaf.ColorUIResource [UI]
Button.disabledBorderColor #000088 HSL 240 100 27 javax.swing.plaf.ColorUIResource [UI]
Button.disabledForeground #000088 HSL 240 100 27 javax.swing.plaf.ColorUIResource [UI]
Button.disabledSelectedBackground #112233 HSL 210 50 13 javax.swing.plaf.ColorUIResource [UI]
Button.disabledSelectedForeground #ffcccc HSL 0 100 90 javax.swing.plaf.ColorUIResource [UI]
Button.disabledText #000088 HSL 240 100 27 javax.swing.plaf.ColorUIResource [UI]
Button.endBackground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
Button.endBorderColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.focusedBackground #00ffff HSL 180 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.focusedBorderColor #466d94 HSL 210 36 43 javax.swing.plaf.ColorUIResource [UI]
Button.focusedForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.font [active] $defaultFont [UI]
Button.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.highlight #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Button.hoverBackground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.hoverBorderColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.hoverForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.iconTextGap 4
Button.innerFocusWidth 1
Button.light #e3e3e3 HSL 0 0 89 javax.swing.plaf.ColorUIResource [UI]
Button.margin 2,14,2,14 javax.swing.plaf.InsetsUIResource [UI]
Button.minimumWidth 72
Button.pressedBackground #ffc800 HSL 47 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.pressedForeground #0080ff HSL 210 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.rollover true
Button.selectedBackground #ffbbbb HSL 0 100 87 javax.swing.plaf.ColorUIResource [UI]
Button.selectedForeground #332211 HSL 30 50 13 javax.swing.plaf.ColorUIResource [UI]
Button.shadow #a0a0a0 HSL 0 0 63 javax.swing.plaf.ColorUIResource [UI]
Button.startBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Button.startBorderColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
Button.textIconGap 4
Button.textShiftOffset 0
Button.toolbar.disabledSelectedBackground #cccccc HSL 0 0 80 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.disabledSelectedForeground #886666 HSL 0 14 47 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.hoverBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.hoverForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.margin 3,3,3,3 javax.swing.plaf.InsetsUIResource [UI]
Button.toolbar.pressedBackground #eeeeee HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.pressedForeground #666666 HSL 0 0 40 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.selectedBackground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.selectedForeground #880000 HSL 0 100 27 javax.swing.plaf.ColorUIResource [UI]
Button.toolbar.spacingInsets 1,2,1,2 javax.swing.plaf.InsetsUIResource [UI]
ButtonUI com.formdev.flatlaf.ui.FlatButtonUI
@@ -1280,31 +1294,43 @@ ToggleButton.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.F
ToggleButton.darkShadow #696969 HSL 0 0 41 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.disabledBackground #e0e0e0 HSL 0 0 88 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.disabledSelectedBackground #44dd44 HSL 120 69 57 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.disabledSelectedForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.disabledText #000088 HSL 240 100 27 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.focusedBackground #00ffff HSL 180 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.focusedForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.font [active] $defaultFont [UI]
ToggleButton.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.highlight #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.hoverBackground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.hoverForeground #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.iconTextGap 4
ToggleButton.light #e3e3e3 HSL 0 0 89 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.margin 2,14,2,14 javax.swing.plaf.InsetsUIResource [UI]
ToggleButton.pressedBackground #ffc800 HSL 47 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.pressedForeground #0080ff HSL 210 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.rollover true
ToggleButton.selectedBackground #44ff44 HSL 120 100 63 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.selectedForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.shadow #a0a0a0 HSL 0 0 63 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.disabledUnderlineColor #7a7a7a HSL 0 0 48 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.focusBackground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.focusForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.hoverBackground #eeeeee HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.selectedBackground #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.hoverForeground #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.selectedBackground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.selectedForeground #00aaff HSL 200 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.underlineColor #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.tab.underlineHeight 2
ToggleButton.textIconGap 4
ToggleButton.textShiftOffset 0
ToggleButton.toolbar.disabledSelectedBackground #cccccc HSL 0 0 80 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.disabledSelectedForeground #886666 HSL 0 14 47 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.hoverBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.hoverForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.pressedBackground #eeeeee HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.pressedForeground #666666 HSL 0 0 40 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.selectedBackground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
ToggleButton.toolbar.selectedForeground #880000 HSL 0 100 27 javax.swing.plaf.ColorUIResource [UI]
ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI

View File

@@ -16,7 +16,12 @@
package com.formdev.flatlaf.testing;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Function;
import javax.swing.*;
import com.formdev.flatlaf.icons.FlatFileChooserHomeFolderIcon;
import net.miginfocom.swing.*;
/**
@@ -28,6 +33,24 @@ public class FlatChooserTest
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
UIManager.put( "FileChooser.shortcuts.filesFunction", (Function<File[], File[]>) files -> {
ArrayList<File> list = new ArrayList<>( Arrays.asList( files ) );
list.add( 0, new File( System.getProperty( "user.home" ) ) );
return list.toArray( new File[list.size()] );
} );
UIManager.put( "FileChooser.shortcuts.displayNameFunction", (Function<File, String>) file -> {
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
return "Home";
return null;
} );
UIManager.put( "FileChooser.shortcuts.iconFunction", (Function<File, Icon>) file -> {
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
return new FlatFileChooserHomeFolderIcon();
return null;
} );
frame.showFrame( FlatChooserTest::new );
} );
}

View File

@@ -336,6 +336,16 @@ public class FlatComponents2Test
table.setSurrendersFocusOnKeystroke( focusCellEditorCheckBox.isSelected() );
}
private void alternatingRowsChanged() {
UIManager.put( "Table.alternateRowColor", alternatingRowsCheckBox.isSelected() ? Color.orange : null );
table1ScrollPane.repaint();
}
private void paintOutsideAlternateRowsChanged() {
UIManager.put( "Table.paintOutsideAlternateRows", paintOutsideAlternateRowsCheckBox.isSelected() ? true : null );
table1ScrollPane.repaint();
}
private void treeRendererChanged() {
Object sel = treeRendererComboBox.getSelectedItem();
if( !(sel instanceof String) )
@@ -493,8 +503,10 @@ public class FlatComponents2Test
focusCellEditorCheckBox = new JCheckBox();
showVerticalLinesCheckBox = new JCheckBox();
columnSelectionCheckBox = new JCheckBox();
alternatingRowsCheckBox = new JCheckBox();
intercellSpacingCheckBox = new JCheckBox();
rowHeaderCheckBox = new JCheckBox();
paintOutsideAlternateRowsCheckBox = new JCheckBox();
redGridColorCheckBox = new JCheckBox();
tableHeaderButtonCheckBox = new JCheckBox();
@@ -875,6 +887,11 @@ public class FlatComponents2Test
columnSelectionCheckBox.addActionListener(e -> columnSelectionChanged());
tableOptionsPanel.add(columnSelectionCheckBox, "cell 1 2");
//---- alternatingRowsCheckBox ----
alternatingRowsCheckBox.setText("alternating rows");
alternatingRowsCheckBox.addActionListener(e -> alternatingRowsChanged());
tableOptionsPanel.add(alternatingRowsCheckBox, "cell 2 2");
//---- intercellSpacingCheckBox ----
intercellSpacingCheckBox.setText("intercell spacing");
intercellSpacingCheckBox.addActionListener(e -> intercellSpacingChanged());
@@ -885,6 +902,11 @@ public class FlatComponents2Test
rowHeaderCheckBox.addActionListener(e -> rowHeaderChanged());
tableOptionsPanel.add(rowHeaderCheckBox, "cell 1 3");
//---- paintOutsideAlternateRowsCheckBox ----
paintOutsideAlternateRowsCheckBox.setText("outside alternating rows");
paintOutsideAlternateRowsCheckBox.addActionListener(e -> paintOutsideAlternateRowsChanged());
tableOptionsPanel.add(paintOutsideAlternateRowsCheckBox, "cell 2 3");
//---- redGridColorCheckBox ----
redGridColorCheckBox.setText("red grid color");
redGridColorCheckBox.addActionListener(e -> redGridColorChanged());
@@ -927,8 +949,10 @@ public class FlatComponents2Test
private JCheckBox focusCellEditorCheckBox;
private JCheckBox showVerticalLinesCheckBox;
private JCheckBox columnSelectionCheckBox;
private JCheckBox alternatingRowsCheckBox;
private JCheckBox intercellSpacingCheckBox;
private JCheckBox rowHeaderCheckBox;
private JCheckBox paintOutsideAlternateRowsCheckBox;
private JCheckBox redGridColorCheckBox;
private JCheckBox tableHeaderButtonCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.5.0.404" Java: "17.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -485,6 +485,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "alternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "alternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "intercellSpacingCheckBox"
"text": "intercell spacing"
@@ -505,6 +515,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "paintOutsideAlternateRowsCheckBox"
"text": "outside alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "paintOutsideAlternateRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "redGridColorCheckBox"
"text": "red grid color"

View File

@@ -78,9 +78,15 @@ controlDkShadow = #696969
Button.startBackground = #fff
Button.endBackground = #bbb
Button.focusedBackground = #0ff
Button.focusedForeground = #00f
Button.hoverBackground = #ff0
Button.hoverForeground = #00f
Button.pressedBackground = #FFC800
Button.pressedForeground = #0080ff
Button.selectedBackground = #fbb
Button.selectedForeground = #321
Button.disabledSelectedBackground = #123
Button.disabledSelectedForeground = #fcc
Button.borderColor = #0f0
Button.startBorderColor = #00f
@@ -95,8 +101,11 @@ Button.default.startBackground = #ddd
Button.default.endBackground = #888
Button.default.foreground = #800
Button.default.focusedBackground = #0ff
Button.default.focusedForeground = #00f
Button.default.hoverBackground = #ff0
Button.default.hoverForeground = #00f
Button.default.pressedBackground = #FFC800
Button.default.pressedForeground = #0080ff
Button.default.startBorderColor = #f00
Button.default.endBorderColor = #00f
Button.default.hoverBorderColor = #f00
@@ -104,8 +113,13 @@ Button.default.focusedBorderColor = #537699
Button.default.focusColor = #f00
Button.toolbar.hoverBackground = #fff
Button.toolbar.hoverForeground = #000
Button.toolbar.pressedBackground = #eee
Button.toolbar.pressedForeground = #666
Button.toolbar.selectedBackground = #ddd
Button.toolbar.selectedForeground = #800
Button.toolbar.disabledSelectedBackground = #ccc
Button.toolbar.disabledSelectedForeground = #866
#---- CheckBox ----
@@ -422,12 +436,28 @@ ToggleButton.background = #ddf
ToggleButton.selectedBackground = #4f4
ToggleButton.selectedForeground = #000
ToggleButton.disabledSelectedBackground = #4d4
ToggleButton.disabledSelectedForeground = #fff
ToggleButton.focusedBackground = #0ff
ToggleButton.focusedForeground = #00f
ToggleButton.hoverBackground = #ff0
ToggleButton.hoverForeground = #00f
ToggleButton.pressedBackground = #FFC800
ToggleButton.pressedForeground = #0080ff
ToggleButton.toolbar.hoverBackground = #fff
ToggleButton.toolbar.hoverForeground = #000
ToggleButton.toolbar.pressedBackground = #eee
ToggleButton.toolbar.pressedForeground = #666
ToggleButton.toolbar.selectedBackground = #ddd
ToggleButton.toolbar.selectedForeground = #800
ToggleButton.toolbar.disabledSelectedBackground = #ccc
ToggleButton.toolbar.disabledSelectedForeground = #866
ToggleButton.tab.selectedBackground = #080
ToggleButton.tab.selectedForeground = #fff
ToggleButton.tab.hoverForeground = #00f
ToggleButton.tab.focusForeground = #080
#---- ToolBar ----

View File

@@ -482,6 +482,10 @@ class FlatCompletionProvider
"dark", colorParamDesc,
"light", colorParamDesc,
"threshold", "(optional) 0-100%, default is 43%" );
addFunction( "over",
"foreground", colorParamDesc,
"background", colorParamDesc );
}
private void addFunction( String name, String... paramNamesAndDescs ) {

View File

@@ -26,7 +26,7 @@ import com.formdev.flatlaf.util.SystemInfo;
public class FlatLafThemeEditor
{
public static void main( String[] args ) {
// macOS
// macOS (see https://www.formdev.com/flatlaf/macos/)
if( SystemInfo.isMacOS ) {
// enable screen menu bar
// (moves menu bar from JFrame window to top of screen)
@@ -41,6 +41,7 @@ public class FlatLafThemeEditor
// - "system": use current macOS appearance (light or dark)
// - "NSAppearanceNameAqua": use light appearance
// - "NSAppearanceNameDarkAqua": use dark appearance
// (needs to be set on main thread; setting it on AWT thread does not work)
System.setProperty( "apple.awt.application.appearance", "system" );
}

View File

@@ -173,10 +173,30 @@ class FlatThemeFileEditor
enableDisableActions();
// hide some menu items on macOS
// macOS (see https://www.formdev.com/flatlaf/macos/)
if( SystemInfo.isMacOS ) {
// hide menu items that are in macOS application menu
exitMenuItem.setVisible( false );
aboutMenuItem.setVisible( false );
if( SystemInfo.isMacFullWindowContentSupported ) {
// expand window content into window title bar and make title bar transparent
getRootPane().putClientProperty( "apple.awt.fullWindowContent", true );
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", true );
// hide window title
if( SystemInfo.isJava_17_orLater )
getRootPane().putClientProperty( "apple.awt.windowTitleVisible", false );
else
setTitle( null );
// add gap to left side of toolbar
controlPanel.add( Box.createHorizontalStrut( 70 ), 0 );
}
// enable full screen mode for this window (for Java 8 - 10; not necessary for Java 11+)
if( !SystemInfo.isJava_11_orLater )
getRootPane().putClientProperty( "apple.awt.fullscreenable", true );
}
// integrate into macOS screen menu
@@ -365,7 +385,17 @@ class FlatThemeFileEditor
String n2 = toSortName( f2.getName() );
return n1.compareToIgnoreCase( n2 );
} );
return propertiesFiles;
File themesDir = new File( dir, "themes" );
if( !themesDir.isDirectory() )
return propertiesFiles;
// get files from "themes" sub-directory
File[] themesFiles = getPropertiesFiles( themesDir );
File[] allFiles = new File[propertiesFiles.length + themesFiles.length];
System.arraycopy( propertiesFiles, 0, allFiles, 0, propertiesFiles.length );
System.arraycopy( themesFiles, 0, allFiles, propertiesFiles.length, themesFiles.length );
return allFiles;
}
private String toSortName( String name ) {
@@ -450,12 +480,21 @@ class FlatThemeFileEditor
FlatIntelliJLaf.NAME,
FlatDarculaLaf.NAME,
} );
JCheckBox genJavaClassCheckBox = new JCheckBox( "Generate Java class" );
genJavaClassCheckBox.setMnemonic( 'G' );
File themesDir = new File( dir, "themes" );
JCheckBox useThemesDirCheckBox = themesDir.isDirectory()
? new JCheckBox( "Create in 'themes' directory", true )
: null;
JOptionPane optionPane = new JOptionPane( new Object[] {
new JLabel( "Theme name:" ),
themeNameField,
new JLabel( "Base Theme:" ),
baseThemeField,
genJavaClassCheckBox,
useThemesDirCheckBox,
}, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION ) {
@Override
public void selectInitialValue() {
@@ -477,7 +516,8 @@ class FlatThemeFileEditor
return;
}
File file = new File( dir, themeName + ".properties" );
File dir2 = (useThemesDirCheckBox != null && useThemesDirCheckBox.isSelected()) ? themesDir : dir;
File file = new File( dir2, themeName + ".properties" );
if( file.exists() ) {
JOptionPane.showMessageDialog( this, "Theme '" + themeName + "' already exists.", title, JOptionPane.INFORMATION_MESSAGE );
return;
@@ -486,7 +526,8 @@ class FlatThemeFileEditor
try {
String baseTheme = (String) baseThemeField.getSelectedItem();
createTheme( file, baseTheme );
createThemeClass( dir, themeName, baseTheme );
if( genJavaClassCheckBox.isSelected() )
createThemeClass( dir2, themeName, baseTheme );
openFile( file, true );
} catch( IOException ex ) {
ex.printStackTrace();

View File

@@ -76,6 +76,7 @@ public class FlatThemeTokenMaker
tokenMap.put( "tint", TOKEN_FUNCTION );
tokenMap.put( "shade", TOKEN_FUNCTION );
tokenMap.put( "contrast", TOKEN_FUNCTION );
tokenMap.put( "over", TOKEN_FUNCTION );
// function options
tokenMap.put( "relative", Token.RESERVED_WORD );

View File

@@ -23,10 +23,13 @@ Button.default.endBorderColor
Button.default.focusColor
Button.default.focusedBackground
Button.default.focusedBorderColor
Button.default.focusedForeground
Button.default.foreground
Button.default.hoverBackground
Button.default.hoverBorderColor
Button.default.hoverForeground
Button.default.pressedBackground
Button.default.pressedForeground
Button.default.startBackground
Button.default.startBorderColor
Button.defaultButtonFollowsFocus
@@ -34,23 +37,27 @@ Button.disabledBackground
Button.disabledBorderColor
Button.disabledForeground
Button.disabledSelectedBackground
Button.disabledSelectedForeground
Button.disabledText
Button.endBackground
Button.endBorderColor
Button.focusInputMap
Button.focusedBackground
Button.focusedBorderColor
Button.focusedForeground
Button.font
Button.foreground
Button.highlight
Button.hoverBackground
Button.hoverBorderColor
Button.hoverForeground
Button.iconTextGap
Button.innerFocusWidth
Button.light
Button.margin
Button.minimumWidth
Button.pressedBackground
Button.pressedForeground
Button.rollover
Button.selectedBackground
Button.selectedForeground
@@ -59,10 +66,15 @@ Button.startBackground
Button.startBorderColor
Button.textIconGap
Button.textShiftOffset
Button.toolbar.disabledSelectedBackground
Button.toolbar.disabledSelectedForeground
Button.toolbar.hoverBackground
Button.toolbar.hoverForeground
Button.toolbar.margin
Button.toolbar.pressedBackground
Button.toolbar.pressedForeground
Button.toolbar.selectedBackground
Button.toolbar.selectedForeground
Button.toolbar.spacingInsets
ButtonUI
Caret.width
@@ -185,6 +197,7 @@ ComboBox.buttonShadow
ComboBox.buttonStyle
ComboBox.disabledBackground
ComboBox.disabledForeground
ComboBox.editableBackground
ComboBox.editorColumns
ComboBox.focusedBackground
ComboBox.font
@@ -252,6 +265,8 @@ FileChooser.homeFolderIcon
FileChooser.listViewIcon
FileChooser.newFolderIcon
FileChooser.readOnly
FileChooser.shortcuts.buttonSize
FileChooser.shortcuts.iconSize
FileChooser.upFolderIcon
FileChooser.useSystemExtensionHiding
FileChooser.usesSingleFilePane
@@ -714,6 +729,7 @@ Separator.stripeIndent
Separator.stripeWidth
SeparatorUI
Slider.background
Slider.disabledThumbBorderColor
Slider.disabledThumbColor
Slider.disabledTrackColor
Slider.focus
@@ -999,32 +1015,44 @@ ToggleButton.border
ToggleButton.darkShadow
ToggleButton.disabledBackground
ToggleButton.disabledSelectedBackground
ToggleButton.disabledSelectedForeground
ToggleButton.disabledText
ToggleButton.focusInputMap
ToggleButton.focusedBackground
ToggleButton.focusedForeground
ToggleButton.font
ToggleButton.foreground
ToggleButton.highlight
ToggleButton.hoverBackground
ToggleButton.hoverForeground
ToggleButton.iconTextGap
ToggleButton.light
ToggleButton.margin
ToggleButton.pressedBackground
ToggleButton.pressedForeground
ToggleButton.rollover
ToggleButton.selectedBackground
ToggleButton.selectedForeground
ToggleButton.shadow
ToggleButton.tab.disabledUnderlineColor
ToggleButton.tab.focusBackground
ToggleButton.tab.focusForeground
ToggleButton.tab.hoverBackground
ToggleButton.tab.hoverForeground
ToggleButton.tab.selectedBackground
ToggleButton.tab.selectedForeground
ToggleButton.tab.underlineColor
ToggleButton.tab.underlineHeight
ToggleButton.textIconGap
ToggleButton.textShiftOffset
ToggleButton.toolbar.disabledSelectedBackground
ToggleButton.toolbar.disabledSelectedForeground
ToggleButton.toolbar.hoverBackground
ToggleButton.toolbar.hoverForeground
ToggleButton.toolbar.pressedBackground
ToggleButton.toolbar.pressedForeground
ToggleButton.toolbar.selectedBackground
ToggleButton.toolbar.selectedForeground
ToggleButtonUI
ToolBar.ancestorInputMap
ToolBar.arrowKeysOnlyNavigation

View File

@@ -118,6 +118,12 @@ Prop.6.selectionForeground = contrast($Prop.6.selectionBackground,#000,#fff)
Prop.7.selectionBackground = #FF9500
Prop.7.selectionForeground = contrast($Prop.7.selectionBackground,#000,#fff)
Prop.colorFunc60 = over(#fff8,#f00)
Prop.colorFunc61 = over(#fff8,#0f0)
Prop.colorFunc62 = over(#f000,#0f0)
Prop.colorFunc63 = over(#f00,#0f0)
Prop.colorFunc64 = over(#f008,null)
@varStyle1 = #f0f