Bläddra i källkod

HolonModel kindly working

Tom Troppmann 3 år sedan
förälder
incheckning
8d7e3f0b6f

+ 80 - 0
src/classes/Holon.java

@@ -0,0 +1,80 @@
+package classes;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Holon {
+	public String name = new String();
+	private Holon parent = null;
+	public ArrayList<Holon> childHolons = new ArrayList<Holon>();
+	private List<HolonObject> objects = new ArrayList<HolonObject>();
+	
+	public Holon(String name) {
+		this.name = name;
+	}
+	public void addHolonObject(HolonObject object) {
+		object.holon = this;
+		objects.add(object);
+	}
+	public void removeHolonObject(HolonObject object) {
+		object.holon = null;
+		objects.remove(object);
+	}
+	public int holonObjectCount() {
+		return objects.size();
+	}
+	
+	public void addChildHolon(Holon child) {
+		child.parent = this;
+		childHolons.add(child);
+	}
+	
+	public void addChildHolon(Holon child, int index) {
+		child.parent = this;
+		childHolons.add(index, child);
+	}
+	
+	public void removeChildHolon(Holon child) {
+		child.parent = null;
+		childHolons.remove(child);
+	}
+	public int getChildCount() {
+		return childHolons.size();
+	}
+	
+	public Holon getParent() {
+		return parent;
+	}
+	
+	public List<Holon> getChildView(){
+		return Collections.unmodifiableList(childHolons);
+	}
+	
+	public List<HolonObject> getHolonObjectsView(){
+		return Collections.unmodifiableList(objects);
+	}
+	
+	@Override
+	public String toString() {
+		return name;
+	}
+	
+	//TODO This can maybe cached
+	public int getLevel() {
+		return parent != null ? parent.getLevel() : 0;
+	}
+	
+	
+	public Holon cloneWithoutParent() {
+		Holon cloned = new Holon(this.name);
+		cloned.childHolons = this.childHolons;
+		cloned.objects = this.objects;
+		return cloned;
+	}
+	
+	
+	
+}
+
+

+ 2 - 1
src/classes/HolonBody.java

@@ -1,10 +1,11 @@
 package classes;
 
 import java.awt.Color;
+
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Graphics2D;
-
+@Deprecated
 public class HolonBody implements Comparable<HolonBody> {
 
 	public Vector2d velocity;

+ 7 - 0
src/classes/HolonObject.java

@@ -18,6 +18,13 @@ public class HolonObject extends AbstractCanvasObject {
     /* Array of all consumers */
     private ArrayList<HolonElement> elements = new ArrayList<HolonElement>();
     
+    public Holon holon = null;
+    
+    
+    
+    
+    
+    
     /**
      * Constructor Set by default the name of the object equals to the category
      * name, until the user changes it.

+ 3 - 1
src/ui/controller/CanvasController.java

@@ -50,7 +50,9 @@ public class CanvasController {
 		model.getCvsObjIdx().put(object.getId(), model.getObjectsOnCanvas().size());
 		model.getObjectsOnCanvas().add(object);
 		if(object instanceof HolonObject) {
-			model.getStateHolon().addHolonObject(((HolonObject) object));
+			Holon holon = new Holon(object.getName());
+			model.getStateHolon().addChildHolon(holon);
+			//model.getStateHolon().addHolonObject(((HolonObject) object));
 		}
 		/**
 		 * check if we should drag & drop replace

+ 7 - 1
src/ui/model/Model.java

@@ -20,6 +20,7 @@ import classes.AbstractCanvasObject;
 import classes.Category;
 import classes.Edge;
 import classes.GroupNode;
+import classes.Holon;
 import classes.HolonElement;
 import classes.HolonObject;
 import classes.HolonSwitch;
@@ -129,7 +130,7 @@ public class Model {
     private PropertyTable tableModelHolonElementSingle;
     private DefaulTable tableModelProperties;
     private HashMap<Integer, GroupNode> hashcodeMap = new HashMap<>();
-
+    private Holon stateHolon = new Holon("state");
 
     private Gson gson;
 
@@ -343,6 +344,11 @@ public class Model {
     public int getScale() {
         return sCALE;
     }
+    
+    
+    public Holon getStateHolon() {
+    	return stateHolon;
+    }
 
     /**
      * Sets the Image Scale.

+ 1 - 0
src/ui/view/GUI.java

@@ -92,6 +92,7 @@ import ui.model.DecoratedState;
 import ui.model.Model;
 import ui.model.Model.FairnessModel;
 import ui.view.CreateNewDialog.Option;
+import ui.view.outliner.Outliner;
 import utility.ImageImport;
 
 /**

+ 87 - 0
src/ui/view/outliner/HolonTreeModel.java

@@ -0,0 +1,87 @@
+package ui.view.outliner;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+import classes.Holon;
+
+public class HolonTreeModel implements TreeModel {
+	Holon root;
+
+	public HolonTreeModel(Holon root) {
+		this.root = root;
+	}
+	// The model knows how to return the root object of the tree 
+	@Override
+	public Object getRoot() { 
+		return root; 
+	} 
+	
+	
+	public void reload() {
+		this.notifyAll();
+	}
+	// Tell JTree whether an object in the tree is a leaf 
+	@Override
+	public boolean isLeaf(Object node) { 
+		return ((Holon)node).getChildCount() == 0; 
+	} 
+	// Tell JTree how many children a node has 
+	@Override
+	public int getChildCount(Object parent) {
+		return ((Holon)parent).getChildCount(); 
+	} 
+	// Fetch any numbered child of a node for the JTree. 
+	// Our model returns File objects for all nodes in the tree. The 
+	// JTree displays these by calling the File.toString() method.
+	@Override
+	public Object getChild(Object parent, int index) { 
+		List<Holon> children = ((Holon)parent).getChildView(); 
+		if ((children == null) || (index >= children.size())) return null; 
+		return children.get(index); 
+	} 
+	// Figure out a child's position in its parent node. 
+	@Override
+	public int getIndexOfChild(Object parent, Object child) { 
+		List<Holon> children = ((Holon)parent).getChildView(); 
+		if (children == null) return -1;
+		for(int i = 0; i < children.size(); i++) {
+			if (child.equals(children.get(i))) return i;
+		} 
+		return -1; 
+	} 
+	// This method is invoked by the JTree only for editable trees. 
+	// This TreeModel does not allow editing, so we do not implement 
+	// this method. The JTree editable property is false by default. 
+	@Override
+	public void valueForPathChanged(TreePath path, Object newvalue) {} 
+	// Since this is not an editable tree model, we never fire any events, 
+	// so we don't actually have to keep track of interested listeners 
+	@Override
+	public void addTreeModelListener(TreeModelListener l) {
+		
+	} 
+	@Override
+	public void removeTreeModelListener(TreeModelListener l) {
+		
+	}
+	public void removeNodeFromParent(Holon holon) {
+		if(holon.getParent() != null) {
+			Holon cParent = holon.getParent();
+			System.out.println("REMOVE Parent:"+ cParent + ":" + cParent.getChildView().stream().map(Object::toString).collect(Collectors.joining(", ")));
+			holon.getParent().removeChildHolon(holon);
+			System.out.println("REMOVE Parent:"+ cParent + ":" + cParent.getChildView().stream().map(Object::toString).collect(Collectors.joining(", ")));
+		}
+	}
+	public void insertNodeInto(Holon holon, Holon parent, int index) {
+		System.out.println("INSERT Parent:"+ parent + ":" + parent.getChildView().stream().map(Object::toString).collect(Collectors.joining(", ")));
+		parent.addChildHolon(holon, index);
+		System.out.println("INSERT Parent:"+ parent + ":" + parent.getChildView().stream().map(Object::toString).collect(Collectors.joining(", ")));
+		
+	} 
+
+}

+ 216 - 0
src/ui/view/outliner/HolonTreeTransferHandler.java

@@ -0,0 +1,216 @@
+package ui.view.outliner;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.TransferHandler;
+import javax.swing.tree.TreePath;
+
+import classes.Holon;
+
+
+class HolonTreeTransferHandler extends TransferHandler {
+    DataFlavor nodesFlavor;
+    DataFlavor[] flavors = new DataFlavor[1];
+    Holon[] nodesToRemove;
+
+    public HolonTreeTransferHandler() {
+        try {
+            String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
+                              ";class=\"" +
+                classes.Holon.class.getName() +
+                              "\"";
+            nodesFlavor = new DataFlavor(mimeType);
+            flavors[0] = nodesFlavor;
+        } catch(ClassNotFoundException e) {
+            System.out.println("ClassNotFound: " + e.getMessage());
+        }
+    }
+
+    public boolean canImport(TransferHandler.TransferSupport support) {
+        if(!support.isDrop()) {
+            return false;
+        }
+        support.setShowDropLocation(true);
+        if(!support.isDataFlavorSupported(nodesFlavor)) {
+            return false;
+        }
+        // Do not allow a drop on the drag source selections.
+        JTree.DropLocation dl =
+                (JTree.DropLocation)support.getDropLocation();
+        JTree tree = (JTree)support.getComponent();
+        int dropRow = tree.getRowForPath(dl.getPath());
+        int[] selRows = tree.getSelectionRows();
+        for(int i = 0; i < selRows.length; i++) {
+            if(selRows[i] == dropRow) {
+                return false;
+            }
+        }
+        // Do not allow MOVE-action drops if a non-leaf node is
+        // selected unless all of its children are also selected.
+        int action = support.getDropAction();
+        if(action == MOVE) {
+            return haveCompleteNode(tree);
+        }
+        // Do not allow a non-leaf node to be copied to a level
+        // which is less than its source level.
+        TreePath dest = dl.getPath();
+        Holon target =
+            (Holon)dest.getLastPathComponent();
+        TreePath path = tree.getPathForRow(selRows[0]);
+        Holon firstNode =
+            (Holon)path.getLastPathComponent();
+        if(firstNode.getChildCount() > 0 &&
+               target.getLevel() < firstNode.getLevel()) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean haveCompleteNode(JTree tree) {
+        int[] selRows = tree.getSelectionRows();
+        TreePath path = tree.getPathForRow(selRows[0]);
+        Holon first =
+            (Holon)path.getLastPathComponent();
+        int childCount = first.getChildCount();
+        // first has children and no children are selected.
+        if(childCount > 0 && selRows.length == 1)
+            return false;
+        // first may have children.
+        for(int i = 1; i < selRows.length; i++) {
+            path = tree.getPathForRow(selRows[i]);
+            Holon next =
+                (Holon)path.getLastPathComponent();
+            if(first.getChildView().contains(next)) {
+                // Found a child of first.
+                if(childCount > selRows.length-1) {
+                    // Not all children of first are selected.
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    protected Transferable createTransferable(JComponent c) {
+        JTree tree = (JTree)c;
+        TreePath[] paths = tree.getSelectionPaths();
+        if(paths != null) {
+            // Make up a node array of copies for transfer and
+            // another for/of the nodes that will be removed in
+            // exportDone after a successful drop.
+            List<Holon> copies =
+                new ArrayList<Holon>();
+            List<Holon> toRemove =
+                new ArrayList<Holon>();
+            Holon node =
+                (Holon)paths[0].getLastPathComponent();
+            Holon copy = node.cloneWithoutParent();
+            copies.add(copy);
+            toRemove.add(node);
+            for(int i = 1; i < paths.length; i++) {
+                Holon next =
+                    (Holon)paths[i].getLastPathComponent();
+                // Do not allow higher level nodes to be added to list.
+                if(next.getLevel() < node.getLevel()) {
+                    break;
+                } else if(next.getLevel() > node.getLevel()) {  // child node
+                    copy.addChildHolon(next.cloneWithoutParent());
+                    // node already contains child
+                } else {                                        // sibling
+                    copies.add(next.cloneWithoutParent());
+                    toRemove.add(next);
+                }
+            }
+            Holon[] nodes =
+                copies.toArray(new Holon[copies.size()]);
+            nodesToRemove =
+                toRemove.toArray(new Holon[toRemove.size()]);
+            return new NodesTransferable(nodes);
+        }
+        return null;
+    }
+
+    protected void exportDone(JComponent source, Transferable data, int action) {
+        if((action & MOVE) == MOVE) {
+            JTree tree = (JTree)source;
+            HolonTreeModel model = (HolonTreeModel)tree.getModel();
+            // Remove nodes saved in nodesToRemove in createTransferable.
+            for(int i = 0; i < nodesToRemove.length; i++) {
+                model.removeNodeFromParent(nodesToRemove[i]);
+            }
+            tree.updateUI();
+        }
+    }
+
+    public int getSourceActions(JComponent c) {
+        return COPY_OR_MOVE;
+    }
+
+    public boolean importData(TransferHandler.TransferSupport support) {
+        if(!canImport(support)) {
+            return false;
+        }
+        // Extract transfer data.
+        Holon[] nodes = null;
+        try {
+            Transferable t = support.getTransferable();
+            nodes = (Holon[])t.getTransferData(nodesFlavor);
+        } catch(UnsupportedFlavorException ufe) {
+            System.out.println("UnsupportedFlavor: " + ufe.getMessage());
+        } catch(java.io.IOException ioe) {
+            System.out.println("I/O error: " + ioe.getMessage());
+        }
+        // Get drop location info.
+        JTree.DropLocation dl =
+                (JTree.DropLocation)support.getDropLocation();
+        int childIndex = dl.getChildIndex();
+        TreePath dest = dl.getPath();
+        Holon parent =
+            (Holon)dest.getLastPathComponent();
+        JTree tree = (JTree)support.getComponent();
+        HolonTreeModel model = (HolonTreeModel)tree.getModel();
+        // Configure for drop mode.
+        int index = childIndex;    // DropMode.INSERT
+        if(childIndex == -1) {     // DropMode.ON
+            index = parent.getChildCount();
+        }
+        // Add data to model.
+        for(int i = 0; i < nodes.length; i++) {
+            model.insertNodeInto(nodes[i], parent, index++);
+        }
+        return true;
+    }
+
+    public String toString() {
+        return getClass().getName();
+    }
+
+    public class NodesTransferable implements Transferable {
+        Holon[] nodes;
+
+        public NodesTransferable(Holon[] nodes) {
+            this.nodes = nodes;
+         }
+
+        public Object getTransferData(DataFlavor flavor)
+                                 throws UnsupportedFlavorException {
+            if(!isDataFlavorSupported(flavor))
+                throw new UnsupportedFlavorException(flavor);
+            return nodes;
+        }
+
+        public DataFlavor[] getTransferDataFlavors() {
+            return flavors;
+        }
+
+        public boolean isDataFlavorSupported(DataFlavor flavor) {
+            return nodesFlavor.equals(flavor);
+        }
+    }
+}

+ 37 - 0
src/ui/view/outliner/HolonView.java

@@ -0,0 +1,37 @@
+package ui.view.outliner;
+
+import java.awt.BorderLayout;
+
+import javax.swing.DropMode;
+import javax.swing.JPanel;
+import javax.swing.JTree;
+import javax.swing.tree.TreeSelectionModel;
+
+import ui.controller.Control;
+/**
+ * An Outliner Tab.
+ * A high level view on the Model with respect to the Holon Structure. 
+ * @author Tom 
+ *
+ */
+public class HolonView extends JPanel{
+	private Control control; 
+	private JTree tree;
+	public HolonView(Outliner parent, Control control) {
+		this.control = control;
+		this.setLayout(new BorderLayout());
+		initilizePanel();
+		parent.outlinerUpdate.addListener(() -> tree.updateUI());
+	}
+
+	private void initilizePanel() {
+		HolonTreeModel model = new HolonTreeModel(control.getModel().getStateHolon()); 
+		tree = new JTree(model);
+		tree.setDragEnabled(true);
+        tree.setDropMode(DropMode.ON_OR_INSERT);
+        tree.setTransferHandler(new HolonTreeTransferHandler());
+        tree.getSelectionModel().setSelectionMode(
+                TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
+		this.add(TreeUtils.makePanelFromTree(tree, true));
+	}
+}

+ 41 - 0
src/ui/view/outliner/TreeUtils.java

@@ -0,0 +1,41 @@
+package ui.view.outliner;
+
+import javax.swing.ImageIcon;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import utility.ImageImport;
+
+public class TreeUtils {
+	static void signIconsForTree(JTree tree) {
+		ImageIcon ClosedIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Close.png",9,9));
+		ImageIcon OpenIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Open.png",9,9));
+		ImageIcon LeafIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/Leaf.png",9,9));
+		if (ClosedIcon != null && OpenIcon != null && LeafIcon!= null) {
+		    DefaultTreeCellRenderer renderer = 
+		        new DefaultTreeCellRenderer();
+		    renderer.setClosedIcon(ClosedIcon);
+		    renderer.setOpenIcon(OpenIcon);
+		    renderer.setLeafIcon(LeafIcon);
+		    tree.setCellRenderer(renderer);
+		}
+	}
+	
+	static void expand(JTree tree) {
+		for (int i = 0; i < tree.getRowCount(); i++) {
+			tree.expandRow(i);
+		}
+	}
+	static JScrollPane makePanelFromNode(DefaultMutableTreeNode node) {
+		JTree stateTree = new JTree(node);
+		return makePanelFromTree(stateTree, true);
+	}
+	static JScrollPane makePanelFromTree(JTree stateTree, boolean rootVisible) {
+		stateTree.setRootVisible(rootVisible);
+		TreeUtils.signIconsForTree(stateTree);
+		TreeUtils.expand(stateTree);
+		return new JScrollPane(stateTree);
+	}
+}