ef13629a7e46626b3080a0ce9fa0ee95a231a91e
[debian/openrocket] / src / net / sf / openrocket / gui / main / componenttree / ComponentTree.java
1 package net.sf.openrocket.gui.main.componenttree;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.awt.Graphics;
7 import java.awt.Graphics2D;
8
9 import javax.swing.DropMode;
10 import javax.swing.Icon;
11 import javax.swing.JTree;
12 import javax.swing.ToolTipManager;
13 import javax.swing.tree.TreeModel;
14 import javax.swing.tree.TreePath;
15
16 import net.sf.openrocket.document.OpenRocketDocument;
17
18
19 public class ComponentTree extends JTree {
20         
21         public ComponentTree(OpenRocketDocument document) {
22                 super();
23                 this.setModel(new ComponentTreeModel(document.getRocket(), this));
24                 this.setToggleClickCount(0);
25                 
26                 javax.swing.plaf.basic.BasicTreeUI plainUI = new javax.swing.plaf.basic.BasicTreeUI();
27                 this.setUI(plainUI);
28                 plainUI.setExpandedIcon(TreeIcon.MINUS);
29                 plainUI.setCollapsedIcon(TreeIcon.PLUS);
30                 plainUI.setLeftChildIndent(15);
31                 
32
33                 this.setBackground(Color.WHITE);
34                 this.setShowsRootHandles(false);
35                 
36                 this.setCellRenderer(new ComponentTreeRenderer());
37                 
38                 this.setDragEnabled(true);
39                 this.setDropMode(DropMode.INSERT);
40                 this.setTransferHandler(new ComponentTreeTransferHandler(document));
41                 
42                 // Expand whole tree by default
43                 expandTree();
44                 
45                 // Enable tooltips for this component
46                 ToolTipManager.sharedInstance().registerComponent(this);
47                 
48         }
49         
50         
51         public void expandTree() {
52                 for (int i = 0; i < getRowCount(); i++)
53                         expandRow(i);
54         }
55         
56         @Override
57         public void treeDidChange() {
58                 super.treeDidChange();
59                 expandChildlessNodes();
60         }
61         
62         /**
63          * Expand all nodes in the tree that are visible and have no children.  This can be used
64          * to avoid the situation where a non-leaf node is marked as being expandable, but when
65          * expanding it it has no children.
66          */
67         private void expandChildlessNodes() {
68                 TreeModel model = this.getModel();
69                 if (model == null) {
70                         return;
71                 }
72                 Object root = model.getRoot();
73                 expandChildlessNodes(model, new TreePath(root));
74         }
75         
76         private void expandChildlessNodes(TreeModel model, TreePath path) {
77                 Object object = path.getLastPathComponent();
78                 if (this.isVisible(path)) {
79                         int count = model.getChildCount(object);
80                         if (count == 0) {
81                                 this.expandPath(path);
82                         }
83                         for (int i = 0; i < count; i++) {
84                                 expandChildlessNodes(model, path.pathByAddingChild(model.getChild(object, i)));
85                         }
86                 }
87         }
88         
89         
90
91         private static class TreeIcon implements Icon {
92                 public static final Icon PLUS = new TreeIcon(true);
93                 public static final Icon MINUS = new TreeIcon(false);
94                 
95                 // Implementation:
96                 
97                 private final static int width = 9;
98                 private final static int height = 9;
99                 private final static BasicStroke stroke = new BasicStroke(2);
100                 private boolean plus;
101                 
102                 private TreeIcon(boolean plus) {
103                         this.plus = plus;
104                 }
105                 
106                 public void paintIcon(Component c, Graphics g, int x, int y) {
107                         Graphics2D g2 = (Graphics2D) g.create();
108                         
109                         g2.setColor(Color.WHITE);
110                         g2.fillRect(x, y, width, height);
111                         
112                         g2.setColor(Color.DARK_GRAY);
113                         g2.drawRect(x, y, width, height);
114                         
115                         g2.setStroke(stroke);
116                         g2.drawLine(x + 3, y + (height + 1) / 2, x + width - 2, y + (height + 1) / 2);
117                         if (plus)
118                                 g2.drawLine(x + (width + 1) / 2, y + 3, x + (width + 1) / 2, y + height - 2);
119                         
120                         g2.dispose();
121                 }
122                 
123                 public int getIconWidth() {
124                         return width;
125                 }
126                 
127                 public int getIconHeight() {
128                         return height;
129                 }
130         }
131         
132 }