HolonView.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package ui.view.outliner;
  2. import java.awt.BorderLayout;
  3. import java.awt.Color;
  4. import java.awt.Component;
  5. import java.awt.datatransfer.DataFlavor;
  6. import java.awt.datatransfer.Transferable;
  7. import java.awt.datatransfer.UnsupportedFlavorException;
  8. import java.io.IOException;
  9. import javax.swing.DropMode;
  10. import javax.swing.Icon;
  11. import javax.swing.ImageIcon;
  12. import javax.swing.JComponent;
  13. import javax.swing.JPanel;
  14. import javax.swing.JTree;
  15. import javax.swing.ToolTipManager;
  16. import javax.swing.TransferHandler;
  17. import javax.swing.tree.DefaultMutableTreeNode;
  18. import javax.swing.tree.DefaultTreeCellRenderer;
  19. import javax.swing.tree.TreePath;
  20. import javax.swing.tree.TreeSelectionModel;
  21. import classes.Holon;
  22. import classes.HolonElement;
  23. import ui.controller.Control;
  24. import utility.ImageImport;
  25. /**
  26. * An Outliner Tab.
  27. * A high level view on the Model with respect to the Holon Structure.
  28. * @author Tom
  29. *
  30. */
  31. public class HolonView extends JPanel{
  32. private Control control;
  33. private JTree tree;
  34. private DefaultMutableTreeNode root;
  35. public HolonView(Outliner parent, Control control) {
  36. this.control = control;
  37. this.setLayout(new BorderLayout());
  38. initilizePanel();
  39. parent.outlinerUpdate.addListener(() -> updateTreeStructure());
  40. }
  41. private void initilizePanel() {
  42. tree = generateTree();
  43. tree.setCellRenderer(new HolonJtreeRenderer());
  44. tree.setDragEnabled(true);
  45. tree.setDropMode(DropMode.ON_OR_INSERT);
  46. tree.setTransferHandler(new HolonTransferHandler());
  47. tree.getSelectionModel().setSelectionMode(
  48. TreeSelectionModel.SINGLE_TREE_SELECTION);
  49. ToolTipManager.sharedInstance().registerComponent(tree);
  50. TreeUtils.expand(tree);
  51. tree.setRootVisible(true);
  52. this.add(TreeUtils.makePanelFromTree(tree));
  53. }
  54. private JTree generateTree() {
  55. root = generateFromHolon(control.getModel().getStateHolon());
  56. return new JTree(root);
  57. }
  58. private DefaultMutableTreeNode generateFromHolon(Holon holon) {
  59. DefaultMutableTreeNode node = new DefaultMutableTreeNode(new HolonInfo(holon));
  60. for(Holon child : holon.getChildView()) {
  61. node.add(generateFromHolon(child));
  62. }
  63. for(HolonElement ele : holon.getElementView()) {
  64. node.add(new DefaultMutableTreeNode(new ElementInfo(ele)));
  65. }
  66. return node;
  67. }
  68. private void updateTreeStructure() {
  69. root.removeAllChildren();
  70. Holon holon = control.getModel().getStateHolon();
  71. for(Holon child : holon.getChildView()) {
  72. root.add(generateFromHolon(child));
  73. }
  74. for(HolonElement ele : holon.getElementView()) {
  75. root.add(new DefaultMutableTreeNode(new ElementInfo(ele)));
  76. }
  77. tree.updateUI();
  78. TreeUtils.expand(tree);
  79. }
  80. interface HolonNode{
  81. public Transferable getTransferable(HolonTransferHandler handler);
  82. public Icon getIcon();
  83. public String getToolTip();
  84. }
  85. static final Icon elementIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/element.png",16,16));
  86. static final String elementToolTip = "Element";
  87. class ElementInfo implements HolonNode{
  88. private HolonElement element;
  89. ElementInfo(HolonElement element){
  90. this.element = element;
  91. }
  92. @Override
  93. public String toString(){
  94. return element.getName();
  95. }
  96. public HolonElement getElement()
  97. {
  98. return element;
  99. }
  100. @Override
  101. public Transferable getTransferable(HolonTransferHandler handler) {
  102. return handler.new ElementTransferable(element);
  103. }
  104. @Override
  105. public Icon getIcon() {
  106. return elementIcon;
  107. }
  108. @Override
  109. public String getToolTip() {
  110. return elementToolTip;
  111. }
  112. }
  113. static final Icon holonIcon = new ImageIcon(ImageImport.loadImage("/Button_Images/holon.png",16,16));
  114. static final String holonToolTip = "Holon";
  115. class HolonInfo implements HolonNode{
  116. private Holon holon;
  117. HolonInfo(Holon holon){
  118. this.holon = holon;
  119. }
  120. @Override
  121. public String toString(){
  122. return holon.name;
  123. }
  124. public Holon getElement()
  125. {
  126. return holon;
  127. }
  128. public void AddElement(HolonElement element) {
  129. if(element.holon != null) {
  130. element.holon.removeElement(element);
  131. }
  132. holon.addElement(element);
  133. }
  134. public void AddHolon(Holon holon) {
  135. holon.removeFromParent();
  136. this.holon.addChild(holon);
  137. }
  138. @Override
  139. public Transferable getTransferable(HolonTransferHandler handler) {
  140. return handler.new HolonTransferable(holon);
  141. }
  142. @Override
  143. public Icon getIcon() {
  144. return holonIcon;
  145. }
  146. @Override
  147. public String getToolTip() {
  148. return holonToolTip;
  149. }
  150. }
  151. class HolonTransferHandler extends TransferHandler{
  152. DataFlavor holonFlavor;
  153. DataFlavor[] holonFlavorArray = new DataFlavor[1];
  154. DataFlavor elementFlavor;
  155. DataFlavor[] elementFlavorArray = new DataFlavor[1];
  156. HolonTransferHandler(){
  157. try {
  158. String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
  159. ";class=\"" +
  160. classes.Holon.class.getName() +
  161. "\"";
  162. holonFlavor = new DataFlavor(mimeType);
  163. holonFlavorArray[0] = holonFlavor;
  164. mimeType = DataFlavor.javaJVMLocalObjectMimeType +
  165. ";class=\"" +
  166. classes.HolonElement.class.getName() +
  167. "\"";
  168. elementFlavor = new DataFlavor(mimeType);
  169. elementFlavorArray[0] = elementFlavor;
  170. } catch (ClassNotFoundException e) {
  171. e.printStackTrace();
  172. }
  173. }
  174. @Override
  175. public boolean canImport(TransferHandler.TransferSupport support) {
  176. if(!support.isDrop()) {
  177. return false;
  178. }
  179. support.setShowDropLocation(true);
  180. //Only accept Element and Holon as Drop
  181. if(!support.isDataFlavorSupported(holonFlavor) && !support.isDataFlavorSupported(elementFlavor)) {
  182. return false;
  183. }
  184. JTree.DropLocation location = (JTree.DropLocation)support.getDropLocation();
  185. TreePath pathDrop = location.getPath();
  186. DefaultMutableTreeNode node = (DefaultMutableTreeNode) pathDrop.getLastPathComponent();
  187. //Element cannot be parent of a holon
  188. if(!(node.getUserObject() instanceof HolonInfo)) {
  189. return false;
  190. }
  191. JTree tree = (JTree) support.getComponent();
  192. TreePath pathDrag = tree.getSelectionPath();
  193. //Dont allow Cycles
  194. if(pathDrag.isDescendant(pathDrop)) {
  195. return false;
  196. }
  197. return true;
  198. }
  199. @Override
  200. public boolean importData(TransferHandler.TransferSupport support) {
  201. if(!canImport(support)) {
  202. return false;
  203. }
  204. JTree.DropLocation location = (JTree.DropLocation)support.getDropLocation();
  205. TreePath path = location.getPath();
  206. DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
  207. if(node.getUserObject() instanceof HolonInfo) {
  208. HolonInfo info = (HolonInfo) node.getUserObject();
  209. try {
  210. if(support.isDataFlavorSupported(holonFlavor)) {
  211. info.AddHolon((Holon) support.getTransferable().getTransferData(holonFlavor));
  212. }else if (support.isDataFlavorSupported(elementFlavor)){
  213. info.AddElement((HolonElement) support.getTransferable().getTransferData(elementFlavor));
  214. }
  215. } catch (UnsupportedFlavorException | IOException e) {
  216. e.printStackTrace();
  217. }
  218. }
  219. return false;
  220. }
  221. protected void exportDone(JComponent source,
  222. Transferable data,
  223. int action) {
  224. updateTreeStructure();
  225. }
  226. @Override
  227. public int getSourceActions(JComponent c) {
  228. return MOVE;
  229. }
  230. @Override
  231. protected Transferable createTransferable(JComponent c) {
  232. JTree tree = (JTree)c;
  233. TreePath path = tree.getSelectionPath();
  234. if(path != null) {
  235. DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
  236. Object userObject = node.getUserObject();
  237. //Only allow Hollon to move
  238. if(userObject instanceof HolonInfo) {
  239. return ((HolonInfo) userObject).getTransferable(this);
  240. }
  241. }
  242. return null;
  243. }
  244. public class HolonTransferable implements Transferable{
  245. Holon holon;
  246. public HolonTransferable(Holon holon) {
  247. this.holon = holon;
  248. }
  249. @Override
  250. public DataFlavor[] getTransferDataFlavors() {
  251. return holonFlavorArray;
  252. }
  253. @Override
  254. public boolean isDataFlavorSupported(DataFlavor flavor) {
  255. return holonFlavor.equals(flavor);
  256. }
  257. @Override
  258. public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
  259. if(!isDataFlavorSupported(flavor))
  260. throw new UnsupportedFlavorException(flavor);
  261. return holon;
  262. }
  263. }
  264. public class ElementTransferable implements Transferable{
  265. HolonElement element;
  266. public ElementTransferable(HolonElement element) {
  267. this.element = element;
  268. }
  269. @Override
  270. public DataFlavor[] getTransferDataFlavors() {
  271. return elementFlavorArray;
  272. }
  273. @Override
  274. public boolean isDataFlavorSupported(DataFlavor flavor) {
  275. return elementFlavor.equals(flavor);
  276. }
  277. @Override
  278. public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
  279. if(!isDataFlavorSupported(flavor))
  280. throw new UnsupportedFlavorException(flavor);
  281. return element;
  282. }
  283. }
  284. }
  285. class HolonJtreeRenderer extends DefaultTreeCellRenderer {
  286. public Component getTreeCellRendererComponent(
  287. JTree tree,
  288. Object value,
  289. boolean isSelected,
  290. boolean expanded,
  291. boolean leaf,
  292. int row,
  293. boolean hasFocus) {
  294. super.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, hasFocus);
  295. DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
  296. HolonNode Node = (HolonNode) node.getUserObject();
  297. if(row != 0) {
  298. this.setIcon(Node.getIcon());
  299. this.setToolTipText(Node.getToolTip());
  300. }
  301. return this;
  302. }
  303. }
  304. }