/plugins/ProjectViewer/tags/pv_2_1_3_2/projectviewer/vpt/VPTFilteredModel.java

# · Java · 324 lines · 196 code · 36 blank · 92 comment · 39 complexity · 14d4c0d63728480376cda868db28c87a 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 detaProjectTreeSelectionListenerils.
  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.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Collections;
  25. import java.util.LinkedList;
  26. import java.util.Iterator;
  27. import java.util.Map;
  28. import java.util.regex.*;
  29. import javax.swing.tree.TreeNode;
  30. import javax.swing.tree.DefaultTreeModel;
  31. import org.gjt.sp.util.Log;
  32. import projectviewer.ProjectManager;
  33. //}}}
  34. /**
  35. * A tree model that compress the view by displaying packed directories.
  36. *
  37. * <p>A directory is displayed only if it contains at least one (non-hidden) file.
  38. * The relative path is used to display these directories.
  39. * </p>
  40. * <p>Example:</p>
  41. * <table>
  42. * <tr><td>-</td><td>MyProject</td></tr>
  43. * <tr><td></td><td>-</td><td>src/net/sf/myproject/ui</td></tr>
  44. * <tr><td></td><td></td><td></td><td>MyFrame.java</td></tr>
  45. * <tr><td></td><td></td><td></td><td>MyDialog.java</td></tr>
  46. * <tr><td></td><td>-</td><td>src/net/sf/myproject/actions</td></tr>
  47. * <tr><td></td><td></td><td></td><td>MyAction.java</td></tr>
  48. * <tr><td></td><td>+</td><td>src/net/sf/myproject/mybigpackage</td></tr>
  49. * </table>
  50. *
  51. * @author Rudolf Widmann
  52. * @version $Id: VPTFilteredModel.java 6391 2006-03-30 04:29:41Z vanza $
  53. * @since PV 2.2.0.0
  54. */
  55. public class VPTFilteredModel extends DefaultTreeModel {
  56. //{{{ Private members
  57. private static final String SEPARATOR = "/";
  58. private Map cache = new HashMap();
  59. // private List filterList = new ArrayList();
  60. //}}}
  61. //{{{ +VPTFilteredModel(VPTNode) : <init>
  62. /**
  63. * Create a new <code>VPTFilteredModel</code>.
  64. *
  65. * @param rootNode The root node of the tree.
  66. */
  67. public VPTFilteredModel(VPTNode rootNode) {
  68. super(rootNode, true);
  69. // filterList.add(new VPTFilterData("java", Pattern.compile(".*\\.java")));
  70. // filterList.add(new VPTFilterData("html", Pattern.compile(".*\\.html")));
  71. // filterList.add(new VPTFilterData("xml", Pattern.compile(".*\\.xml")));
  72. // filterList.add(new VPTFilterData("c", Pattern.compile(".*\\.c")));
  73. // filterList.add(new VPTFilterData("other", Pattern.compile(".*")));
  74. }
  75. //}}}
  76. //{{{ +getChildCount(Object) : int
  77. public int getChildCount(Object parent) {
  78. VPTNode node = (VPTNode) parent;
  79. if (node.isGroup()) {
  80. return node.getChildCount();
  81. } else if (node.isProject()) {
  82. return getProjectChildren((VPTProject)node).size();
  83. } else if (node instanceof FilteredDirectoryNode) {
  84. FilteredDirectoryNode cd = (FilteredDirectoryNode) node;
  85. return cd.getFiles().size();
  86. }
  87. Log.log(Log.WARNING, this, "Reached the supposedly unreachable! parent.getClass() = " + parent.getClass());
  88. return 0; // shouldn't reach here
  89. } //}}}
  90. //{{{ +getChild(Object, int) : Object
  91. public Object getChild(Object parent, int index) {
  92. VPTNode node = (VPTNode) parent;
  93. if (node.isGroup()) {
  94. return node.getChildAt(index);
  95. } else if (node.isProject()) {
  96. return getProjectChildren((VPTProject)node).get(index);
  97. } else if (node instanceof FilteredDirectoryNode) {
  98. FilteredDirectoryNode cd = (FilteredDirectoryNode) node;
  99. return cd.getFiles().get(index);
  100. }
  101. Log.log(Log.WARNING, this, "Reached the supposedly unreachable! parent.getClass() = " + parent.getClass());
  102. return null; // shouldn't reach here
  103. } //}}}
  104. //{{{ +getIndexOfChild(Object, Object) : int
  105. public int getIndexOfChild(Object parent, Object child) {
  106. VPTNode node = (VPTNode) parent;
  107. if (node.isGroup()) {
  108. return super.getIndexOfChild(parent, child);
  109. } else if (node.isProject()) {
  110. List l = getProjectChildren((VPTProject)node);
  111. return l.indexOf(child);
  112. } else if (node instanceof FilteredDirectoryNode) {
  113. FilteredDirectoryNode cd = (FilteredDirectoryNode) node;
  114. return cd.getFiles().indexOf(child);
  115. }
  116. Log.log(Log.WARNING, this, "Reached the supposedly unreachable! parent.getClass() = " + parent.getClass());
  117. return -1; // shouldn't reach here
  118. } //}}}
  119. //{{{ +nodeStructureChanged(TreeNode) : void
  120. public void nodeStructureChanged(TreeNode node) {
  121. cache.clear();
  122. super.nodeStructureChanged(node);
  123. } //}}}
  124. //{{{ +clearCache() : void
  125. /** when the filter has changed, clear the cache */
  126. public void clearCache() {
  127. cache.clear();
  128. } //}}}
  129. //{{{ +nodesWereInserted(TreeNode, int[]) : void
  130. public void nodesWereInserted(TreeNode node, int[] childIndices) {
  131. nodeStructureChanged(VPTNode.findProjectFor((VPTNode)node));
  132. } //}}}
  133. //{{{ +nodesWereRemoved(TreeNode, int[], Object[]) : void
  134. public void nodesWereRemoved(TreeNode node, int[] childIndices, Object[] removedChildren) {
  135. nodeStructureChanged(VPTNode.findProjectFor((VPTNode)node));
  136. } //}}}
  137. //{{{ #getFilteredNodes(VPTProject) : List
  138. protected List getFilteredNodes(VPTProject node) {
  139. if (cache.get(node)!=null)
  140. return (List)cache.get(node);
  141. Log.log(Log.DEBUG, this, "not cached: "+node);
  142. List filteredNodesList=new ArrayList();
  143. // openableNodes returns an unmodifiable Collection
  144. // ==> copy it into a new list
  145. List openableNodelist = new LinkedList();
  146. Iterator openableNodesIt = node.openableNodes.values().iterator();
  147. while (openableNodesIt.hasNext())
  148. openableNodelist.add(openableNodesIt.next());
  149. // check first project list, then global list
  150. boolean useProjectFilter = true;
  151. for (int i=0; i<2 ;i++)
  152. {
  153. Iterator it;
  154. if (useProjectFilter) {
  155. it = node.getFilterList().iterator();
  156. } else {
  157. it = ProjectManager.getInstance().getGlobalFilterList().iterator();
  158. }
  159. useProjectFilter = false;
  160. while (it.hasNext())
  161. {
  162. VPTFilterData fd = (VPTFilterData)it.next();
  163. FilteredDirectoryNode filtNode = new FilteredDirectoryNode(fd, openableNodelist);
  164. if (filtNode.getChildCount() > 0)
  165. filteredNodesList.add(filtNode);
  166. }
  167. }
  168. cache.put(node, filteredNodesList);
  169. return filteredNodesList;
  170. } //}}}
  171. //{{{ #hasFile(VPTNode) : boolean
  172. protected boolean hasFile(VPTNode node) {
  173. for (int i = 0; i < node.getChildCount(); i++) {
  174. VPTNode child = (VPTNode) node.getChildAt(i);
  175. if (child.isFile()) {
  176. return true;
  177. }
  178. }
  179. return false;
  180. } //}}}
  181. //{{{ #getProjectChildren(VPTProject) : List
  182. protected List getProjectChildren(VPTProject project) {
  183. List cd = getFilteredNodes(project);
  184. return cd;
  185. } //}}}
  186. //{{{ +getPathToRoot(TreeNode) : TreeNode[]
  187. public TreeNode[] getPathToRoot(TreeNode aNode) {
  188. // Three possibilities: aNode is a group, aNode is a
  189. // project or aNode is a leaf. In the first cases, just
  190. // return the normal path to root. Otherwise, need to build
  191. // the path...
  192. VPTNode node = (VPTNode) aNode;
  193. if (node.isGroup() || node.isProject()) {
  194. return super.getPathToRoot(aNode);
  195. } else if (node.isLeaf()) {
  196. VPTProject proj = VPTNode.findProjectFor(node);
  197. TreeNode[] proj_path = super.getPathToRoot(proj);
  198. // path will be project path + 2 nodes
  199. TreeNode[] lpath = new TreeNode[proj_path.length + 2];
  200. System.arraycopy(proj_path, 0, lpath, 0, proj_path.length);
  201. boolean found = false;
  202. List filters = getFilteredNodes(proj);
  203. for (Iterator i = filters.iterator(); i.hasNext(); ) {
  204. FilteredDirectoryNode dnode = (FilteredDirectoryNode) i.next();
  205. if (dnode.getFiles().contains(node)) {
  206. lpath[lpath.length - 2] = dnode;
  207. lpath[lpath.length - 1] = node;
  208. found = true;
  209. break;
  210. }
  211. }
  212. return (found) ? lpath : null;
  213. } else {
  214. // shouldn't reach here?
  215. return null;
  216. }
  217. } //}}}
  218. //{{{ +nodeChanged(TreeNode) : void
  219. /** Handles a node changed request. */
  220. public void nodeChanged(TreeNode node) {
  221. VPTNode n = (VPTNode) node;
  222. if (n.isGroup() || n.isProject()) {
  223. super.nodeChanged(node);
  224. } else {
  225. TreeNode[] path_to_node = getPathToRoot(n);
  226. if (path_to_node != null) {
  227. fireTreeNodesChanged(n, path_to_node, null, null);
  228. }
  229. }
  230. } //}}}
  231. //{{{ +class FilteredDirectoryNode
  232. public class FilteredDirectoryNode extends VPTDirectory {
  233. private VPTFilterData filterData;
  234. private List files = new ArrayList();
  235. //{{{ +FilteredDirectoryNode(VPTFilterData, List) : <init>
  236. public FilteredDirectoryNode(VPTFilterData filterData, List openableNodeList)
  237. {
  238. super(new java.io.File(filterData.getName()));
  239. this.filterData = filterData;
  240. Iterator it = openableNodeList.iterator();
  241. //org.gjt.sp.util.Log.log(org.gjt.sp.util.Log.DEBUG, VPTFilteredModel.class,"+++ .191: openableNodeList size = "+openableNodeList.size());
  242. while (it.hasNext())
  243. {
  244. VPTNode node = (VPTNode)it.next();
  245. //org.gjt.sp.util.Log.log(org.gjt.sp.util.Log.DEBUG, VPTFilteredModel.class,"+++ .199: node.getName() = "+node.getName());
  246. if (filterData.getPattern().matcher(node.getName()).matches())
  247. {
  248. // pattern matched: add to list of this node
  249. add(node);
  250. }
  251. }
  252. sortFiles();
  253. // remove from openableNodeList
  254. it =files.iterator();
  255. while (it.hasNext())
  256. openableNodeList.remove(it.next());
  257. } //}}}
  258. //{{{ +getName() : String
  259. public String getName() {
  260. return filterData.getName();
  261. } //}}}
  262. //{{{ +getFiles() : List
  263. public List getFiles() {
  264. return files;
  265. } //}}}
  266. //{{{ -sortFiles() : void
  267. private void sortFiles()
  268. {
  269. Collections.sort(files);
  270. } //}}}
  271. //{{{ +getChildCount() : int
  272. public int getChildCount() {
  273. return files.size();
  274. } //}}}
  275. //{{{ +remove(VPTNode) : void
  276. public void remove(VPTNode node) {
  277. files.remove(node);
  278. } //}}}
  279. //{{{ +add(VPTNode) : void
  280. public void add(VPTNode node) {
  281. files.add(node);
  282. } //}}}
  283. //{{{ +getClipType() : int
  284. public int getClipType() {
  285. return VPTCellRenderer.CLIP_START;
  286. } //}}}
  287. } //}}}
  288. }