adds a first gui integration, see #645

This commit is contained in:
hneemann 2021-02-11 13:30:15 +01:00
parent e1f5d4da4c
commit 3362c09b62
7 changed files with 153 additions and 2 deletions

View File

@ -63,6 +63,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
@ -391,7 +393,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
if (treeCheckBox.isSelected()) {
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
treeModel = new LibraryTreeModel(library);
split.setLeftComponent(new JScrollPane(new SelectTree(treeModel, circuitComponent, shapeFactory, insertHistory)));
split.setLeftComponent(createTreeComponent());
split.setRightComponent(circuitScrollPanel);
getContentPane().add(split);
componentOnPane = split;
@ -450,6 +452,48 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
view.add(viewHelp.createJMenuItem());
}
private JComponent createTreeComponent() {
JPanel panel = new JPanel(new BorderLayout());
JPanel field = new JPanel(new BorderLayout());
JTextField textField = new SearchTextField();
field.add(textField);
JButton clearButton = new JButton(new AbstractAction("\u2717") {
@Override
public void actionPerformed(ActionEvent actionEvent) {
textField.setText("");
}
});
clearButton.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
field.add(clearButton, BorderLayout.EAST);
panel.add(field, BorderLayout.NORTH);
textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
SelectTree tree = new SelectTree(treeModel, circuitComponent, shapeFactory, insertHistory);
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent documentEvent) {
changedUpdate(documentEvent);
}
@Override
public void removeUpdate(DocumentEvent documentEvent) {
changedUpdate(documentEvent);
}
@Override
public void changedUpdate(DocumentEvent documentEvent) {
String text = textField.getText().trim();
if (text.isEmpty())
treeModel = new LibraryTreeModel(library);
else
treeModel = new LibraryTreeModel(library, new TextSearchFilter(text));
tree.setModel(treeModel);
}
});
panel.add(new JScrollPane(tree));
return panel;
}
private void clearPane() {
circuitComponent.setCircuit(new Circuit());
setFilename(null, true);

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.gui;
import de.neemann.digital.lang.Lang;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* JTextField which shows the text "search" if the field is empty.
*/
public class SearchTextField extends JTextField {
/**
* Creates a new instance
*/
public SearchTextField() {
addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
repaint();
}
@Override
public void focusLost(FocusEvent e) {
repaint();
}
});
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (getText().isEmpty() && !hasFocus()) {
g.setColor(Color.GRAY);
g.drawString(Lang.get("msg_search"), 5, (getHeight() + getFont().getSize()) / 2);
}
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2021 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.gui;
import de.neemann.digital.draw.library.LibraryNode;
import de.neemann.digital.gui.components.tree.LibraryTreeModel;
/**
* Used to filter nodes in the tree view
*/
public class TextSearchFilter implements LibraryTreeModel.Filter {
private final String filterStr;
/**
* Creates a new filter
*
* @param filterStr the search string
*/
public TextSearchFilter(String filterStr) {
this.filterStr = filterStr.toLowerCase();
}
@Override
public boolean accept(LibraryNode node) {
return node.getName().toLowerCase().contains(filterStr)
|| node.getTranslatedName().toLowerCase().contains(filterStr);
}
}

View File

@ -111,6 +111,13 @@ public class LibraryTreeModel implements TreeModel, LibraryListener {
}
}
/**
* @return true if this model is filtered
*/
public boolean isFiltered() {
return filter != null;
}
private Container getContainer(LibraryNode libraryNode) {
Container c = map.get(libraryNode);
if (c == null) {

View File

@ -22,6 +22,7 @@ import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Enumeration;
/**
* Tree to select items
@ -29,6 +30,7 @@ import java.io.IOException;
public class SelectTree extends JTree {
private final ShapeFactory shapeFactory;
private Enumeration<TreePath> storedExpanded;
/**
* Create a new instance
@ -68,6 +70,27 @@ public class SelectTree extends JTree {
expandPath(new TreePath(model.getFirstLeafParent().getPath()));
}
/**
* Sets a new model to this SelectTree.
*
* @param newModel the new model
*/
public void setModel(LibraryTreeModel newModel) {
LibraryTreeModel oldModel = (LibraryTreeModel) getModel();
if (!oldModel.isFiltered() && newModel.isFiltered())
storedExpanded = getExpandedDescendants(new TreePath(getModel().getRoot()));
boolean restore = oldModel.isFiltered() && !newModel.isFiltered();
super.setModel(newModel);
if (restore && storedExpanded != null) {
while (storedExpanded.hasMoreElements())
expandPath(storedExpanded.nextElement());
storedExpanded = null;
} else
expandPath(new TreePath(newModel.getFirstLeafParent().getPath()));
}
@Override
public String getToolTipText(MouseEvent e) {
TreePath selPath = getPathForLocation(e.getX(), e.getY());

View File

@ -51,7 +51,7 @@
<string name="elem_Help_inputs">Eingänge</string>
<string name="elem_Help_outputs">Ausgänge</string>
<string name="elem_Help_attributes">Veränderbare Attribute</string>
<string name="msg_search">Suche</string>
<!-- logik -->

View File

@ -51,6 +51,7 @@
<string name="elem_Help_inputs">Inputs</string>
<string name="elem_Help_outputs">Outputs</string>
<string name="elem_Help_attributes">Attributes</string>
<string name="msg_search">search</string>
<!-- logic -->