From 56b3d35420602de81335f7bf67cea3956e44653b Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Fri, 19 Jan 2024 12:40:03 -0800 Subject: [PATCH] Factory<> is now NodeFactory --- .../com/marginallyclever/ro3/Registry.java | 39 ++++++------- .../ro3/apps/actions/AddNode.java | 7 +-- .../nodeselector/NodeSelectionDialog.java | 3 + .../ro3/apps/nodetreeview/NodeTreeView.java | 8 +-- .../ro3/apps/shared/SearchBar.java | 5 +- .../{ => node/nodefactory}/NodeFactory.java | 55 +++++++++---------- .../nodefactory}/NodeFactoryPanel.java | 53 ++++++++++-------- .../nodefactory}/NodeTreeBranchRenderer.java | 4 +- .../marginallyclever/ro3/TestAllPanels.java | 2 +- 9 files changed, 92 insertions(+), 84 deletions(-) rename src/main/java/com/marginallyclever/ro3/{ => node/nodefactory}/NodeFactory.java (50%) rename src/main/java/com/marginallyclever/ro3/{apps => node/nodefactory}/NodeFactoryPanel.java (74%) rename src/main/java/com/marginallyclever/ro3/{apps/nodetreeview => node/nodefactory}/NodeTreeBranchRenderer.java (81%) diff --git a/src/main/java/com/marginallyclever/ro3/Registry.java b/src/main/java/com/marginallyclever/ro3/Registry.java index 41fd96be7..691b662ce 100644 --- a/src/main/java/com/marginallyclever/ro3/Registry.java +++ b/src/main/java/com/marginallyclever/ro3/Registry.java @@ -2,6 +2,7 @@ import com.marginallyclever.ro3.listwithevents.ListWithEvents; import com.marginallyclever.ro3.mesh.MeshFactory; +import com.marginallyclever.ro3.node.nodefactory.NodeFactory; import com.marginallyclever.ro3.node.nodes.*; import com.marginallyclever.ro3.node.Node; import com.marginallyclever.ro3.node.nodes.limbplanner.LimbPlanner; @@ -24,7 +25,7 @@ public class Registry { public static final EventListenerList listeners = new EventListenerList(); public static final TextureFactory textureFactory = new TextureFactory(); public static final MeshFactory meshFactory = new MeshFactory(); - public static final NodeFactory nodeFactory = new NodeFactory<>(Node.class); + public static final NodeFactory nodeFactory = new NodeFactory(); private static Node scene = new Node("Scene"); public static final ListWithEvents cameras = new ListWithEvents<>(); private static Camera activeCamera = null; @@ -32,24 +33,24 @@ public class Registry { public static void start() { nodeFactory.clear(); - NodeFactory.Category nodule = nodeFactory.getRoot().add("Node", Node::new); - nodule.add("DHParameter", DHParameter::new); - nodule.add("HingeJoint", HingeJoint::new); - nodule.add("LimbSolver", LimbSolver::new); - nodule.add("MarlinRobotArm", MarlinRobotArm::new); - nodule.add("Material", Material::new); - nodule.add("MeshInstance", MeshInstance::new); - nodule.add("Motor", Motor::new); - nodule.add("LimbPlanner", LimbPlanner::new); - NodeFactory.Category pose = nodule.add("Pose", Pose::new); - pose.add("Camera", Camera::new); - pose.add("LookAt", LookAt::new); - pose.add("Limb", Limb::new); - pose.add("AttachmentPoint", AttachmentPoint::new);/* - Factory.Category behavior = nodule.add("Behavior", null); - Factory.Category action = behavior.add("Action",null); - Factory.Category control = behavior.add("Control",null); - Factory.Category decorator = behavior.add("Decorator",null); + NodeFactory.Category nodule = nodeFactory.getRoot(); + nodule.add("DHParameter", DHParameter::new); + nodule.add("HingeJoint", HingeJoint::new); + nodule.add("LimbPlanner", LimbPlanner::new); + nodule.add("LimbSolver", LimbSolver::new); + nodule.add("MarlinRobotArm", MarlinRobotArm::new); + nodule.add("Material", Material::new); + nodule.add("MeshInstance", MeshInstance::new); + nodule.add("Motor", Motor::new); + NodeFactory.Category pose = nodule.add("Pose", Pose::new); + pose.add("AttachmentPoint", AttachmentPoint::new); + pose.add("Camera", Camera::new); + pose.add("Limb", Limb::new); + pose.add("LookAt", LookAt::new);/* + Factory.Category behavior = nodule.add("Behavior", null); + Factory.Category action = behavior.add("Action",null); + Factory.Category control = behavior.add("Control",null); + Factory.Category decorator = behavior.add("Decorator",null); decorator.add("ForceFailure", ForceFailure::new); decorator.add("ForceSuccess", ForceSuccess::new); decorator.add("Inverter", Inverter::new); diff --git a/src/main/java/com/marginallyclever/ro3/apps/actions/AddNode.java b/src/main/java/com/marginallyclever/ro3/apps/actions/AddNode.java index d4a0bbe1e..e4c8cfb36 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/actions/AddNode.java +++ b/src/main/java/com/marginallyclever/ro3/apps/actions/AddNode.java @@ -1,6 +1,6 @@ package com.marginallyclever.ro3.apps.actions; -import com.marginallyclever.ro3.apps.NodeFactoryPanel; +import com.marginallyclever.ro3.node.nodefactory.NodeFactoryPanel; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.Node; import com.marginallyclever.ro3.apps.UndoSystem; @@ -15,10 +15,9 @@ * {@link AddNode} is an {@link AbstractAction} to add a new instance of a {@link Node} to every selected branch of the * tree. It will ask the user which type of {@link Node} to add, then create an * {@link com.marginallyclever.ro3.apps.commands.AddNode} command to add the new {@link Node}. - * @param the type of {@link Node} to add */ -public class AddNode extends AbstractAction { - private static final NodeFactoryPanel nfd = new NodeFactoryPanel<>(Registry.nodeFactory); +public class AddNode extends AbstractAction { + private static final NodeFactoryPanel nfd = new NodeFactoryPanel(Registry.nodeFactory); public AddNode() { super(); diff --git a/src/main/java/com/marginallyclever/ro3/apps/nodeselector/NodeSelectionDialog.java b/src/main/java/com/marginallyclever/ro3/apps/nodeselector/NodeSelectionDialog.java index 44ca52ad5..40fbd4d8d 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/nodeselector/NodeSelectionDialog.java +++ b/src/main/java/com/marginallyclever/ro3/apps/nodeselector/NodeSelectionDialog.java @@ -75,9 +75,12 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } else { setForeground(Color.BLACK); } + setIcon(branch.getNode().getIcon()); + setToolTipText(branch.getNode().getClass().getSimpleName()); return this; } }); + tree.setToolTipText(""); } public void setSubject(T subject) { diff --git a/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeView.java b/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeView.java index fee01f86e..202cb74a5 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeView.java +++ b/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeView.java @@ -6,10 +6,8 @@ import com.marginallyclever.ro3.apps.actions.*; import com.marginallyclever.ro3.listwithevents.ItemAddedListener; import com.marginallyclever.ro3.listwithevents.ItemRemovedListener; -import com.marginallyclever.ro3.node.Node; -import com.marginallyclever.ro3.node.NodeAttachListener; -import com.marginallyclever.ro3.node.NodeDetachListener; -import com.marginallyclever.ro3.node.NodeRenameListener; +import com.marginallyclever.ro3.node.*; +import com.marginallyclever.ro3.node.nodefactory.NodeTreeBranchRenderer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -154,7 +152,7 @@ public void scanTree(Node toScan) { } private void buildToolBar() { - var addButton = new JButton(new AddNode<>()); + var addButton = new JButton(new AddNode()); var cutButton = new JButton(cutNode); var removeButton = new JButton(removeNode); var copyButton = new JButton(copyNode); diff --git a/src/main/java/com/marginallyclever/ro3/apps/shared/SearchBar.java b/src/main/java/com/marginallyclever/ro3/apps/shared/SearchBar.java index fa78e1a3b..26b269fd5 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/shared/SearchBar.java +++ b/src/main/java/com/marginallyclever/ro3/apps/shared/SearchBar.java @@ -44,6 +44,9 @@ public SearchBar(String text) { match.setText(text); match.getDocument().addDocumentListener(this); + isCaseSensitive.addActionListener(e -> fireMatchChange()); + isRegex.addActionListener(e -> fireMatchChange()); + addAncestorListener(new AncestorListener() { @Override public void ancestorAdded(javax.swing.event.AncestorEvent event) { @@ -73,7 +76,7 @@ public void changedUpdate(DocumentEvent e) { fireMatchChange(); } - public void fireMatchChange() { + protected void fireMatchChange() { String newValue = match.getText(); super.firePropertyChange("match", null, newValue); } diff --git a/src/main/java/com/marginallyclever/ro3/NodeFactory.java b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactory.java similarity index 50% rename from src/main/java/com/marginallyclever/ro3/NodeFactory.java rename to src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactory.java index 998d61032..3c25bb7f6 100644 --- a/src/main/java/com/marginallyclever/ro3/NodeFactory.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactory.java @@ -1,5 +1,6 @@ -package com.marginallyclever.ro3; +package com.marginallyclever.ro3.node.nodefactory; +import com.marginallyclever.ro3.node.Node; import org.reflections.Reflections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,35 +11,32 @@ import java.util.function.Supplier; /** - * A factory that can be used to create objects. It does not manage the objects it creates. - * @param The class of object to create. + * A factory that can be used to create Nodes. It does not manage the objects it creates. */ -public class NodeFactory { +public class NodeFactory { private static final Logger logger = LoggerFactory.getLogger(NodeFactory.class); - private final Class type; /** - * A category of objects. These categories can be nested in a tree. - * @param The class of object to create. + * Categories of Node types. These categories can be nested in a tree. */ - public static class Category { + public static class Category { private final String name; - private final Supplier supplier; - private final List> children = new ArrayList<>(); - private Category parent=null; + private final Supplier supplier; + private final List children = new ArrayList<>(); + private Category parent=null; - public Category(String name,Supplier supplier) { + public Category(String name,Supplier supplier) { this.name = name; this.supplier = supplier; } - public void add(Category c) { + public void add(Category c) { children.add(c); c.parent = this; } - public Category add(String name,Supplier supplier) { - Category item = new Category<>(name,supplier); + public Category add(String name, Supplier supplier) { + Category item = new Category(name,supplier); add(item); return item; } @@ -47,34 +45,33 @@ public String getName() { return name; } - public Category getParent() { + public Category getParent() { return parent; } - public List> getChildren() { + public List getChildren() { return children; } - public Supplier getSupplier() { + public Supplier getSupplier() { return supplier; } } - private final Category root = new Category<>("root",null); + private final Category root = new Category("Node",Node::new); - public NodeFactory(Class type) { - this.type = type; + public NodeFactory() { scan(); } - public Category getRoot() { + public Category getRoot() { return root; } - public Supplier getSupplierFor(String path) { - List> toCheck = new ArrayList<>(root.children); + public Supplier getSupplierFor(String path) { + List toCheck = new ArrayList<>(root.children); while(!toCheck.isEmpty()) { - Category current = toCheck.remove(0); + Category current = toCheck.remove(0); toCheck.addAll(current.children); if(current.name.equals(path)) { @@ -85,8 +82,8 @@ public Supplier getSupplierFor(String path) { return null; } - public T create(String path) { - Supplier supplier = getSupplierFor(path); + public Node create(String path) { + Supplier supplier = getSupplierFor(path); if(supplier==null) return null; return supplier.get(); } @@ -95,9 +92,9 @@ public void scan() { // Create a new instance of Reflections Reflections reflections = new Reflections("com.marginallyclever.ro3"); // Get all classes that extend T - Set> found = reflections.getSubTypesOf(type); + Set> found = reflections.getSubTypesOf(Node.class); // Now, classes contains all classes that extend T - for (Class clazz : found) { + for (Class clazz : found) { logger.info("Found " + clazz.getName()); } } diff --git a/src/main/java/com/marginallyclever/ro3/apps/NodeFactoryPanel.java b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactoryPanel.java similarity index 74% rename from src/main/java/com/marginallyclever/ro3/apps/NodeFactoryPanel.java rename to src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactoryPanel.java index 83c1a0084..e441ffaa6 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/NodeFactoryPanel.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeFactoryPanel.java @@ -1,7 +1,7 @@ -package com.marginallyclever.ro3.apps; +package com.marginallyclever.ro3.node.nodefactory; -import com.marginallyclever.ro3.NodeFactory; import com.marginallyclever.ro3.apps.shared.SearchBar; +import com.marginallyclever.ro3.node.Node; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,15 +13,15 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; /** * {@link NodeFactoryPanel} allows a user to select from a list of things that can be created by a given {@link NodeFactory}. - * @param the class of thing to create. */ -public class NodeFactoryPanel extends JPanel { +public class NodeFactoryPanel extends JPanel { private static final Logger logger = LoggerFactory.getLogger(NodeFactoryPanel.class); private final JTree tree = new JTree(); - private final NodeFactory factory; + private final NodeFactory factory; private final JButton okButton = new JButton("OK"); private final SearchBar searchBar = new SearchBar(); @@ -30,19 +30,24 @@ private static class FactoryCategoryCellRenderer extends DefaultTreeCellRenderer public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); var branch = (DefaultMutableTreeNode) value; - if(branch.getUserObject() instanceof NodeFactory.Category category) { + if(branch.getUserObject() instanceof NodeFactory.Category category) { if (category.getSupplier() == null) { setForeground(Color.LIGHT_GRAY); } else { setForeground(Color.BLACK); } setText(category.getName()); + Supplier supplier = category.getSupplier(); + if (supplier != null) { + Node node = category.getSupplier().get(); + setIcon(node.getIcon()); + } } return this; } } - public NodeFactoryPanel(NodeFactory factory) { + public NodeFactoryPanel(NodeFactory factory) { super(new BorderLayout()); this.factory = factory; @@ -77,7 +82,7 @@ private void populateTree() { } } - private void selectNodeInTree(NodeFactory.Category node) { + private void selectNodeInTree(NodeFactory.Category node) { var rootNode = (DefaultMutableTreeNode)tree.getModel().getRoot(); TreePath path = findNodeInTree(rootNode, node); if (path != null) { @@ -86,7 +91,7 @@ private void selectNodeInTree(NodeFactory.Category node) { } } - private TreePath findNodeInTree(DefaultMutableTreeNode branch, NodeFactory.Category node) { + private TreePath findNodeInTree(DefaultMutableTreeNode branch, NodeFactory.Category node) { if (getCategory(branch) == node) { return new TreePath(branch.getPath()); } @@ -99,8 +104,8 @@ private TreePath findNodeInTree(DefaultMutableTreeNode branch, NodeFactory.Categ return null; } - private void addBranches(NodeFactory.Category node, DefaultMutableTreeNode branch, List> matches) { - for(NodeFactory.Category child : node.getChildren()) { + private void addBranches(NodeFactory.Category node, DefaultMutableTreeNode branch, List matches) { + for(NodeFactory.Category child : node.getChildren()) { if(!matches.contains(child)) continue; DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(child); @@ -109,10 +114,10 @@ private void addBranches(NodeFactory.Category node, DefaultMutableTreeNode br } } - private void addAllParents(List> matches) { - List> toAdd = new ArrayList<>(); - for (NodeFactory.Category node : matches) { - NodeFactory.Category parent = node.getParent(); + private void addAllParents(List matches) { + List toAdd = new ArrayList<>(); + for (NodeFactory.Category node : matches) { + NodeFactory.Category parent = node.getParent(); while (parent != null) { if(!matches.contains(parent) && !toAdd.contains(parent)) { toAdd.add(parent); @@ -129,12 +134,12 @@ private void addAllParents(List> matches) { * @param searchCriteria the search criteria * @return a list of all categories that match the search criteria */ - private List> findAllTypesMatching(NodeFactory.Category root) { - List> matches = new ArrayList<>(); - List> toSearch = new ArrayList<>(); + private List findAllTypesMatching(NodeFactory.Category root) { + List matches = new ArrayList<>(); + List toSearch = new ArrayList<>(); toSearch.add(root); while(!toSearch.isEmpty()) { - NodeFactory.Category category = toSearch.remove(0); + NodeFactory.Category category = toSearch.remove(0); String name = category.getName(); if(searchBar.matches(name)) { matches.add(category); @@ -149,7 +154,7 @@ private void setupTree() { tree.addTreeSelectionListener(e -> { TreePath path = tree.getSelectionPath(); if (path != null) { - NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); + NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); okButton.setEnabled(category.getSupplier() != null); } }); @@ -162,7 +167,7 @@ private void setupTree() { public int getResult() { TreePath path = tree.getSelectionPath(); if (path != null) { - NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); + NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); if (category.getSupplier() != null) { return JOptionPane.OK_OPTION; } @@ -173,14 +178,14 @@ public int getResult() { public String getSelectedNode() { TreePath path = tree.getSelectionPath(); if (path != null) { - NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); + NodeFactory.Category category = getCategory((DefaultMutableTreeNode) path.getLastPathComponent()); return category.getName(); } return null; } - NodeFactory.Category getCategory(DefaultMutableTreeNode branch) { + NodeFactory.Category getCategory(DefaultMutableTreeNode branch) { Object obj = branch.getUserObject(); - return (NodeFactory.Category)obj; + return (NodeFactory.Category)obj; } } diff --git a/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeBranchRenderer.java b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeTreeBranchRenderer.java similarity index 81% rename from src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeBranchRenderer.java rename to src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeTreeBranchRenderer.java index d8cb74fe8..2e8d6d162 100644 --- a/src/main/java/com/marginallyclever/ro3/apps/nodetreeview/NodeTreeBranchRenderer.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodefactory/NodeTreeBranchRenderer.java @@ -1,5 +1,7 @@ -package com.marginallyclever.ro3.apps.nodetreeview; +package com.marginallyclever.ro3.node.nodefactory; +import com.marginallyclever.ro3.apps.nodetreeview.NodeTreeBranch; +import com.marginallyclever.ro3.apps.nodetreeview.NodeTreeView; import com.marginallyclever.ro3.node.Node; import javax.swing.*; diff --git a/src/test/java/com/marginallyclever/ro3/TestAllPanels.java b/src/test/java/com/marginallyclever/ro3/TestAllPanels.java index 77e72656f..c53e2cbff 100644 --- a/src/test/java/com/marginallyclever/ro3/TestAllPanels.java +++ b/src/test/java/com/marginallyclever/ro3/TestAllPanels.java @@ -1,7 +1,7 @@ package com.marginallyclever.ro3; import com.formdev.flatlaf.FlatLightLaf; -import com.marginallyclever.ro3.apps.NodeFactoryPanel; +import com.marginallyclever.ro3.node.nodefactory.NodeFactoryPanel; import com.marginallyclever.ro3.node.Node; import com.marginallyclever.ro3.apps.nodedetailview.NodeDetailView; import org.reflections.Reflections;