/plugins/ProjectViewer/tags/pv_2_1_0_1/projectviewer/vpt/VPTNode.java

# · Java · 409 lines · 152 code · 55 blank · 202 comment · 38 complexity · 5afc210fdee3c1013df7a55350e9d204 MD5 · raw file

  1. /*
  2. * :tabSize=4:indentSize=4:noTabs=false:
  3. * :folding=explicit:collapseFolds=1:
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. package projectviewer.vpt;
  20. //{{{ Imports
  21. import java.util.Collections;
  22. import java.awt.Color;
  23. import java.awt.Component;
  24. import javax.swing.Icon;
  25. import javax.swing.UIManager;
  26. import javax.swing.tree.MutableTreeNode;
  27. import javax.swing.tree.DefaultMutableTreeNode;
  28. //}}}
  29. /**
  30. * Node implementation for the Virtual Project Tree. Keeps track of children
  31. * and provides basic functionality for the nodes.
  32. *
  33. * <p>Based on the <code>TreeNode</code> class from the VirtualProjectTree
  34. * plugin by Shad Stafford.</p>
  35. *
  36. * @author Marcelo Vanzin
  37. * @version $Id: VPTNode.java 6334 2005-02-10 06:33:28Z vanza $
  38. */
  39. public abstract class VPTNode extends DefaultMutableTreeNode
  40. implements Comparable {
  41. //{{{ Constants
  42. protected final static Color treeSelectionForeground = UIManager.getColor("Tree.selectionForeground");
  43. protected final static Color treeNoSelectionForeground = UIManager.getColor("Tree.textForeground");
  44. protected final static Color treeSelectionBackground = UIManager.getColor("Tree.selectionBackground");
  45. protected final static Color treeNoSelectionBackground = UIManager.getColor("Tree.textBackground");
  46. //}}}
  47. //{{{ Static members
  48. //{{{ +_findProjectFor(VPTNode)_ : VPTProject
  49. /**
  50. * Returns the project associated with the node, or null if the node
  51. * is the root of the project tree.
  52. */
  53. public static VPTProject findProjectFor(VPTNode node) {
  54. if (node.isRoot()) {
  55. return null;
  56. } else {
  57. while (node != null && !node.isProject()) {
  58. node = (VPTNode) node.getParent();
  59. }
  60. return (VPTProject) node;
  61. }
  62. } //}}}
  63. //}}}
  64. //{{{ Attributes
  65. protected String name;
  66. //}}}
  67. //{{{ #VPTNode(String) : <init>
  68. protected VPTNode(String name) {
  69. this.name = name;
  70. setAllowsChildren(getClass() != VPTFile.class);
  71. } //}}}
  72. //{{{ #VPTNode(String, boolean) : <init>
  73. protected VPTNode(String name, boolean allowsChildren) {
  74. this.name = name;
  75. setAllowsChildren(allowsChildren);
  76. }
  77. //}}}
  78. //{{{ Public methods
  79. //{{{ +sortChildren() : void
  80. /**
  81. * Sort the children list for this node using the default node comparator.
  82. * The trees containing the node are not notified of the update.
  83. */
  84. public void sortChildren() {
  85. if (children != null && children.size() > 1)
  86. Collections.sort(children);
  87. } //}}}
  88. //{{{ +delete() : boolean
  89. /**
  90. * The "delete()" method should remove the resource from the the disk,
  91. * if applicable. This method does not call remove().
  92. *
  93. * @return Whether the deletion was successful or not.
  94. */
  95. public boolean delete() {
  96. return false;
  97. } //}}}
  98. //{{{ +isFile() : boolean
  99. /** Returns true if this node is a VPTFile. */
  100. public final boolean isFile() {
  101. return (getClass() == VPTFile.class);
  102. } //}}}
  103. //{{{ +isDirectory() : boolean
  104. /** Returns true if this node is a VPTDirectory. */
  105. public final boolean isDirectory() {
  106. return (getClass() == VPTDirectory.class);
  107. } //}}}
  108. //{{{ +isProject() : boolean
  109. /** Returns true if this node is a VPTProject. */
  110. public final boolean isProject() {
  111. return (getClass() == VPTProject.class);
  112. } //}}}
  113. //{{{ +isGroup() : boolean
  114. /** Whether this instance if a VPTGroup or any subclass of it. */
  115. public boolean isGroup() {
  116. return (this instanceof VPTGroup);
  117. } //}}}
  118. //{{{ +isRoot() : boolean
  119. /** Returns whether this node is the root node. */
  120. public final boolean isRoot() {
  121. return (this == VPTRoot.getInstance());
  122. } //}}}
  123. //{{{ +isOpened() : boolean
  124. /**
  125. * Tells if the resource is currently opened in jEdit. This only makes
  126. * sense for files, so the default just returns "false" and is
  127. * overridden in the file implementation.
  128. */
  129. public boolean isOpened() {
  130. return false;
  131. } //}}}
  132. //{{{ +getName() : String
  133. /**
  134. * Returns the name of this node. The name is the text that will appear
  135. * in the project tree.
  136. */
  137. public String getName() {
  138. return name;
  139. } //}}}
  140. //{{{ +setName(String) : void
  141. /** Changes the name of the node. */
  142. public void setName(String name) {
  143. this.name = name;
  144. } //}}}
  145. //{{{ +canWrite() : boolean
  146. /**
  147. * Returns whether the underlying resource can be written to. It makes
  148. * more sense for files and directories, for example, to check if it is
  149. * possible to delete them.
  150. */
  151. public boolean canWrite() {
  152. return false;
  153. } //}}}
  154. //{{{ +toString() : String
  155. /** Returns a string representation of the current node. */
  156. public String toString() {
  157. return "VPTNode [" + getName() + "]";
  158. } //}}}
  159. //{{{ +canOpen() : boolean
  160. /**
  161. * This method should return whether it makes sense to "open" the node.
  162. * For example, for file nodes, it should be reasonable to open the file
  163. * in a jEdit buffer, so this method should return "true" and implement
  164. * {@link #open() open()} and {@link #close() close()} to execute
  165. * the opening and closing operations.
  166. */
  167. public boolean canOpen() {
  168. return false;
  169. } //}}}
  170. //{{{ +open() : void
  171. /**
  172. * "Opens" the node. The default implementation does nothing. If a node can
  173. * be opened, it should implement the opening action in this method.
  174. */
  175. public void open() {
  176. } //}}}
  177. //{{{ +close() : void
  178. /**
  179. * "Closes" the node. This should "undo" what was done by
  180. * {@link #open() open()}, normally.
  181. */
  182. public void close() {
  183. } //}}}
  184. //{{{ +*getNodePath()* : String
  185. /**
  186. * Returns a String representing a "path" for this node. This can be any
  187. * arbitrary String, but the idea is to have the string represent some kind
  188. * of URL or file path. This makes more sense for nodes that deal with
  189. * files and directories, or even URL links.
  190. */
  191. public abstract String getNodePath(); //}}}
  192. //{{{ +compareToNode(VPTNode) : int
  193. /**
  194. * This method is used to sort the nodes in the trees. The rough hierarchy
  195. * is Root -> Groups -> Projects -> "allows children" -> leaves, so try
  196. * to keep that consistent.
  197. *
  198. * <p>IT'S VERY IMPORTANT TO IMPLEMENT THIS METHOD CORRECTLY. Especially
  199. * for nodes that allow children nodes, since VPTDirectory expects
  200. * nodes of these kinds to take care of the comparison themselves.
  201. * There's danger of infinite recursion if you don't take this into
  202. * account.</p>
  203. */
  204. public int compareToNode(VPTNode node) {
  205. return 1;
  206. } //}}}
  207. //{{{ +compareTo(Object) : int
  208. /**
  209. * Implementation of the Comparable interface. Returns -1 if "o" is
  210. * not another VPTNode, otherwise calls
  211. * {@link #compareToNode(VPTNode) compareToNode(VPTNode)}.
  212. *
  213. * @since PV 2.1.0
  214. */
  215. public int compareTo(Object o) {
  216. if (o instanceof VPTNode) {
  217. return compareToNode((VPTNode)o);
  218. } else {
  219. return -1;
  220. }
  221. } //}}}
  222. //{{{ +findIndexForChild(VPTNode) : int
  223. /**
  224. * Do a binary search with the goal of finding in what index of the child
  225. * array of this node the given child would be inserted to maintain order
  226. * according to the comparison rules defined by the compareToNode() methods.
  227. *
  228. * @param child The child to be inserted.
  229. * @return The index where to put the child as to maintain the child array
  230. * in ascendant order.
  231. */
  232. public int findIndexForChild(VPTNode child) {
  233. if (children == null || children.size() == 0) return 0;
  234. int b = 0, e = children.size(), i = e/2;
  235. VPTNode n;
  236. while (e - b > 1) {
  237. n = (VPTNode) children.get(i);
  238. int comp = child.compareToNode(n);
  239. if (comp < 0) {
  240. e = i;
  241. } else if (comp == 0) {
  242. i++;
  243. b = e = i;
  244. } else {
  245. b = i;
  246. }
  247. i = (e+b)/2;
  248. }
  249. if (b == children.size()) return b;
  250. n = (VPTNode) children.get(b);
  251. return (child.compareToNode(n) < 0 ? b : b + 1);
  252. } //}}}
  253. //{{{ +setParent(MutableTreeNode) : void
  254. /**
  255. * Sets the parent for the node. If the node is an openable node (e.g.,
  256. * a file), it registers itself in the parent project, or unregisters
  257. * itself from the project in case the parent is being set to null.
  258. */
  259. public void setParent(MutableTreeNode newParent) {
  260. if (canOpen()) {
  261. if (newParent == null) {
  262. VPTProject p = findProjectFor(this);
  263. if (p != null) {
  264. p.unregisterNodePath(this);
  265. }
  266. } else {
  267. VPTProject p = findProjectFor((VPTNode)newParent);
  268. if (p != null) {
  269. p.registerNodePath(this);
  270. }
  271. }
  272. }
  273. super.setParent(newParent);
  274. } //}}}
  275. //{{{ +persistChildren() : boolean
  276. /**
  277. * This method should return whether the children of this node should
  278. * be persisted when the node is saved to the project config file. The
  279. * default is "true".
  280. *
  281. * <p>Nodes that provide run time children (for example, allowing for the
  282. * exploration of the contents of a JAR file) should override this method
  283. * and return "false".</p>
  284. *
  285. * <p>This only makes sense for nodes that allow children in the first
  286. * place.</p>
  287. *
  288. * @since PV 2.1.0
  289. */
  290. public boolean persistChildren() {
  291. return true;
  292. } //}}}
  293. //{{{ +getChildWithName(String) : VPTNode
  294. /**
  295. * Returns the child directly under this node that has the given
  296. * name. This doesn't look into the children's children.
  297. *
  298. * @since PV 2.1.0
  299. */
  300. public VPTNode getChildWithName(String name) {
  301. if (getAllowsChildren()) {
  302. for (int i = 0; i < getChildCount(); i++) {
  303. if (((VPTNode)getChildAt(i)).getName().equals(name))
  304. return (VPTNode) getChildAt(i);
  305. }
  306. }
  307. return null;
  308. } //}}}
  309. //}}}
  310. //{{{ GUI stuff
  311. //{{{ +*getIcon(boolean)* : Icon
  312. /**
  313. * Returns the icon to be shown on the tree next to the node name.
  314. *
  315. * @param expanded If the node is currently expanded or not.
  316. */
  317. public abstract Icon getIcon(boolean expanded); //}}}
  318. //{{{ +getForegroundColor(boolean) : Color
  319. /**
  320. * Returns the node's foreground color.
  321. *
  322. * @param sel If the node is currently selected.
  323. */
  324. public Color getForegroundColor(boolean sel) {
  325. return (sel ? treeSelectionForeground : treeNoSelectionForeground);
  326. } //}}}
  327. //{{{ +getBackgroundColor(boolean) : Color
  328. /**
  329. * Returns the node's background color.
  330. *
  331. * @param sel If the node is currently selected.
  332. */
  333. public Color getBackgroundColor(boolean sel) {
  334. return (sel ? treeSelectionBackground : treeNoSelectionBackground);
  335. } //}}}
  336. //{{{ +getClipType() : int
  337. /**
  338. * This method controls how the CellRenderer implementation will clip the
  339. * name of the node when it doesn't fit in the tree.
  340. *
  341. * @see VPTCellRenderer
  342. * @return CLIP_NOCLIP in the default implementation, override to change it.
  343. * @since PV 2.1.0
  344. */
  345. public int getClipType() {
  346. return VPTCellRenderer.CLIP_NOCLIP;
  347. } //}}}
  348. //}}}
  349. //{{{ -class _TTEntry_
  350. private static class TTEntry {
  351. public String str;
  352. public Component component;
  353. } //}}}
  354. }