package holeg.ui.view.window; import holeg.model.AbstractCanvasObject; import holeg.model.GroupNode; import holeg.model.Holon; import holeg.model.HolonObject; import holeg.preferences.ColorPreference; import holeg.preferences.ImagePreference; import holeg.ui.controller.Control; import holeg.ui.view.image.Import; import holeg.utility.listener.WindowClosingListener; import holeg.utility.math.decimal.Format; import java.awt.BorderLayout; import java.awt.Color; import java.util.logging.Logger; import java.util.stream.Stream; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; public class Outliner extends JFrame { private static final Logger log = Logger.getLogger(Outliner.class.getName()); private static final String ConsumptionFontHTMLBracket = ""; private static final String ProductionFontHTMLBracket = ""; private static final String FontClosingBracket = " "; private static final String ProducerNodeText = getColoredHtmlText( ColorPreference.HolonObject.Producer, "Producer"); private static final String OverSuppliedNodeText = getColoredHtmlText( ColorPreference.HolonObject.OverSupplied, "Over supplied"); private static final String SuppliedNodeText = getColoredHtmlText( ColorPreference.HolonObject.Supplied, "Supplied"); private static final String PartiallySuppliedNodeText = getColoredHtmlText( ColorPreference.HolonObject.PartiallySupplied, "Partially supplied"); private static final String NotSuppliedNodeText = getColoredHtmlText( ColorPreference.HolonObject.NotSupplied, "Not supplied"); private static final String NoEnergyNodeText = getColoredHtmlText( ColorPreference.HolonObject.NoEnergy, "No energy"); private final Control control; JTabbedPane tabbedPane = new JTabbedPane(); JPanel hierarchyPanel = new JPanel(new BorderLayout()); JPanel holonPanel = new JPanel(new BorderLayout()); Runnable update = this::update; public Outliner(JFrame parentFrame, Control control) { setBounds(0, 0, 400, parentFrame.getHeight()); this.setIconImage(Import.loadImage(ImagePreference.Logo, 30, 30)); this.setTitle("Outliner"); setLocationRelativeTo(parentFrame); this.setVisible(true); this.control = control; update(); this.getContentPane().add(tabbedPane); this.addWindowListener( (WindowClosingListener) e -> control.OnCanvasUpdate.removeListener(update)); control.OnCanvasUpdate.addListener(update); tabbedPane.addTab("Hierarchy", hierarchyPanel); tabbedPane.addTab("Holons", holonPanel); } private static String getColoredHtmlText(Color color, String text) { return "" + text + FontClosingBracket; } public void update() { hierarchyPanel.removeAll(); holonPanel.removeAll(); DefaultMutableTreeNode topListPanel = new DefaultMutableTreeNode(); DefaultMutableTreeNode objects = new DefaultMutableTreeNode("HolonObjects"); DefaultMutableTreeNode switches = new DefaultMutableTreeNode("Switches"); DefaultMutableTreeNode nodes = new DefaultMutableTreeNode("Nodes"); DefaultMutableTreeNode cables = new DefaultMutableTreeNode("Cable"); topListPanel.add(objects); topListPanel.add(switches); topListPanel.add(nodes); topListPanel.add(cables); DefaultMutableTreeNode topHolonNode = createHolonNode(); DefaultMutableTreeNode topHierarchyNode = createHierarchyNode(); JTree hierarchyTree = new JTree(topHierarchyNode); signIconsForTree(hierarchyTree); hierarchyTree.setRootVisible(false); for (int i = 0; i < hierarchyTree.getRowCount(); i++) { hierarchyTree.expandRow(i); } hierarchyPanel.add(new JScrollPane(hierarchyTree)); JTree holonTree = new JTree(topHolonNode); signIconsForTree(holonTree); holonTree.setRootVisible(false); for (int i = 0; i < holonTree.getRowCount(); i++) { holonTree.expandRow(i); } holonPanel.add(new JScrollPane(holonTree)); holonPanel.revalidate(); hierarchyPanel.repaint(); } private DefaultMutableTreeNode createHolonNode() { DefaultMutableTreeNode topHolonNode = new DefaultMutableTreeNode(); for (Holon holon : control.getModel().holons) { DefaultMutableTreeNode holonNode = new DefaultMutableTreeNode("Holon"); DefaultMutableTreeNode producer = new DefaultMutableTreeNode(ProducerNodeText); DefaultMutableTreeNode overSupplied = new DefaultMutableTreeNode(OverSuppliedNodeText); DefaultMutableTreeNode supplied = new DefaultMutableTreeNode(SuppliedNodeText); DefaultMutableTreeNode partiallySupplied = new DefaultMutableTreeNode( PartiallySuppliedNodeText); DefaultMutableTreeNode notSupplied = new DefaultMutableTreeNode(NotSuppliedNodeText); DefaultMutableTreeNode noEnergy = new DefaultMutableTreeNode(NoEnergyNodeText); for (HolonObject hObject : holon.holonObjects) { DefaultMutableTreeNode holonObjectNode = createColoredTreeNodeFromHolonObject(hObject); switch (hObject.getState()) { case PRODUCER -> producer.add(holonObjectNode); case OVER_SUPPLIED -> overSupplied.add(holonObjectNode); case SUPPLIED -> supplied.add(holonObjectNode); case PARTIALLY_SUPPLIED -> partiallySupplied.add(holonObjectNode); case NOT_SUPPLIED -> notSupplied.add(holonObjectNode); case NO_ENERGY -> noEnergy.add(holonObjectNode); } } Stream.of(producer, overSupplied, supplied, partiallySupplied, notSupplied, noEnergy) .filter(node -> !node.isLeaf()).forEach(holonNode::add); topHolonNode.add(holonNode); } return topHolonNode; } private DefaultMutableTreeNode createHierarchyNode() { DefaultMutableTreeNode hierarchyNode = new DefaultMutableTreeNode(); hierarchyNode.add(getNodeFromGroupNode(control.getModel().getCanvas())); DefaultMutableTreeNode edgeNode = new DefaultMutableTreeNode("Edges"); control.getModel().getEdgesOnCanvas().forEach(edge -> { edgeNode.add(new DefaultMutableTreeNode(edge.toString())); }); hierarchyNode.add(edgeNode); return hierarchyNode; } private DefaultMutableTreeNode getNodeFromGroupNode(GroupNode groupNode) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(groupNode.getName()); groupNode.getHolonObjects().forEach(obj -> node.add(canvasObjectToNode(obj))); groupNode.getSwitches().forEach(obj -> node.add(canvasObjectToNode(obj))); groupNode.getNodes().forEach(obj -> node.add(canvasObjectToNode(obj))); groupNode.getGroupNodes().forEach(obj -> node.add(getNodeFromGroupNode(obj))); return node; } private DefaultMutableTreeNode canvasObjectToNode(AbstractCanvasObject obj) { return new DefaultMutableTreeNode(obj.getName() + " [" + obj.getId() + "]"); } private void signIconsForTree(JTree t) { ImageIcon ClosedIcon = new ImageIcon( Import.loadImage(ImagePreference.Button.Outliner.Closed, 9, 9)); ImageIcon OpenIcon = new ImageIcon( Import.loadImage(ImagePreference.Button.Outliner.Open, 9, 9)); ImageIcon LeafIcon = new ImageIcon( Import.loadImage(ImagePreference.Button.Outliner.Leaf, 9, 9)); DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); renderer.setClosedIcon(ClosedIcon); renderer.setOpenIcon(OpenIcon); renderer.setLeafIcon(LeafIcon); t.setCellRenderer(renderer); } private DefaultMutableTreeNode createColoredTreeNodeFromHolonObject(HolonObject obj) { float energy = obj.getActualEnergy(); String context = "" + obj.getName() + "    " + (obj.isConsumer() ? ConsumptionFontHTMLBracket : ProductionFontHTMLBracket) + Format.doubleTwoPlaces(energy) + FontClosingBracket + ""; return new DefaultMutableTreeNode(context); } }