Ability to tag components and building blocks as favorites

This commit is contained in:
Branislav Stojkovic
2019-03-09 10:42:39 +01:00
parent 8ed2c0c9a5
commit d544797047
6 changed files with 229 additions and 8 deletions
@@ -0,0 +1,88 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2018 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.common;
import java.io.Serializable;
public class Favorite implements Serializable, Comparable<Favorite> {
private static final long serialVersionUID = 1L;
private FavoriteType type;
private String name;
public Favorite(FavoriteType type, String name) {
super();
this.type = type;
this.name = name;
}
public FavoriteType getType() {
return type;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Favorite other = (Favorite) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type != other.type)
return false;
return true;
}
@Override
public String toString() {
return type + ":" + name;
}
public enum FavoriteType {
Component, Block
}
@Override
public int compareTo(Favorite o) {
return name.compareToIgnoreCase(o.getName());
}
}
@@ -75,6 +75,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
public static final String HIGHLIGHT_CONTINUITY_AREA = "highlightContinuityArea"; public static final String HIGHLIGHT_CONTINUITY_AREA = "highlightContinuityArea";
public static final String HARDWARE_ACCELERATION = "hardwareAcceleration"; public static final String HARDWARE_ACCELERATION = "hardwareAcceleration";
public static final String EXTRA_SPACE_KEY = "extraSpace"; public static final String EXTRA_SPACE_KEY = "extraSpace";
public static final String FAVORITES_KEY = "favorites";
public static final int DND_TOGGLE_STICKY = 0x1; public static final int DND_TOGGLE_STICKY = 0x1;
public static final int DND_TOGGLE_SNAP = 0x40000000; public static final int DND_TOGGLE_SNAP = 0x40000000;
@@ -63,7 +63,7 @@ public enum IconLoader {
"component_add.png"), History("history.png"), DocumentPlain("document_plain.png"), FitToSize("fit_to_size.png"), DocumentsGear( "component_add.png"), History("history.png"), DocumentPlain("document_plain.png"), FitToSize("fit_to_size.png"), DocumentsGear(
"documents_gear.png"), SplashResistor("splash_resistor.png"), SplashCeramic("splash_ceramic.png"), SplashElectrolytic( "documents_gear.png"), SplashResistor("splash_resistor.png"), SplashCeramic("splash_ceramic.png"), SplashElectrolytic(
"splash_electrolytic.png"), SplashFilm("splash_film.png"), Splash("splash.png"), Help("help2.png"), ScrollInformation("scroll_information.png"), "splash_electrolytic.png"), SplashFilm("splash_film.png"), Splash("splash.png"), Help("help2.png"), ScrollInformation("scroll_information.png"),
Node("node.png"), Web("web.png"), Guitar("guitar.png"), Scientist("scientist.png"); Node("node.png"), Web("web.png"), Guitar("guitar.png"), Scientist("scientist.png"), StarGrey("star_grey.png"), StarBlue("star_blue.png");
protected String name; protected String name;
Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

@@ -36,7 +36,6 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -63,6 +62,7 @@ import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener; import javax.swing.event.PopupMenuListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
@@ -72,9 +72,12 @@ import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.TreeSelectionModel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.log4j.lf5.viewer.categoryexplorer.TreeModelAdapter;
import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.IConfigListener; import org.diylc.appframework.miscutils.IConfigListener;
import org.diylc.common.ComponentType; import org.diylc.common.ComponentType;
import org.diylc.common.Favorite;
import org.diylc.common.Favorite.FavoriteType;
import org.diylc.common.IBlockProcessor.InvalidBlockException; import org.diylc.common.IBlockProcessor.InvalidBlockException;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
@@ -99,11 +102,14 @@ public class TreePanel extends JPanel {
private JTextField searchField; private JTextField searchField;
private DefaultMutableTreeNode recentNode; private DefaultMutableTreeNode recentNode;
private DefaultMutableTreeNode blocksNode; private DefaultMutableTreeNode blocksNode;
private DefaultMutableTreeNode favoritesNode;
private List<String> recentComponents; private List<String> recentComponents;
private List<Favorite> favorites;
private List<String> blocks; private List<String> blocks;
private IPlugInPort plugInPort; private IPlugInPort plugInPort;
private ISwingUI swingUI; private ISwingUI swingUI;
private boolean initializing = false;
private JPopupMenu popup; private JPopupMenu popup;
@@ -175,6 +181,20 @@ public class TreePanel extends JPanel {
} }
}); });
ConfigurationManager.getInstance().addConfigListener(IPlugInPort.FAVORITES_KEY, new IConfigListener() {
@SuppressWarnings("unchecked")
@Override
public void valueChanged(String key, Object value) {
List<Favorite> newFavorites = (List<Favorite>) value;
if (newFavorites != null && !newFavorites.equals(TreePanel.this.favorites)) {
LOG.info("Detected favorites change");
refreshFavorites(newFavorites);
} else
LOG.info("Detected no favorites change");
}
});
getTree().expandRow(0); getTree().expandRow(0);
initializeDnD(); initializeDnD();
@@ -199,6 +219,7 @@ public class TreePanel extends JPanel {
public DefaultMutableTreeNode getRecentNode() { public DefaultMutableTreeNode getRecentNode() {
if (this.recentNode == null) { if (this.recentNode == null) {
this.recentNode = new DefaultMutableTreeNode(new Payload("(Recently Used)", null), true); this.recentNode = new DefaultMutableTreeNode(new Payload("(Recently Used)", null), true);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<String> recent = List<String> recent =
(List<String>) ConfigurationManager.getInstance().readObject(IPlugInPort.RECENT_COMPONENTS_KEY, null); (List<String>) ConfigurationManager.getInstance().readObject(IPlugInPort.RECENT_COMPONENTS_KEY, null);
@@ -215,6 +236,7 @@ public class TreePanel extends JPanel {
public DefaultMutableTreeNode getBlocksNode() { public DefaultMutableTreeNode getBlocksNode() {
if (this.blocksNode == null) { if (this.blocksNode == null) {
this.blocksNode = new DefaultMutableTreeNode(new Payload("(Building Blocks)", null), true); this.blocksNode = new DefaultMutableTreeNode(new Payload("(Building Blocks)", null), true);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, List<IDIYComponent<?>>> newBlocks = Map<String, List<IDIYComponent<?>>> newBlocks =
(Map<String, List<IDIYComponent<?>>>) ConfigurationManager.getInstance().readObject( (Map<String, List<IDIYComponent<?>>>) ConfigurationManager.getInstance().readObject(
@@ -223,7 +245,6 @@ public class TreePanel extends JPanel {
List<String> blockNames = new ArrayList<String>(newBlocks.keySet()); List<String> blockNames = new ArrayList<String>(newBlocks.keySet());
Collections.sort(blockNames); Collections.sort(blockNames);
refreshBuildingBlocks(blockNames); refreshBuildingBlocks(blockNames);
this.blocks = blockNames;
} else { } else {
this.blocks = new ArrayList<String>(); this.blocks = new ArrayList<String>();
} }
@@ -231,6 +252,21 @@ public class TreePanel extends JPanel {
return this.blocksNode; return this.blocksNode;
} }
public DefaultMutableTreeNode getFavoritesNode() {
if (this.favoritesNode == null) {
this.favoritesNode = new DefaultMutableTreeNode(new Payload("(Favorites)", null), true);
@SuppressWarnings("unchecked")
List<Favorite> favorites = (List<Favorite>) ConfigurationManager.getInstance().readObject(IPlugInPort.FAVORITES_KEY, null);
if (favorites != null) {
refreshFavorites(favorites);
} else {
this.favorites = new ArrayList<Favorite>();
}
}
return this.favoritesNode;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void refreshRecentComponents(List<String> recentComponentClassList) { private void refreshRecentComponents(List<String> recentComponentClassList) {
getRecentNode().removeAllChildren(); getRecentNode().removeAllChildren();
@@ -260,6 +296,7 @@ public class TreePanel extends JPanel {
LOG.error("Could not create recent component button for " + componentClassName, e); LOG.error("Could not create recent component button for " + componentClassName, e);
} }
} }
if (!initializing)
getTreeModel().nodeStructureChanged(getRecentNode()); getTreeModel().nodeStructureChanged(getRecentNode());
} }
@@ -291,14 +328,72 @@ public class TreePanel extends JPanel {
payload.setVisible(visible); payload.setVisible(visible);
getBlocksNode().add(componentNode); getBlocksNode().add(componentNode);
} }
if (!initializing)
getTreeModel().nodeStructureChanged(getBlocksNode()); getTreeModel().nodeStructureChanged(getBlocksNode());
} }
private void refreshFavorites(List<Favorite> favorites) {
this.favorites = new ArrayList<Favorite>(favorites);
getFavoritesNode().removeAllChildren();
Map<String, List<ComponentType>> types = plugInPort.getComponentTypes();
Map<String, ComponentType> typesByClass = new HashMap<String, ComponentType>();
for (Map.Entry<String, List<ComponentType>> e : types.entrySet())
for (ComponentType c : e.getValue())
typesByClass.put(c.getInstanceClass().getCanonicalName(), c);
for (Favorite f : favorites) {
if (f.getType() == FavoriteType.Component) {
final ComponentType type = typesByClass.get(f.getName());
if (type != null) {
DefaultMutableTreeNode componentNode = new DefaultMutableTreeNode(new Payload(type, new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
plugInPort.setNewComponentTypeSlot(type, null, false);
}
}), false);
getFavoritesNode().add(componentNode);
}
} else if (f.getType() == FavoriteType.Block) {
final String block = f.getName();
Payload payload = new Payload(block, new MouseAdapter() {
long previousActionTime = 0;
@Override
public void mouseClicked(MouseEvent e) {
if (e == null || SwingUtilities.isLeftMouseButton(e) && System.currentTimeMillis() - previousActionTime > 100) {
previousActionTime = System.currentTimeMillis();
try {
plugInPort.loadBlock(block);
} catch (InvalidBlockException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
final DefaultMutableTreeNode componentNode = new DefaultMutableTreeNode(payload, false);
String text = getSearchField().getText();
boolean visible = text.trim().length() == 0 || block.toLowerCase().contains(text.toLowerCase());
payload.setVisible(visible);
getFavoritesNode().add(componentNode);
}
}
if (!initializing)
getTreeModel().nodeStructureChanged(getFavoritesNode());
}
public DefaultTreeModel getTreeModel() { public DefaultTreeModel getTreeModel() {
if (treeModel == null) { if (treeModel == null) {
final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Components", true); final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Components", true);
initializing = true;
rootNode.add(getFavoritesNode());
rootNode.add(getRecentNode()); rootNode.add(getRecentNode());
rootNode.add(getBlocksNode()); rootNode.add(getBlocksNode());
initializing = false;
Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes(); Map<String, List<ComponentType>> componentTypes = plugInPort.getComponentTypes();
List<String> categories = new ArrayList<String>(componentTypes.keySet()); List<String> categories = new ArrayList<String>(componentTypes.keySet());
Collections.sort(categories); Collections.sort(categories);
@@ -317,6 +412,18 @@ public class TreePanel extends JPanel {
} }
} }
treeModel = new DefaultTreeModel(rootNode); treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new TreeModelAdapter() {
@Override
public void treeNodesRemoved(TreeModelEvent e) {
super.treeNodesRemoved(e);
}
@Override
public void treeNodesChanged(TreeModelEvent e) {
// TODO Auto-generated method stub
super.treeNodesChanged(e);
}
});
} }
return treeModel; return treeModel;
} }
@@ -460,6 +567,27 @@ public class TreePanel extends JPanel {
shortcutSubmenu.add(item); shortcutSubmenu.add(item);
} }
final Favorite fav = new Favorite(componentType == null ? FavoriteType.Block : FavoriteType.Component, componentType == null ? payload.toString() : componentType.getInstanceClass()
.getCanonicalName());
final boolean isFavorite = favorites != null && favorites.indexOf(fav) >= 0;
final JMenuItem favoritesItem = new JMenuItem(isFavorite ? "Remove From Favorites" : "Add To Favorites",
isFavorite ? IconLoader.StarBlue.getIcon() : IconLoader.StarGrey.getIcon());
favoritesItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<Favorite> favorites = new ArrayList<Favorite>(TreePanel.this.favorites);
if (isFavorite) {
favorites.remove(fav);
} else {
favorites.add(fav);
Collections.sort(favorites);
}
ConfigurationManager.getInstance().writeValue(IPlugInPort.FAVORITES_KEY, favorites);
}
});
popup.add(favoritesItem);
if (componentType != null) { if (componentType != null) {
popup.add(new SelectAllAction(plugInPort, componentType)); popup.add(new SelectAllAction(plugInPort, componentType));
popup.add(shortcutSubmenu); popup.add(shortcutSubmenu);
+4
View File
@@ -2578,6 +2578,10 @@
<releaseDate>2019-03-02 00:00:00.000 CET</releaseDate> <releaseDate>2019-03-02 00:00:00.000 CET</releaseDate>
<name></name> <name></name>
<changes> <changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Ability to tag components and building blocks as favorites</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType> <changeType>BUG_FIX</changeType>
<description>"Highlight Connected Areas" doesn't follow multiple chained wires and jumpers</description> <description>"Highlight Connected Areas" doesn't follow multiple chained wires and jumpers</description>