Demo: support using own FlatLaf themes (.properties files) that are located in working directory of Demo application

This commit is contained in:
Karl Tauber
2020-03-29 18:02:35 +02:00
parent 1bebfe9cf2
commit 5ed40cab1d
8 changed files with 159 additions and 32 deletions

View File

@@ -0,0 +1,13 @@
# This file demonstrates using a FlatLaf theme file in the FlatLaf Demo application.
# Must be in the working directory of the Demo application.
# Shown in the "Themes" list under category "Current Directory".
#
# Modifications to this file are automatically loaded by the FlatLaf Demo application
# when the Demo window is activated.
# base theme (light, dark, intellij or darcula)
@baseTheme=light
# add you theme defaults here
@background=#ccc

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.demo;
import java.io.File;
import java.io.FileInputStream;
import java.util.prefs.Preferences;
import javax.swing.UIManager;
@@ -23,6 +24,8 @@ import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel.PropertiesLaf;
import com.formdev.flatlaf.util.StringUtils;
/**
* @author Karl Tauber
@@ -30,12 +33,12 @@ import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
public class DemoPrefs
{
public static final String KEY_LAF = "laf";
public static final String KEY_LAF_INTELLIJ_THEME = "lafIntelliJTheme";
public static final String KEY_LAF_THEME = "lafTheme";
public static final String RESOURCE_PREFIX = "res:";
public static final String FILE_PREFIX = "file:";
public static final String INTELLIJ_THEME_UI_KEY = "__FlatLaf.demo.intelliJTheme";
public static final String THEME_UI_KEY = "__FlatLaf.demo.theme";
private static Preferences state;
@@ -55,16 +58,27 @@ public class DemoPrefs
else {
String lafClassName = state.get( KEY_LAF, FlatLightLaf.class.getName() );
if( IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) {
String intelliJTheme = state.get( KEY_LAF_INTELLIJ_THEME, "" );
if( intelliJTheme.startsWith( RESOURCE_PREFIX ) )
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( intelliJTheme.substring( RESOURCE_PREFIX.length() ) ) );
else if( intelliJTheme.startsWith( FILE_PREFIX ) )
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( intelliJTheme.substring( FILE_PREFIX.length() ) ) ) );
String theme = state.get( KEY_LAF_THEME, "" );
if( theme.startsWith( RESOURCE_PREFIX ) )
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( theme.substring( RESOURCE_PREFIX.length() ) ) );
else if( theme.startsWith( FILE_PREFIX ) )
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( theme.substring( FILE_PREFIX.length() ) ) ) );
else
FlatLightLaf.install();
if( !intelliJTheme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( INTELLIJ_THEME_UI_KEY, intelliJTheme );
if( !theme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
} else if( IJThemesPanel.PropertiesLaf.class.getName().equals( lafClassName ) ) {
String theme = state.get( KEY_LAF_THEME, "" );
if( theme.startsWith( FILE_PREFIX ) ) {
File themeFile = new File( theme.substring( FILE_PREFIX.length() ) );
String themeName = StringUtils.removeTrailing( themeFile.getName(), ".properties" );
FlatLaf.install( new PropertiesLaf( themeName, themeFile ) );
} else
FlatLightLaf.install();
if( !theme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
} else
UIManager.setLookAndFeel( lafClassName );
}

View File

@@ -68,7 +68,9 @@ class IJThemesManager
// get current working directory
File directory = new File( "" ).getAbsoluteFile();
File[] themeFiles = directory.listFiles( (dir, name) -> name.endsWith( ".theme.json" ) );
File[] themeFiles = directory.listFiles( (dir, name) -> {
return name.endsWith( ".theme.json" ) || name.endsWith( ".properties" );
} );
if( themeFiles == null )
return;
@@ -77,7 +79,10 @@ class IJThemesManager
moreThemes.clear();
for( File f : themeFiles ) {
String name = StringUtils.removeTrailing( f.getName(), ".theme.json" );
String fname = f.getName();
String name = fname.endsWith( ".properties" )
? StringUtils.removeTrailing( fname, ".properties" )
: StringUtils.removeTrailing( fname, ".theme.json" );
moreThemes.add( new IJThemeInfo( name, null, null, null, null, null, f, null ) );
lastModifiedMap.put( f, f.lastModified() );
}

View File

@@ -28,6 +28,7 @@ import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
@@ -37,6 +38,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Predicate;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
@@ -71,6 +73,7 @@ public class IJThemesPanel
private Window window;
private File lastDirectory;
private boolean isAdjustingThemesList;
public IJThemesPanel() {
initComponents();
@@ -134,6 +137,10 @@ public class IJThemesPanel
themes.add( new IJThemeInfo( "Flat IntelliJ", null, null, null, null, null, null, FlatIntelliJLaf.class.getName() ) );
themes.add( new IJThemeInfo( "Flat Darcula", null, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
// add themes from directory
categories.put( themes.size(), "Current Directory" );
themes.addAll( themesManager.moreThemes );
// add uncategorized bundled themes
categories.put( themes.size(), "IntelliJ Themes" );
for( IJThemeInfo ti : themesManager.bundledThemes ) {
@@ -157,10 +164,6 @@ public class IJThemesPanel
themes.add( ti );
}
// add themes from directory
categories.put( themes.size(), "Current Directory" );
themes.addAll( themesManager.moreThemes );
// remember selection
IJThemeInfo oldSel = themesList.getSelectedValue();
@@ -193,7 +196,7 @@ public class IJThemesPanel
}
private void themesListValueChanged( ListSelectionEvent e ) {
if( e.getValueIsAdjusting() )
if( e.getValueIsAdjusting() || isAdjustingThemesList )
return;
IJThemeInfo themeInfo = themesList.getSelectedValue();
@@ -223,15 +226,19 @@ public class IJThemesPanel
}
} else if( themeInfo.themeFile != null ) {
try {
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_INTELLIJ_THEME, DemoPrefs.FILE_PREFIX + themeInfo.themeFile );
if( themeInfo.themeFile.getName().endsWith( ".properties" ) ) {
FlatLaf.install( new PropertiesLaf( themeInfo.name, themeInfo.themeFile ) );
} else
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.FILE_PREFIX + themeInfo.themeFile );
} catch( Exception ex ) {
ex.printStackTrace();
showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex );
}
} else {
IntelliJTheme.install( getClass().getResourceAsStream( themeInfo.resourceName ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_INTELLIJ_THEME, DemoPrefs.RESOURCE_PREFIX + themeInfo.resourceName );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.RESOURCE_PREFIX + themeInfo.resourceName );
}
// update all components
@@ -331,17 +338,17 @@ public class IJThemesPanel
private void selectedCurrentLookAndFeel() {
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
String intelliJTheme = UIManager.getLookAndFeelDefaults().getString( DemoPrefs.INTELLIJ_THEME_UI_KEY );
String theme = UIManager.getLookAndFeelDefaults().getString( DemoPrefs.THEME_UI_KEY );
if( intelliJTheme == null && lookAndFeel instanceof IntelliJTheme.ThemeLaf )
if( theme == null && (lookAndFeel instanceof IntelliJTheme.ThemeLaf || lookAndFeel instanceof PropertiesLaf) )
return;
Predicate<IJThemeInfo> test;
if( intelliJTheme != null && intelliJTheme.startsWith( DemoPrefs.RESOURCE_PREFIX ) ) {
String resourceName = intelliJTheme.substring( DemoPrefs.RESOURCE_PREFIX.length() );
if( theme != null && theme.startsWith( DemoPrefs.RESOURCE_PREFIX ) ) {
String resourceName = theme.substring( DemoPrefs.RESOURCE_PREFIX.length() );
test = ti -> Objects.equals( ti.resourceName, resourceName );
} else if( intelliJTheme != null && intelliJTheme.startsWith( DemoPrefs.FILE_PREFIX ) ) {
File themeFile = new File( intelliJTheme.substring( DemoPrefs.FILE_PREFIX.length() ) );
} else if( theme != null && theme.startsWith( DemoPrefs.FILE_PREFIX ) ) {
File themeFile = new File( theme.substring( DemoPrefs.FILE_PREFIX.length() ) );
test = ti -> Objects.equals( ti.themeFile, themeFile );
} else {
String lafClassName = lookAndFeel.getClass().getName();
@@ -356,11 +363,13 @@ public class IJThemesPanel
}
}
isAdjustingThemesList = true;
if( newSel >= 0 ) {
if( newSel != themesList.getSelectedIndex() )
themesList.setSelectedIndex( newSel );
} else
themesList.clearSelection();
isAdjustingThemesList = false;
}
private void initComponents() {
@@ -420,4 +429,78 @@ public class IJThemesPanel
private JScrollPane themesScrollPane;
private JList<IJThemeInfo> themesList;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class PropertiesLaf ------------------------------------------------
public static class PropertiesLaf
extends FlatLaf
{
private final String name;
private final String baseTheme;
private final boolean dark;
private final Properties properties;
public PropertiesLaf( String name, File propertiesFile )
throws IOException
{
this.name = name;
properties = new Properties();
try( InputStream in = new FileInputStream( propertiesFile ) ) {
if( in != null )
properties.load( in );
}
baseTheme = properties.getProperty( "@baseTheme", "light" );
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme );
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return name;
}
@Override
public boolean isDark() {
return dark;
}
@Override
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
ArrayList<Class<?>> lafClasses = new ArrayList<>();
lafClasses.add( FlatLaf.class );
switch( baseTheme.toLowerCase() ) {
default:
case "light":
lafClasses.add( FlatLightLaf.class );
break;
case "dark":
lafClasses.add( FlatDarkLaf.class );
break;
case "intellij":
lafClasses.add( FlatLightLaf.class );
lafClasses.add( FlatIntelliJLaf.class );
break;
case "darcula":
lafClasses.add( FlatDarkLaf.class );
lafClasses.add( FlatDarculaLaf.class );
break;
}
lafClasses.add( PropertiesLaf.class );
return lafClasses;
}
@Override
protected Properties getAdditionalDefaults() {
return properties;
}
}
}