mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-07 22:40:53 +03:00
Theme Editor: auto-completion improved:
- reference completion shows all keys defined in current and base files - support auto-activate for value provider - do not auto-complete single choices
This commit is contained in:
@@ -22,10 +22,13 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import org.fife.ui.autocomplete.BasicCompletion;
|
||||||
import org.fife.ui.autocomplete.Completion;
|
import org.fife.ui.autocomplete.Completion;
|
||||||
import org.fife.ui.autocomplete.CompletionProvider;
|
import org.fife.ui.autocomplete.CompletionProvider;
|
||||||
import org.fife.ui.autocomplete.CompletionProviderBase;
|
import org.fife.ui.autocomplete.CompletionProviderBase;
|
||||||
@@ -109,10 +112,12 @@ class FlatCompletionProvider
|
|||||||
return getValueProvider();
|
return getValueProvider();
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
|
case '@':
|
||||||
return getReferenceProvider();
|
return getReferenceProvider();
|
||||||
|
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
|
case '#': // colors
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +131,7 @@ class FlatCompletionProvider
|
|||||||
|
|
||||||
private CompletionProvider getKeyProvider() {
|
private CompletionProvider getKeyProvider() {
|
||||||
if( keyProvider == null )
|
if( keyProvider == null )
|
||||||
keyProvider = new KeyCompletionProvider();
|
keyProvider = KeyCompletionProvider.getInstance();
|
||||||
return keyProvider;
|
return keyProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,20 +147,25 @@ class FlatCompletionProvider
|
|||||||
return valueProvider;
|
return valueProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class KnownKeysCompletionProvider ----------------------------------
|
//---- class KeyCompletionProvider ----------------------------------------
|
||||||
|
|
||||||
private static final class KnownKeysCompletionProvider
|
/**
|
||||||
extends DefaultCompletionProvider
|
* A completion provider for keys, which always uses all known/predefined keys.
|
||||||
|
*/
|
||||||
|
private static final class KeyCompletionProvider
|
||||||
|
extends BaseCompletionProvider
|
||||||
{
|
{
|
||||||
private static KnownKeysCompletionProvider instance;
|
private static KeyCompletionProvider instance;
|
||||||
|
|
||||||
static KnownKeysCompletionProvider getInstance() {
|
static KeyCompletionProvider getInstance() {
|
||||||
if( instance == null )
|
if( instance == null )
|
||||||
instance = new KnownKeysCompletionProvider();
|
instance = new KeyCompletionProvider();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownKeysCompletionProvider() {
|
KeyCompletionProvider() {
|
||||||
|
setAutoActivationRules( true, "." );
|
||||||
|
|
||||||
// load all keys
|
// load all keys
|
||||||
HashSet<String> keys = new HashSet<>();
|
HashSet<String> keys = new HashSet<>();
|
||||||
try {
|
try {
|
||||||
@@ -197,19 +207,14 @@ class FlatCompletionProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class KeyCompletionProvider ----------------------------------------
|
//---- class BaseCompletionProvider ---------------------------------------
|
||||||
|
|
||||||
private static class KeyCompletionProvider
|
//TODO remove if https://github.com/bobbylight/AutoComplete/issues/77 is fixed
|
||||||
|
private static class BaseCompletionProvider
|
||||||
extends DefaultCompletionProvider
|
extends DefaultCompletionProvider
|
||||||
{
|
{
|
||||||
KeyCompletionProvider() {
|
private boolean autoActivateAfterLetters;
|
||||||
setParent( KnownKeysCompletionProvider.getInstance() );
|
private String autoActivateChars;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValidChar( char ch ) {
|
|
||||||
return super.isValidChar( ch ) || ch == '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAutoActivateOkay( JTextComponent comp ) {
|
public boolean isAutoActivateOkay( JTextComponent comp ) {
|
||||||
@@ -219,36 +224,90 @@ class FlatCompletionProvider
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
char ch = comp.getText( caretPosition - 1, 1 ).charAt( 0 );
|
char ch = comp.getText( caretPosition - 1, 1 ).charAt( 0 );
|
||||||
return isAutoActivateOkay( ch );
|
return (autoActivateAfterLetters && Character.isLetter( ch )) ||
|
||||||
|
(autoActivateChars != null && autoActivateChars.indexOf( ch ) >= 0);
|
||||||
} catch( BadLocationException | IndexOutOfBoundsException ex ) {
|
} catch( BadLocationException | IndexOutOfBoundsException ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isAutoActivateOkay( char ch ) {
|
@Override
|
||||||
return Character.isLetter( ch ) || ch == '.';
|
public void setAutoActivationRules( boolean letters, String others ) {
|
||||||
|
autoActivateAfterLetters = letters;
|
||||||
|
autoActivateChars = others;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class ReferenceCompletionProvider ----------------------------------
|
//---- class ReferenceCompletionProvider ----------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A completion provider for references within values. Only keys defined
|
||||||
|
* in current properties file and in base properties files are used.
|
||||||
|
*/
|
||||||
private static class ReferenceCompletionProvider
|
private static class ReferenceCompletionProvider
|
||||||
extends KeyCompletionProvider
|
extends BaseCompletionProvider
|
||||||
{
|
{
|
||||||
|
private Set<String> lastKeys;
|
||||||
|
|
||||||
|
ReferenceCompletionProvider() {
|
||||||
|
setAutoActivationRules( true, "$@." );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isAutoActivateOkay( char ch ) {
|
protected boolean isValidChar( char ch ) {
|
||||||
return ch == '$' || super.isAutoActivateOkay( ch );
|
return super.isValidChar( ch ) || ch == '.' || ch == '$' || ch == '@';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Completion> getCompletionsImpl( JTextComponent comp ) {
|
||||||
|
updateCompletions( comp );
|
||||||
|
return super.getCompletionsImpl( comp );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Completion> getCompletionsAt( JTextComponent comp, Point pt ) {
|
||||||
|
updateCompletions( comp );
|
||||||
|
return super.getCompletionsAt( comp, pt );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ParameterizedCompletion> getParameterizedCompletions( JTextComponent comp ) {
|
||||||
|
updateCompletions( comp );
|
||||||
|
return super.getParameterizedCompletions( comp );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCompletions( JTextComponent comp ) {
|
||||||
|
FlatSyntaxTextArea fsta = (FlatSyntaxTextArea) comp;
|
||||||
|
Set<String> keys = fsta.propertiesSupport.getAllKeys();
|
||||||
|
if( keys == lastKeys )
|
||||||
|
return;
|
||||||
|
|
||||||
|
completions.clear();
|
||||||
|
for( String key : keys ) {
|
||||||
|
if( key.startsWith( "*." ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !key.startsWith( "@" ) )
|
||||||
|
key = "$".concat( key );
|
||||||
|
|
||||||
|
completions.add( new BasicCompletion( this, key ) );
|
||||||
|
}
|
||||||
|
Collections.sort(completions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class ValueCompletionProvider --------------------------------------
|
//---- class ValueCompletionProvider --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A completion provider for values.
|
||||||
|
*/
|
||||||
private static class ValueCompletionProvider
|
private static class ValueCompletionProvider
|
||||||
extends DefaultCompletionProvider
|
extends BaseCompletionProvider
|
||||||
{
|
{
|
||||||
ValueCompletionProvider() {
|
ValueCompletionProvider() {
|
||||||
setParameterizedCompletionParams( '(', ", ", ')' );
|
setAutoActivationRules( true, null );
|
||||||
|
setParameterizedCompletionParams( '(', ",", ')' );
|
||||||
|
|
||||||
addFunction( "rgb",
|
addFunction( "rgb",
|
||||||
"red", "0-255 or 0-100%",
|
"red", "0-255 or 0-100%",
|
||||||
@@ -293,17 +352,12 @@ class FlatCompletionProvider
|
|||||||
FunctionCompletion f = new FunctionCompletion( this, name, null ) {
|
FunctionCompletion f = new FunctionCompletion( this, name, null ) {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getDefinitionString().replace( "(", " (" );
|
return getDefinitionString().replace( "(", " (" ).replace( ",", ", " );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
f.setParams( params );
|
f.setParams( params );
|
||||||
addCompletion( f );
|
addCompletion( f );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAutoActivateOkay( JTextComponent tc ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JLayer;
|
import javax.swing.JLayer;
|
||||||
@@ -63,8 +64,8 @@ class FlatThemeEditorPane
|
|||||||
// textArea.setUseColorOfColorTokens( true );
|
// textArea.setUseColorOfColorTokens( true );
|
||||||
|
|
||||||
// theme
|
// theme
|
||||||
try {
|
try( InputStream in = getClass().getResourceAsStream( "light.xml" ) ) {
|
||||||
Theme theme = Theme.load( getClass().getResourceAsStream( "light.xml" ) );
|
Theme theme = Theme.load( in );
|
||||||
theme.apply( textArea );
|
theme.apply( textArea );
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
@@ -79,6 +80,7 @@ class FlatThemeEditorPane
|
|||||||
// autocomplete
|
// autocomplete
|
||||||
CompletionProvider provider = new FlatCompletionProvider();
|
CompletionProvider provider = new FlatCompletionProvider();
|
||||||
AutoCompletion ac = new AutoCompletion( provider );
|
AutoCompletion ac = new AutoCompletion( provider );
|
||||||
|
ac.setAutoCompleteSingleChoices( false );
|
||||||
ac.setAutoActivationEnabled( true );
|
ac.setAutoActivationEnabled( true );
|
||||||
ac.setParameterAssistanceEnabled( true );
|
ac.setParameterAssistanceEnabled( true );
|
||||||
ac.setChoicesWindowSize( UIScale.scale( 300 ), UIScale.scale( 400 ) );
|
ac.setChoicesWindowSize( UIScale.scale( 300 ), UIScale.scale( 400 ) );
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
@@ -50,6 +52,8 @@ class FlatThemePropertiesSupport
|
|||||||
private long[] baseFilesLastModified;
|
private long[] baseFilesLastModified;
|
||||||
private Properties[] basePropertiesCache;
|
private Properties[] basePropertiesCache;
|
||||||
|
|
||||||
|
private Set<String> allKeysCache;
|
||||||
|
|
||||||
FlatThemePropertiesSupport( FlatSyntaxTextArea textArea ) {
|
FlatThemePropertiesSupport( FlatSyntaxTextArea textArea ) {
|
||||||
this.textArea = textArea;
|
this.textArea = textArea;
|
||||||
|
|
||||||
@@ -129,19 +133,7 @@ class FlatThemePropertiesSupport
|
|||||||
|
|
||||||
// look in base properties files
|
// look in base properties files
|
||||||
for( int i = 0; i < baseFiles.length; i++ ) {
|
for( int i = 0; i < baseFiles.length; i++ ) {
|
||||||
long lastModified = baseFiles[i].lastModified();
|
value = getBaseProperties( i ).getProperty( key );
|
||||||
if( baseFilesLastModified[i] != lastModified ) {
|
|
||||||
// (re)load base properties file
|
|
||||||
baseFilesLastModified[i] = lastModified;
|
|
||||||
basePropertiesCache[i] = new Properties();
|
|
||||||
try( InputStream in = new FileInputStream( baseFiles[i] ) ) {
|
|
||||||
basePropertiesCache[i].load( in );
|
|
||||||
} catch( IOException ex ) {
|
|
||||||
ex.printStackTrace(); //TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = basePropertiesCache[i].getProperty( key );
|
|
||||||
if( value != null )
|
if( value != null )
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -162,9 +154,43 @@ class FlatThemePropertiesSupport
|
|||||||
return propertiesCache;
|
return propertiesCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Properties getBaseProperties( int index ) {
|
||||||
|
long lastModified = baseFiles[index].lastModified();
|
||||||
|
if( baseFilesLastModified[index] != lastModified || basePropertiesCache[index] == null ) {
|
||||||
|
// (re)load base properties file
|
||||||
|
baseFilesLastModified[index] = lastModified;
|
||||||
|
basePropertiesCache[index] = new Properties();
|
||||||
|
try( InputStream in = new FileInputStream( baseFiles[index] ) ) {
|
||||||
|
basePropertiesCache[index].load( in );
|
||||||
|
} catch( IOException ex ) {
|
||||||
|
ex.printStackTrace(); //TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return basePropertiesCache[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> getAllKeys() {
|
||||||
|
if( allKeysCache != null )
|
||||||
|
return allKeysCache;
|
||||||
|
|
||||||
|
allKeysCache = new HashSet<>();
|
||||||
|
|
||||||
|
for( Object key : getProperties().keySet() )
|
||||||
|
allKeysCache.add( (String) key );
|
||||||
|
|
||||||
|
for( int i = 0; i < baseFiles.length; i++ ) {
|
||||||
|
for( Object key : getBaseProperties( i ).keySet() )
|
||||||
|
allKeysCache.add( (String) key );
|
||||||
|
}
|
||||||
|
|
||||||
|
return allKeysCache;
|
||||||
|
}
|
||||||
|
|
||||||
private void clearCache() {
|
private void clearCache() {
|
||||||
propertiesCache = null;
|
propertiesCache = null;
|
||||||
parsedValueCache.clear();
|
parsedValueCache.clear();
|
||||||
|
allKeysCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- interface DocumentListener ----
|
//---- interface DocumentListener ----
|
||||||
|
|||||||
Reference in New Issue
Block a user