Theme Editor: re-implemented support loading/resolving base properties from other editors in opened directory

This commit is contained in:
Karl Tauber
2021-08-11 21:53:10 +02:00
parent 1df9597bb1
commit 896e9bca8e
4 changed files with 218 additions and 51 deletions

View File

@@ -23,7 +23,6 @@ import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JComponent;
@@ -49,6 +48,7 @@ import org.fife.ui.rsyntaxtextarea.TokenTypes;
import org.fife.ui.rtextarea.Gutter;
import org.fife.ui.rtextarea.RTextArea;
import org.fife.ui.rtextarea.RTextScrollPane;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -168,8 +168,9 @@ class FlatThemeEditorPane
return textArea.requestFocusInWindow();
}
void setBaseFiles( List<File> baseFiles ) {
textArea.propertiesSupport.setBaseFiles( baseFiles );
void initBasePropertyProvider( FlatThemePropertiesBaseManager propertiesBaseManager ) {
String name = StringUtils.removeTrailing( file.getName(), ".properties" );
textArea.propertiesSupport.setBasePropertyProvider( propertiesBaseManager.create( name, textArea.propertiesSupport ) );
}
File getFile() {

View File

@@ -68,6 +68,8 @@ public class FlatThemeFileEditor
private Preferences state;
private boolean inLoadDirectory;
private final FlatThemePropertiesBaseManager propertiesBaseManager = new FlatThemePropertiesBaseManager();
public static void main( String[] args ) {
File dir = (args.length > 0)
? new File( args[0] )
@@ -187,6 +189,7 @@ public class FlatThemeFileEditor
return;
this.dir = dir;
propertiesBaseManager.clear();
inLoadDirectory = true;
@@ -266,6 +269,8 @@ public class FlatThemeFileEditor
ex.printStackTrace(); // TODO
}
themeEditorPane.initBasePropertyProvider( propertiesBaseManager );
Supplier<String> titleFun = () -> {
return (themeEditorPane.isDirty() ? "* " : "")
+ StringUtils.removeTrailing( themeEditorPane.getFile().getName(), ".properties" );

View File

@@ -0,0 +1,160 @@
/*
* Copyright 2021 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.themeeditor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @author Karl Tauber
*/
class FlatThemePropertiesBaseManager
{
private final Map<String, MyBasePropertyProvider> providers = new HashMap<>();
FlatThemePropertiesSupport.BasePropertyProvider create( String name, FlatThemePropertiesSupport propertiesSupport ) {
MyBasePropertyProvider provider = new MyBasePropertyProvider( name, propertiesSupport );
providers.put( name, provider );
return provider;
}
void clear() {
providers.clear();
}
private static List<String> baseFiles( String name, String baseTheme ) {
ArrayList<String> result = new ArrayList<>();
// core themes
switch( name ) {
case "FlatLaf":
result.add( "FlatLightLaf" );
break;
case "FlatLightLaf":
case "FlatDarkLaf":
result.add( "FlatLaf" );
break;
case "FlatIntelliJLaf":
result.add( "FlatLightLaf" );
result.add( "FlatLaf" );
break;
case "FlatDarculaLaf":
result.add( "FlatDarkLaf" );
result.add( "FlatLaf" );
break;
}
// custom themes based on core themes
if( result.isEmpty() ) {
if( baseTheme == null )
baseTheme = "light";
switch( baseTheme ) {
default:
case "light":
result.add( "FlatLightLaf" );
result.add( "FlatLaf" );
break;
case "dark":
result.add( "FlatDarkLaf" );
result.add( "FlatLaf" );
break;
case "intellij":
result.add( "FlatIntelliJLaf" );
result.add( "FlatLightLaf" );
result.add( "FlatLaf" );
break;
case "darcula":
result.add( "FlatDarculaLaf" );
result.add( "FlatLightLaf" );
result.add( "FlatLaf" );
break;
}
}
return result;
}
//---- class MyBasePropertyProvider ---------------------------------------
private class MyBasePropertyProvider
implements FlatThemePropertiesSupport.BasePropertyProvider
{
private final String name;
private final FlatThemePropertiesSupport propertiesSupport;
private List<String> baseFiles;
private String lastBaseTheme;
MyBasePropertyProvider( String name, FlatThemePropertiesSupport propertiesSupport ) {
this.name = name;
this.propertiesSupport = propertiesSupport;
}
@Override
public String getProperty( String key, String baseTheme ) {
updateBaseFiles( baseTheme );
for( String baseFile : baseFiles ) {
String value = getPropertyFromBase( baseFile, key );
if( value != null )
return value;
}
return null;
}
private String getPropertyFromBase( String baseFile, String key ) {
MyBasePropertyProvider provider = providers.get( baseFile );
return (provider != null)
? provider.propertiesSupport.getProperties().getProperty( key )
: null;
}
private void updateBaseFiles( String baseTheme ) {
if( baseFiles != null && Objects.equals( baseTheme, lastBaseTheme ) )
return;
baseFiles = baseFiles( name, baseTheme );
lastBaseTheme = baseTheme;
}
@Override
public void addAllKeys( Set<String> allKeys, String baseTheme ) {
updateBaseFiles( baseTheme );
for( String baseFile : baseFiles ) {
MyBasePropertyProvider provider = providers.get( baseFile );
if( provider == null )
continue;
for( Object key : provider.propertiesSupport.getProperties().keySet() )
allKeys.add( (String) key );
}
}
}
}

View File

@@ -17,14 +17,10 @@
package com.formdev.flatlaf.themeeditor;
import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -45,14 +41,16 @@ class FlatThemePropertiesSupport
private final FlatSyntaxTextArea textArea;
private final Function<String, String> propertiesGetter;
private final Function<String, String> resolver;
private BasePropertyProvider basePropertyProvider;
// caches
private Properties propertiesCache;
private final Map<Integer, Object> parsedValueCache = new HashMap<>();
private File[] baseFiles;
private long[] baseFilesLastModified;
private Properties[] basePropertiesCache;
private Set<String> allKeysCache;
private String baseTheme;
private static long globalCacheInvalidationCounter;
private long cacheInvalidationCounter;
FlatThemePropertiesSupport( FlatSyntaxTextArea textArea ) {
this.textArea = textArea;
@@ -67,12 +65,8 @@ class FlatThemePropertiesSupport
textArea.getDocument().addDocumentListener( this );
}
void setBaseFiles( List<File> baseFiles ) {
int size = baseFiles.size();
this.baseFiles = baseFiles.toArray( new File[size] );
baseFilesLastModified = new long[size];
basePropertiesCache = new Properties[size];
void setBasePropertyProvider( BasePropertyProvider basePropertyProvider ) {
this.basePropertyProvider = basePropertyProvider;
}
private String resolveValue( String value ) {
@@ -80,6 +74,8 @@ class FlatThemePropertiesSupport
}
Object getParsedValueAtLine( int line ) {
autoClearCache();
Integer lineKey = line;
Object parsedValue = parsedValueCache.get( lineKey );
if( parsedValue != null )
@@ -96,7 +92,7 @@ class FlatThemePropertiesSupport
parsedValueCache.put( lineKey, parsedValue );
return parsedValue;
} catch( Exception ex ) {
System.out.println( ex.getMessage() ); //TODO
System.out.println( textArea.getFileName() + ": " + ex.getMessage() ); //TODO
parsedValueCache.put( lineKey, ex );
return null;
}
@@ -128,20 +124,14 @@ class FlatThemePropertiesSupport
if( value != null )
return value;
if( baseFiles == null )
if( basePropertyProvider == null )
return null;
// look in base properties files
for( int i = 0; i < baseFiles.length; i++ ) {
value = getBaseProperties( i ).getProperty( key );
if( value != null )
return value;
}
return null;
return basePropertyProvider.getProperty( key, getBaseTheme() );
}
private Properties getProperties() {
Properties getProperties() {
if( propertiesCache != null )
return propertiesCache;
@@ -154,23 +144,9 @@ class FlatThemePropertiesSupport
return propertiesCache;
}
private Properties getBaseProperties( int index ) {
long lastModified = baseFiles[index].lastModified();
if( baseFilesLastModified[index] != lastModified || basePropertiesCache[index] == null ) {
// (re)load base properties file
baseFilesLastModified[index] = lastModified;
basePropertiesCache[index] = new Properties();
try( InputStream in = new FileInputStream( baseFiles[index] ) ) {
basePropertiesCache[index].load( in );
} catch( IOException ex ) {
ex.printStackTrace(); //TODO
}
}
return basePropertiesCache[index];
}
Set<String> getAllKeys() {
autoClearCache();
if( allKeysCache != null )
return allKeysCache;
@@ -179,21 +155,39 @@ class FlatThemePropertiesSupport
for( Object key : getProperties().keySet() )
allKeysCache.add( (String) key );
if( baseFiles == null )
return allKeysCache;
for( int i = 0; i < baseFiles.length; i++ ) {
for( Object key : getBaseProperties( i ).keySet() )
allKeysCache.add( (String) key );
}
// look in base properties files
if( basePropertyProvider != null )
basePropertyProvider.addAllKeys( allKeysCache, getBaseTheme() );
return allKeysCache;
}
private String getBaseTheme() {
if( baseTheme == null )
baseTheme = getProperties().getProperty( "@baseTheme", "light" );
return baseTheme;
}
private void clearCache() {
propertiesCache = null;
parsedValueCache.clear();
allKeysCache = null;
baseTheme = null;
// increase global cache invalidation counter to allow auto-clear caches
globalCacheInvalidationCounter++;
cacheInvalidationCounter = globalCacheInvalidationCounter;
}
/**
* Clear caches that may depend on other editors if cache of another editor was invalidated.
*/
private void autoClearCache() {
if( cacheInvalidationCounter == globalCacheInvalidationCounter )
return;
parsedValueCache.clear();
allKeysCache = null;
}
//---- interface DocumentListener ----
@@ -233,4 +227,11 @@ class FlatThemePropertiesSupport
this.value = value;
}
}
//---- interface BasePropertyProvider -------------------------------------
interface BasePropertyProvider {
String getProperty( String key, String baseTheme );
void addAllKeys( Set<String> allKeys, String baseTheme );
}
}