diff --git a/flatlaf-theme-editor/build.gradle.kts b/flatlaf-theme-editor/build.gradle.kts
index e759f118..31a6fc02 100644
--- a/flatlaf-theme-editor/build.gradle.kts
+++ b/flatlaf-theme-editor/build.gradle.kts
@@ -30,8 +30,9 @@ dependencies {
implementation( project( ":flatlaf-extras" ) )
implementation( "com.miglayout:miglayout-swing:5.3-SNAPSHOT" )
- implementation( "com.fifesoft:rsyntaxtextarea:3.1.1" )
- implementation( "com.fifesoft:autocomplete:3.1.0" )
+ implementation( "com.fifesoft:rsyntaxtextarea:3.1.2" )
+ implementation( "com.fifesoft:autocomplete:3.1.1" )
+ implementation( "com.fifesoft:rstaui:3.1.1" )
}
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
new file mode 100644
index 00000000..141b0614
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2020 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.awt.Container;
+import javax.swing.*;
+import org.fife.rsta.ui.CollapsibleSectionPanel;
+import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
+import org.fife.ui.rtextarea.SearchContext;
+import org.fife.ui.rtextarea.SearchEngine;
+import org.fife.ui.rtextarea.SearchResult;
+import com.formdev.flatlaf.extras.FlatSVGIcon;
+import net.miginfocom.swing.*;
+
+/**
+ * @author Karl Tauber
+ */
+class FlatFindReplaceBar
+ extends JPanel
+{
+ private final RSyntaxTextArea textArea;
+
+ private SearchContext context;
+
+ FlatFindReplaceBar( RSyntaxTextArea textArea ) {
+ this.textArea = textArea;
+
+ initComponents();
+
+ findPreviousButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/findAndShowPrevMatches.svg" ) );
+ findNextButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/findAndShowNextMatches.svg" ) );
+ matchCaseToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/matchCase.svg" ) );
+ matchWholeWordToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/words.svg" ) );
+ regexToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/regex.svg" ) );
+ closeButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/themeeditor/icons/close.svg" ) );
+
+ SearchContext context = new SearchContext();
+ context.setSearchWrap( true );
+ setSearchContext( context );
+ }
+
+ SearchContext getSearchContext() {
+ return context;
+ }
+
+ void setSearchContext( SearchContext context ) {
+ this.context = context;
+
+ findField.setText( context.getSearchFor() );
+ matchCaseToggleButton.setSelected( context.getMatchCase() );
+ matchWholeWordToggleButton.setSelected( context.getWholeWord() );
+ regexToggleButton.setSelected( context.isRegularExpression() );
+ }
+
+ @Override
+ public boolean requestFocusInWindow() {
+ return findField.requestFocusInWindow();
+ }
+
+ private void findNext() {
+ context.setSearchForward( true );
+ find();
+ }
+
+ private void findPrevious() {
+ context.setSearchForward( false );
+ find();
+ }
+
+ private void find() {
+ // update search context
+ context.setSearchFor( findField.getText() );
+
+ // find
+ SearchResult result = SearchEngine.find( textArea, context );
+
+ // update matches info label
+ matchesLabel.setText( result.getMarkedCount() + " matches" );
+ }
+
+ private void matchCaseChanged() {
+ context.setMatchCase( matchCaseToggleButton.isSelected() );
+ find();
+ }
+
+ private void matchWholeWordChanged() {
+ context.setWholeWord( matchWholeWordToggleButton.isSelected() );
+ find();
+ }
+
+ private void regexChanged() {
+ context.setRegularExpression( regexToggleButton.isSelected() );
+ find();
+ }
+
+ private void close() {
+ Container parent = getParent();
+ if( parent instanceof CollapsibleSectionPanel )
+ ((CollapsibleSectionPanel)parent).hideBottomComponent();
+ else if( parent != null )
+ parent.remove( this );
+ }
+
+ private void initComponents() {
+ // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
+ findLabel = new JLabel();
+ findField = new JTextField();
+ findToolBar = new JToolBar();
+ findPreviousButton = new JButton();
+ findNextButton = new JButton();
+ matchCaseToggleButton = new JToggleButton();
+ matchWholeWordToggleButton = new JToggleButton();
+ regexToggleButton = new JToggleButton();
+ matchesLabel = new JLabel();
+ hSpacer1 = new JPanel(null);
+ closeButton = new JButton();
+
+ //======== this ========
+ setFocusCycleRoot(true);
+ setLayout(new MigLayout(
+ "insets 3,hidemode 3",
+ // columns
+ "[fill]" +
+ "[fill]0" +
+ "[grow,fill]",
+ // rows
+ "[]"));
+
+ //---- findLabel ----
+ findLabel.setText("Find:");
+ findLabel.setDisplayedMnemonic('F');
+ findLabel.setLabelFor(findField);
+ add(findLabel, "cell 0 0");
+
+ //---- findField ----
+ findField.setColumns(16);
+ findField.addActionListener(e -> find());
+ add(findField, "cell 1 0");
+
+ //======== findToolBar ========
+ {
+ findToolBar.setFloatable(false);
+ findToolBar.setBorder(null);
+
+ //---- findPreviousButton ----
+ findPreviousButton.setToolTipText("Previous Occurrence");
+ findPreviousButton.addActionListener(e -> findPrevious());
+ findToolBar.add(findPreviousButton);
+
+ //---- findNextButton ----
+ findNextButton.setToolTipText("Next Occurrence");
+ findNextButton.addActionListener(e -> findNext());
+ findToolBar.add(findNextButton);
+ findToolBar.addSeparator();
+
+ //---- matchCaseToggleButton ----
+ matchCaseToggleButton.setToolTipText("Match Case");
+ matchCaseToggleButton.addActionListener(e -> matchCaseChanged());
+ findToolBar.add(matchCaseToggleButton);
+
+ //---- matchWholeWordToggleButton ----
+ matchWholeWordToggleButton.setToolTipText("Match Whole Word");
+ matchWholeWordToggleButton.addActionListener(e -> matchWholeWordChanged());
+ findToolBar.add(matchWholeWordToggleButton);
+
+ //---- regexToggleButton ----
+ regexToggleButton.setToolTipText("Regex");
+ regexToggleButton.addActionListener(e -> regexChanged());
+ findToolBar.add(regexToggleButton);
+ findToolBar.addSeparator();
+
+ //---- matchesLabel ----
+ matchesLabel.setEnabled(false);
+ findToolBar.add(matchesLabel);
+ findToolBar.add(hSpacer1);
+
+ //---- closeButton ----
+ closeButton.setToolTipText("Close");
+ closeButton.addActionListener(e -> close());
+ findToolBar.add(closeButton);
+ }
+ add(findToolBar, "cell 2 0");
+ // JFormDesigner - End of component initialization //GEN-END:initComponents
+ }
+
+ // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
+ private JLabel findLabel;
+ private JTextField findField;
+ private JToolBar findToolBar;
+ private JButton findPreviousButton;
+ private JButton findNextButton;
+ private JToggleButton matchCaseToggleButton;
+ private JToggleButton matchWholeWordToggleButton;
+ private JToggleButton regexToggleButton;
+ private JLabel matchesLabel;
+ private JPanel hSpacer1;
+ private JButton closeButton;
+ // JFormDesigner - End of variables declaration //GEN-END:variables
+}
diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.jfd b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.jfd
new file mode 100644
index 00000000..d993c89c
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatFindReplaceBar.jfd
@@ -0,0 +1,83 @@
+JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
+
+new FormModel {
+ contentType: "form/swing"
+ root: new FormRoot {
+ add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
+ "$layoutConstraints": "insets 3,hidemode 3"
+ "$columnConstraints": "[fill][fill]0[grow,fill]"
+ "$rowConstraints": "[]"
+ } ) {
+ name: "this"
+ "focusCycleRoot": true
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "findLabel"
+ "text": "Find:"
+ "displayedMnemonic": 70
+ "labelFor": new FormReference( "findField" )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 0"
+ } )
+ add( new FormComponent( "javax.swing.JTextField" ) {
+ name: "findField"
+ "columns": 16
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "find", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 0"
+ } )
+ add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
+ name: "findToolBar"
+ "floatable": false
+ "border": sfield com.jformdesigner.model.FormObject NULL_VALUE
+ add( new FormComponent( "javax.swing.JButton" ) {
+ name: "findPreviousButton"
+ "toolTipText": "Previous Occurrence"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "findPrevious", false ) )
+ } )
+ add( new FormComponent( "javax.swing.JButton" ) {
+ name: "findNextButton"
+ "toolTipText": "Next Occurrence"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "findNext", false ) )
+ } )
+ add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
+ name: "separator1"
+ } )
+ add( new FormComponent( "javax.swing.JToggleButton" ) {
+ name: "matchCaseToggleButton"
+ "toolTipText": "Match Case"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "matchCaseChanged", false ) )
+ } )
+ add( new FormComponent( "javax.swing.JToggleButton" ) {
+ name: "matchWholeWordToggleButton"
+ "toolTipText": "Match Whole Word"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "matchWholeWordChanged", false ) )
+ } )
+ add( new FormComponent( "javax.swing.JToggleButton" ) {
+ name: "regexToggleButton"
+ "toolTipText": "Regex"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "regexChanged", false ) )
+ } )
+ add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
+ name: "separator2"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "matchesLabel"
+ "enabled": false
+ } )
+ add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
+ name: "hSpacer1"
+ } )
+ add( new FormComponent( "javax.swing.JButton" ) {
+ name: "closeButton"
+ "toolTipText": "Close"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "close", false ) )
+ } )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 0"
+ } )
+ }, new FormLayoutConstraints( null ) {
+ "location": new java.awt.Point( 0, 0 )
+ "size": new java.awt.Dimension( 400, 300 )
+ } )
+ }
+}
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 850ec621..d914af25 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
@@ -30,6 +30,7 @@ import javax.swing.JLayer;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
+import org.fife.rsta.ui.CollapsibleSectionPanel;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.autocomplete.CompletionProvider;
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
@@ -53,8 +54,10 @@ class FlatThemeEditorPane
private static final String FLATLAF_STYLE = "text/flatlaf";
+ private final CollapsibleSectionPanel collapsiblePanel;
private final RTextScrollPane scrollPane;
private final FlatSyntaxTextArea textArea;
+ private FlatFindReplaceBar findReplaceBar;
private File file;
@@ -114,7 +117,10 @@ class FlatThemeEditorPane
// use same font for line numbers as in editor
scrollPane.getGutter().setLineNumberFont( textArea.getFont() );
- add( scrollPane, BorderLayout.CENTER );
+ // create collapsible panel
+ collapsiblePanel = new CollapsibleSectionPanel();
+ collapsiblePanel.add( scrollPane );
+ add( collapsiblePanel, BorderLayout.CENTER );
}
private static Font scaleFont( Font font ) {
@@ -198,4 +204,13 @@ class FlatThemeEditorPane
Window window = SwingUtilities.windowForComponent( this );
return (window instanceof JFrame) ? ((JFrame)window).getTitle() : null;
}
+
+ void showFindReplaceBar() {
+ if( findReplaceBar == null ) {
+ findReplaceBar = new FlatFindReplaceBar( textArea );
+ collapsiblePanel.addBottomComponent( findReplaceBar );
+ }
+
+ collapsiblePanel.showBottomComponent( findReplaceBar );
+ }
}
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 5643c4fa..48b6e4ed 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
@@ -179,12 +179,20 @@ public class FlatThemeFileEditor
tabbedPane.setSelectedIndex( index );
}
+ private void find() {
+ FlatThemeEditorPane themeEditorPane = (FlatThemeEditorPane) tabbedPane.getSelectedComponent();
+ if( themeEditorPane != null )
+ themeEditorPane.showFindReplaceBar();
+ }
+
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
menuBar = new JMenuBar();
fileMenu = new JMenu();
saveAllMenuItem = new JMenuItem();
exitMenuItem = new JMenuItem();
+ editMenu = new JMenu();
+ findMenuItem = new JMenuItem();
windowMenu = new JMenu();
nextEditorMenuItem = new JMenuItem();
previousEditorMenuItem = new JMenuItem();
@@ -237,6 +245,20 @@ public class FlatThemeFileEditor
}
menuBar.add(fileMenu);
+ //======== editMenu ========
+ {
+ editMenu.setText("Edit");
+ editMenu.setMnemonic('E');
+
+ //---- findMenuItem ----
+ findMenuItem.setText("Find...");
+ findMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ findMenuItem.setMnemonic('F');
+ findMenuItem.addActionListener(e -> find());
+ editMenu.add(findMenuItem);
+ }
+ menuBar.add(editMenu);
+
//======== windowMenu ========
{
windowMenu.setText("Window");
@@ -294,6 +316,8 @@ public class FlatThemeFileEditor
private JMenu fileMenu;
private JMenuItem saveAllMenuItem;
private JMenuItem exitMenuItem;
+ private JMenu editMenu;
+ private JMenuItem findMenuItem;
private JMenu windowMenu;
private JMenuItem nextEditorMenuItem;
private JMenuItem previousEditorMenuItem;
diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.jfd b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.jfd
index 5dad47f3..d424ce74 100644
--- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.jfd
+++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemeFileEditor.jfd
@@ -63,6 +63,18 @@ new FormModel {
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "exit", false ) )
} )
} )
+ add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
+ name: "editMenu"
+ "text": "Edit"
+ "mnemonic": 69
+ add( new FormComponent( "javax.swing.JMenuItem" ) {
+ name: "findMenuItem"
+ "text": "Find..."
+ "accelerator": static javax.swing.KeyStroke getKeyStroke( 70, 4226, false )
+ "mnemonic": 70
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "find", false ) )
+ } )
+ } )
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "windowMenu"
"text": "Window"
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/LICENSE.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/LICENSE.txt
new file mode 100644
index 00000000..186cd751
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/LICENSE.txt
@@ -0,0 +1,3 @@
+The icons in this folder are from IntelliJ IDEA Community Edition,
+which is licensed under the Apache 2.0 license. Copyright 2000-2019 JetBrains s.r.o.
+See: https://github.com/JetBrains/intellij-community/
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/close.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/close.svg
new file mode 100644
index 00000000..7f63bd7f
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/close.svg
@@ -0,0 +1,3 @@
+
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowNextMatches.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowNextMatches.svg
new file mode 100644
index 00000000..62f0f972
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowNextMatches.svg
@@ -0,0 +1,3 @@
+
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowPrevMatches.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowPrevMatches.svg
new file mode 100644
index 00000000..88d78e89
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/findAndShowPrevMatches.svg
@@ -0,0 +1,3 @@
+
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/matchCase.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/matchCase.svg
new file mode 100644
index 00000000..874ee768
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/matchCase.svg
@@ -0,0 +1,8 @@
+
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/regex.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/regex.svg
new file mode 100644
index 00000000..68316ab9
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/regex.svg
@@ -0,0 +1,6 @@
+
diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/words.svg b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/words.svg
new file mode 100644
index 00000000..353e3bb4
--- /dev/null
+++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/icons/words.svg
@@ -0,0 +1,5 @@
+