added searchable component tree

This commit is contained in:
bancika
2016-12-26 17:29:42 +01:00
parent 62893ffb7c
commit ebb6a57ee8
10 changed files with 414 additions and 3 deletions
@@ -36,7 +36,7 @@ public enum IconLoader {
"cloud_edit.png"), CloudUpload("cloud_upload.png"), NavLeftBlue("nav_left_blue.png"), NavRightBlue(
"nav_right_blue.png"), MissingImage("missing_image.png"), CloudBg("cloud_bg.png"), CloudBig("cloud_big.png"), CloudWait(
"cloud_wait.png"), Spinning("spinning.gif"), Megaphone("megaphone.png"), Download("download.png"), Eye("eye.png"), Messages(
"messages.png");
"messages.png"), SearchBox("search-box.png"), Screwdriver("screwdriver.png"), Hammer("hammer.png");
protected String name;
Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -27,6 +27,7 @@ import org.diylc.images.IconLoader;
import org.diylc.presenter.Presenter;
import org.diylc.swing.gui.DialogFactory;
import org.diylc.swing.gui.editor.PropertyEditorDialog;
import org.diylc.swing.plugins.config.ConfigPlugin;
import org.diylc.swing.plugins.edit.ComponentTransferable;
import org.diylc.swing.plugins.file.BomDialog;
import org.diylc.swing.plugins.file.FileFilterEnum;
@@ -160,6 +161,10 @@ public class ActionFactory {
return new ThemeAction(plugInPort, theme);
}
public ComponentBrowserAction createComponentBrowserAction(String browserType) {
return new ComponentBrowserAction(browserType);
}
public RenumberAction createRenumberAction(IPlugInPort plugInPort, boolean xAxisFirst) {
return new RenumberAction(plugInPort, xAxisFirst);
}
@@ -1005,6 +1010,30 @@ public class ActionFactory {
}
}
public static class ComponentBrowserAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private String browserType;
public ComponentBrowserAction(String browserType) {
super();
this.browserType = browserType;
putValue(AbstractAction.NAME, browserType);
putValue(IView.RADIO_BUTTON_GROUP_KEY, "componentBrowser");
putValue(AbstractAction.SELECTED_KEY,
browserType.equals(ConfigurationManager.getInstance().readString(ConfigPlugin.COMPONENT_BROWSER, ConfigPlugin.SEARCHABLE_TREE)));
}
@Override
public void actionPerformed(ActionEvent e) {
LOG.info(getValue(AbstractAction.NAME) + " triggered");
ConfigurationManager.getInstance().writeValue(ConfigPlugin.COMPONENT_BROWSER, browserType);
}
}
public static class RenumberAction extends AbstractAction {
private static final long serialVersionUID = 1L;
@@ -59,6 +59,7 @@ import org.diylc.swing.plugins.help.HelpMenuPlugin;
import org.diylc.swing.plugins.layers.LayersMenuPlugin;
import org.diylc.swing.plugins.statusbar.StatusBar;
import org.diylc.swing.plugins.toolbox.ToolBox;
import org.diylc.swing.plugins.tree.ComponentTree;
import org.diylc.swingframework.ButtonDialog;
public class MainFrame extends JFrame implements ISwingUI {
@@ -95,6 +96,7 @@ public class MainFrame extends JFrame implements ISwingUI {
this.presenter = new Presenter(this);
presenter.installPlugin(new ToolBox(this));
presenter.installPlugin(new ComponentTree(this));
presenter.installPlugin(new FileMenuPlugin(this));
presenter.installPlugin(new EditMenuPlugin(this));
presenter.installPlugin(new ConfigPlugin(this));
@@ -29,6 +29,10 @@ public class ConfigPlugin implements IPlugIn {
private static final String CONFIG_MENU = "Config";
private static final String THEME_MENU = "Theme";
private static final String COMPONENT_BROWSER_MENU = "Toolbox";
public static final String COMPONENT_BROWSER = "componentBrowser";
public static final String SEARCHABLE_TREE = "Searchable Tree";
public static final String TABBED_TOOLBAR = "Tabbed Toolbar";
private ISwingUI swingUI;
@@ -43,8 +47,8 @@ public class ConfigPlugin implements IPlugIn {
ActionFactory.getInstance()
.createConfigAction(plugInPort, "Anti-Aliasing", IPlugInPort.ANTI_ALIASING_KEY, true), CONFIG_MENU);
swingUI.injectMenuAction(
ActionFactory.getInstance()
.createConfigAction(plugInPort, "Auto-Create Pads", SolderPadAutoCreator.AUTO_PADS_KEY, false), CONFIG_MENU);
ActionFactory.getInstance().createConfigAction(plugInPort, "Auto-Create Pads",
SolderPadAutoCreator.AUTO_PADS_KEY, false), CONFIG_MENU);
swingUI.injectMenuAction(
ActionFactory.getInstance().createConfigAction(plugInPort, "Auto-Edit Mode", IPlugInPort.AUTO_EDIT_KEY, true),
CONFIG_MENU);
@@ -87,6 +91,13 @@ public class ConfigPlugin implements IPlugIn {
}
}
}
swingUI.injectSubmenu(COMPONENT_BROWSER_MENU, IconLoader.Hammer.getIcon(), CONFIG_MENU);
swingUI.injectMenuAction(ActionFactory.getInstance().createComponentBrowserAction(SEARCHABLE_TREE),
COMPONENT_BROWSER_MENU);
swingUI.injectMenuAction(ActionFactory.getInstance().createComponentBrowserAction(TABBED_TOOLBAR),
COMPONENT_BROWSER_MENU);
}
@Override
@@ -5,11 +5,14 @@ import java.util.EnumSet;
import javax.swing.SwingConstants;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.IConfigListener;
import org.diylc.common.BadPositionException;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.swing.ISwingUI;
import org.diylc.swing.plugins.config.ConfigPlugin;
import org.diylc.swing.plugins.statusbar.StatusBar;
@@ -34,6 +37,18 @@ public class ToolBox implements IPlugIn {
} catch (BadPositionException e) {
LOG.error("Could not install the toolbox", e);
}
ConfigurationManager.getInstance().addConfigListener(ConfigPlugin.COMPONENT_BROWSER, new IConfigListener() {
@Override
public void valueChanged(String key, Object value) {
getComponentTabbedPane().setVisible(
ConfigPlugin.COMPONENT_BROWSER.equals(key) && ConfigPlugin.TABBED_TOOLBAR.equals(value));
}
});
getComponentTabbedPane().setVisible(
ConfigurationManager.getInstance().readString(ConfigPlugin.COMPONENT_BROWSER, ConfigPlugin.SEARCHABLE_TREE)
.equals(ConfigPlugin.TABBED_TOOLBAR));
}
public ComponentTabbedPane getComponentTabbedPane() {
@@ -0,0 +1,72 @@
package org.diylc.swing.plugins.tree;
import java.util.EnumSet;
import javax.swing.SwingConstants;
import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.IConfigListener;
import org.diylc.common.BadPositionException;
import org.diylc.common.EventType;
import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort;
import org.diylc.swing.ISwingUI;
import org.diylc.swing.plugins.config.ConfigPlugin;
import org.diylc.swing.plugins.statusbar.StatusBar;
public class ComponentTree implements IPlugIn {
private static final Logger LOG = Logger.getLogger(StatusBar.class);
private ISwingUI swingUI;
private IPlugInPort plugInPort;
private TreePanel treePanel;
public ComponentTree(ISwingUI swingUI) {
this.swingUI = swingUI;
}
@Override
public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort;
try {
swingUI.injectGUIComponent(getTreePanel(), SwingConstants.LEFT);
} catch (BadPositionException e) {
LOG.error("Could not install the component tree", e);
}
ConfigurationManager.getInstance().addConfigListener(ConfigPlugin.COMPONENT_BROWSER, new IConfigListener() {
@Override
public void valueChanged(String key, Object value) {
getTreePanel().setVisible(
ConfigPlugin.COMPONENT_BROWSER.equals(key) && ConfigPlugin.SEARCHABLE_TREE.equals(value));
}
});
getTreePanel().setVisible(
ConfigurationManager.getInstance().readString(ConfigPlugin.COMPONENT_BROWSER, ConfigPlugin.SEARCHABLE_TREE)
.equals(ConfigPlugin.SEARCHABLE_TREE));
}
public TreePanel getTreePanel() {
if (treePanel == null) {
treePanel = new TreePanel(plugInPort);
}
return treePanel;
}
@Override
public EnumSet<EventType> getSubscribedEventTypes() {
// TODO Auto-generated method stub
return null;
}
@Override
public void processMessage(EventType eventType, Object... params) {
// TODO Auto-generated method stub
}
}
@@ -0,0 +1,282 @@
package org.diylc.swing.plugins.tree;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.diylc.common.ComponentType;
import org.diylc.common.IPlugInPort;
import org.diylc.images.IconLoader;
public class TreePanel extends JPanel {
private static final long serialVersionUID = 1L;
private DefaultTreeModel treeModel;
private JTree tree;
private JTextField searchField;
private IPlugInPort plugInPort;
public TreePanel(IPlugInPort plugInPort) {
this.plugInPort = plugInPort;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 0;
add(getSearchField(), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 1;
gbc.weightx = 1;
JScrollPane scroll = new JScrollPane(getTree());
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
add(scroll, gbc);
setPreferredSize(new Dimension(240, 200));
}
public DefaultTreeModel getTreeModel() {
if (treeModel == null) {
final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Components", true);
Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes();
List<String> categories = new ArrayList<String>(componentTypes.keySet());
Collections.sort(categories);
for (String category : categories) {
final DefaultMutableTreeNode categoryNode = new DefaultMutableTreeNode(new Payload(category));
rootNode.add(categoryNode);
for (ComponentType type : componentTypes.get(category)) {
final DefaultMutableTreeNode componentNode = new DefaultMutableTreeNode(new Payload(type), false);
categoryNode.add(componentNode);
}
}
treeModel = new DefaultTreeModel(rootNode);
}
return treeModel;
}
public JTree getTree() {
if (tree == null) {
tree = new JTree(getTreeModel());
tree.setRootVisible(false);
tree.setCellRenderer(new ComponentCellRenderer());
tree.setRowHeight(0);
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
Object c = e.getPath().getLastPathComponent();
if (c != null && c.getClass().equals(DefaultMutableTreeNode.class)) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) c;
Object obj = node.getUserObject();
if (obj != null && obj.getClass().equals(Payload.class)) {
Payload payload = (Payload) obj;
plugInPort.setNewComponentTypeSlot(payload.getComponentType(), null);
}
}
}
});
}
return tree;
}
public JTextField getSearchField() {
if (searchField == null) {
searchField = new JTextField() {
private static final long serialVersionUID = 1L;
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
Icon icon = IconLoader.SearchBox.getIcon();
icon.paintIcon(searchField, g2d, searchField.getWidth() - 18, 3);
if (searchField.getText().trim().length() == 0 && !searchField.hasFocus()) {
g2d.setColor(Color.gray);
g2d.setFont(searchField.getFont());
g2d.drawString("Search", 4, 3 + searchField.getFont().getSize());
}
}
};
searchField.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
searchField.repaint();
}
@Override
public void focusLost(FocusEvent e) {
searchField.repaint();
}
});
searchField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
process();
}
public void removeUpdate(DocumentEvent e) {
process();
}
public void insertUpdate(DocumentEvent e) {
process();
}
public void process() {
String text = searchField.getText();
DefaultTreeModel model = getTreeModel();
DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) model.getRoot();
for (int i = 0; i < model.getChildCount(rootNode); i++) {
int visibleCount = 0;
DefaultMutableTreeNode categoryNode = (DefaultMutableTreeNode) model.getChild(rootNode, i);
for (int j = 0; j < model.getChildCount(categoryNode); j++) {
DefaultMutableTreeNode componentNode = (DefaultMutableTreeNode) model.getChild(categoryNode, j);
Object obj = componentNode.getUserObject();
if (obj != null && obj.getClass().equals(Payload.class)) {
Payload payload = (Payload) obj;
boolean visible = false;
if (text.trim().length() == 0) {
visible = true;
} else {
ComponentType type = payload.getComponentType();
visible =
type.getName().toLowerCase().contains(text.toLowerCase())
|| type.getDescription().toLowerCase().contains(text.toLowerCase())
|| type.getCategory().toLowerCase().contains(text.toLowerCase());
}
if (visible != payload.isVisible()) {
payload.setVisible(visible);
model.nodeStructureChanged(componentNode);
}
if (visible)
visibleCount++;
}
}
Object obj = categoryNode.getUserObject();
if (obj != null && obj.getClass().equals(Payload.class)) {
Payload payload = (Payload) obj;
boolean visible = visibleCount > 0;
if (visible != payload.isVisible()) {
payload.setVisible(visible);
model.nodeStructureChanged(rootNode);
}
if (visible && text.trim().length() > 0) {
tree.expandPath(new TreePath(categoryNode.getPath()));
}
}
}
getTree().invalidate();
}
});
}
return searchField;
}
public class ComponentCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean selected,
final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
Object obj = ((DefaultMutableTreeNode) value).getUserObject();
if (obj != null && obj.getClass().equals(Payload.class)) {
Payload type = (Payload) obj;
if (type.getComponentType() == null) {
if (type.isVisible())
setPreferredSize(new Dimension(240, 20));
else
setPreferredSize(new Dimension(0, 0));
} else {
setIcon(type.getComponentType().getIcon());
if (type.isVisible())
setPreferredSize(new Dimension(240, 32));
else
setPreferredSize(new Dimension(0, 0));
}
}
return this;
}
}
public class Payload {
private ComponentType componentType;
private String category;
private boolean isVisible;
public Payload(ComponentType componentType) {
super();
this.componentType = componentType;
this.isVisible = true;
}
public Payload(String category) {
super();
this.category = category;
this.isVisible = true;
}
public ComponentType getComponentType() {
return componentType;
}
public boolean isVisible() {
return isVisible;
}
public void setVisible(boolean isVisible) {
this.isVisible = isVisible;
}
@Override
public String toString() {
return componentType == null ? category : componentType.getName();
}
}
}