From 5cd0b2403c9390d06fcc514d71f2783ff4726442 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 8 Jul 2022 17:52:08 +0200 Subject: [PATCH] Theme Editor: find/replace bar improvements: - always use editor selection to search if `Ctrl+F` is pressed - keep find/replace bar open if switching to another editor - mark matches when switching to another editor --- flatlaf-theme-editor/build.gradle.kts | 1 - .../themeeditor/FlatFindReplaceBar.java | 70 ++++++++++++------- .../themeeditor/FlatThemeEditorPane.java | 47 ++++++++++--- .../themeeditor/FlatThemeFileEditor.java | 13 +++- 4 files changed, 93 insertions(+), 38 deletions(-) diff --git a/flatlaf-theme-editor/build.gradle.kts b/flatlaf-theme-editor/build.gradle.kts index 129a7b64..c469e48e 100644 --- a/flatlaf-theme-editor/build.gradle.kts +++ b/flatlaf-theme-editor/build.gradle.kts @@ -25,7 +25,6 @@ dependencies { implementation( "com.miglayout:miglayout-swing:5.3" ) implementation( "com.fifesoft:rsyntaxtextarea:3.1.4" ) implementation( "com.fifesoft:autocomplete:3.1.3" ) - implementation( "com.fifesoft:rstaui:3.1.3" ) } tasks { diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.java index 820be31e..fb16f07a 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.java @@ -16,7 +16,7 @@ package com.formdev.flatlaf.themeeditor; -import java.awt.Container; +import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.List; @@ -26,7 +26,6 @@ import javax.swing.border.MatteBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import com.formdev.flatlaf.extras.components.*; -import org.fife.rsta.ui.CollapsibleSectionPanel; import org.fife.ui.rsyntaxtextarea.DocumentRange; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities; @@ -44,9 +43,13 @@ import net.miginfocom.swing.*; class FlatFindReplaceBar extends JPanel { + static final String PROP_CLOSED = "closed"; + private final RSyntaxTextArea textArea; private SearchContext context; + private boolean inSetContext; + private boolean markAllPending; FlatFindReplaceBar( RSyntaxTextArea textArea ) { this.textArea = textArea; @@ -74,6 +77,10 @@ class FlatFindReplaceBar regexToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/regex.svg" ) ); closeButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/close.svg" ) ); + registerKeyboardAction( e -> close(), + KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); + SearchContext context = new SearchContext(); context.setSearchWrap( true ); setSearchContext( context ); @@ -93,29 +100,32 @@ class FlatFindReplaceBar void setSearchContext( SearchContext context ) { this.context = context; - findField.setText( context.getSearchFor() ); - replaceField.setText( context.getReplaceWith() ); - matchCaseToggleButton.setSelected( context.getMatchCase() ); - matchWholeWordToggleButton.setSelected( context.getWholeWord() ); - regexToggleButton.setSelected( context.isRegularExpression() ); + inSetContext = true; + try { + findField.setText( context.getSearchFor() ); + replaceField.setText( context.getReplaceWith() ); + matchCaseToggleButton.setSelected( context.getMatchCase() ); + matchWholeWordToggleButton.setSelected( context.getWholeWord() ); + regexToggleButton.setSelected( context.isRegularExpression() ); + } finally { + inSetContext = false; + } } - @Override - public boolean requestFocusInWindow() { - // invoked from CollapsibleSectionPanel - - // use selected text in editor for searching - String selectedText = textArea.getSelectedText(); - if( !StringUtils.isEmpty( selectedText ) && selectedText.indexOf( '\n' ) < 0 ) - findField.setText( selectedText ); - else - findField.selectAll(); + void activate( boolean findEditorSelection ) { + // use selected text of editor for searching + if( findEditorSelection ) { + String selectedText = textArea.getSelectedText(); + if( !StringUtils.isEmpty( selectedText ) && selectedText.indexOf( '\n' ) < 0 ) + findField.setText( selectedText ); + else + findField.selectAll(); + } // if showing bar, highlight matches in editor - // (not invoking this from addNotify() because this would break the slide-in animation) markAll(); - return findField.requestFocusInWindow(); + findField.requestFocusInWindow(); } @Override @@ -142,7 +152,20 @@ class FlatFindReplaceBar } void markAll() { - findOrMarkAll( false ); + if( inSetContext ) + return; + + // do mark all only once + if( markAllPending ) + return; + markAllPending = true; + + EventQueue.invokeLater( () -> { + markAllPending = false; + + findOrMarkAll( false ); + } ); + } private void findOrMarkAll( boolean find ) { @@ -254,11 +277,8 @@ class FlatFindReplaceBar } private void close() { - Container parent = getParent(); - if( parent instanceof CollapsibleSectionPanel ) - ((CollapsibleSectionPanel)parent).hideBottomComponent(); - else if( parent != null ) - parent.remove( this ); + setVisible( false ); + firePropertyChange( PROP_CLOSED, false, true ); } private void initComponents() { diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeEditorPane.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeEditorPane.java index e6ee4133..4bc60aba 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeEditorPane.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeEditorPane.java @@ -34,7 +34,6 @@ import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; -import org.fife.rsta.ui.CollapsibleSectionPanel; import org.fife.ui.autocomplete.AutoCompletion; import org.fife.ui.autocomplete.CompletionProvider; import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory; @@ -48,6 +47,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 org.fife.ui.rtextarea.SearchContext; import com.formdev.flatlaf.util.UIScale; /** @@ -62,7 +62,10 @@ class FlatThemeEditorPane private static final String FLATLAF_STYLE = "text/flatlaf"; - private final CollapsibleSectionPanel collapsiblePanel; + private static boolean findReplaceVisible; + private static SearchContext findReplaceContext; + + private final JPanel editorPanel; private final RTextScrollPane scrollPane; private final FlatSyntaxTextArea textArea; private final ErrorStrip errorStrip; @@ -115,11 +118,11 @@ class FlatThemeEditorPane // create error strip errorStrip = new ErrorStrip( textArea ); - // create collapsible panel - collapsiblePanel = new CollapsibleSectionPanel(); - collapsiblePanel.add( scrollPane ); - collapsiblePanel.add( errorStrip, BorderLayout.LINE_END ); - add( collapsiblePanel, BorderLayout.CENTER ); + // create editor panel + editorPanel = new JPanel( new BorderLayout() ); + editorPanel.add( scrollPane ); + editorPanel.add( errorStrip, BorderLayout.LINE_END ); + add( editorPanel, BorderLayout.CENTER ); updateTheme(); } @@ -166,6 +169,13 @@ class FlatThemeEditorPane scrollPane.getGutter().setLineNumberFont( font ); } + void selected() { + if( findReplaceVisible ) + showFindReplaceBar( false ); + else + hideFindReplaceBar(); + } + void windowActivated() { if( preview != null ) preview.repaint(); @@ -261,13 +271,30 @@ class FlatThemeEditorPane return (window instanceof JFrame) ? ((JFrame)window).getTitle() : null; } - void showFindReplaceBar() { + void showFindReplaceBar( boolean findEditorSelection ) { if( findReplaceBar == null ) { findReplaceBar = new FlatFindReplaceBar( textArea ); - collapsiblePanel.addBottomComponent( findReplaceBar ); + findReplaceBar.addPropertyChangeListener( FlatFindReplaceBar.PROP_CLOSED, e -> { + findReplaceVisible = false; + textArea.requestFocusInWindow(); + } ); + editorPanel.add( findReplaceBar, BorderLayout.SOUTH ); + editorPanel.revalidate(); } - collapsiblePanel.showBottomComponent( findReplaceBar ); + findReplaceVisible = true; + if( findReplaceContext == null ) + findReplaceContext = findReplaceBar.getSearchContext(); + else + findReplaceBar.setSearchContext( findReplaceContext ); + + findReplaceBar.setVisible( true ); + findReplaceBar.activate( findEditorSelection ); + } + + void hideFindReplaceBar() { + if( findReplaceBar != null ) + findReplaceBar.setVisible( false ); } void showPreview( boolean show ) { diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.java index a7f14d1d..8ab22dbd 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.java @@ -336,6 +336,7 @@ class FlatThemeFileEditor SwingUtilities.invokeLater( () -> { activateEditor(); + notifyEditorSelected(); } ); saveState(); enableDisableActions(); @@ -448,11 +449,13 @@ class FlatThemeFileEditor FlatThemeEditorPane themeEditorPane = (FlatThemeEditorPane) tabbedPane.getSelectedComponent(); String filename = (themeEditorPane != null) ? themeEditorPane.getFile().getName() : null; putPrefsString( state, KEY_RECENT_FILE, filename ); + + notifyEditorSelected(); } private void enableDisableActions() { boolean dirOpen = (directoryField.getSelectedItem() != null); - boolean editorOpen = (dirOpen &&tabbedPane.getSelectedIndex() >= 0); + boolean editorOpen = (dirOpen && tabbedPane.getSelectedIndex() >= 0); // enable/disable buttons newButton.setEnabled( dirOpen ); @@ -687,6 +690,12 @@ class FlatThemeFileEditor return result; } + private void notifyEditorSelected() { + FlatThemeEditorPane themeEditorPane = (FlatThemeEditorPane) tabbedPane.getSelectedComponent(); + if( themeEditorPane != null ) + themeEditorPane.selected(); + } + private void activateEditor() { FlatThemeEditorPane themeEditorPane = (FlatThemeEditorPane) tabbedPane.getSelectedComponent(); if( themeEditorPane != null ) @@ -709,7 +718,7 @@ class FlatThemeFileEditor private void find() { FlatThemeEditorPane themeEditorPane = (FlatThemeEditorPane) tabbedPane.getSelectedComponent(); if( themeEditorPane != null ) - themeEditorPane.showFindReplaceBar(); + themeEditorPane.showFindReplaceBar( true ); } private void insertColor() {