/plugins/ProjectViewer/tags/pv_2_1_3_4/projectviewer/action/NodeRemoverAction.java

# · Java · 384 lines · 256 code · 47 blank · 81 comment · 81 complexity · 7636b5ece997138de13e6a62634aa993 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.action;
  20. //{{{ Imports
  21. import java.util.HashMap;
  22. import java.util.HashSet;
  23. import java.util.Iterator;
  24. import java.util.ArrayList;
  25. import java.util.Enumeration;
  26. import java.awt.event.ActionEvent;
  27. import javax.swing.JTree;
  28. import javax.swing.JMenuItem;
  29. import javax.swing.JOptionPane;
  30. import javax.swing.tree.TreePath;
  31. import org.gjt.sp.util.Log;
  32. import org.gjt.sp.jedit.jEdit;
  33. import projectviewer.ProjectViewer;
  34. import projectviewer.ProjectManager;
  35. import projectviewer.vpt.VPTDirectory;
  36. import projectviewer.vpt.VPTFile;
  37. import projectviewer.vpt.VPTGroup;
  38. import projectviewer.vpt.VPTNode;
  39. import projectviewer.vpt.VPTProject;
  40. import projectviewer.vpt.VPTRoot;
  41. //}}}
  42. /**
  43. * Action that when executed removes nodes from the trees.
  44. *
  45. * @author Marcelo Vanzin
  46. * @version $Id: NodeRemoverAction.java 6378 2005-12-12 04:33:47Z vanza $
  47. */
  48. public class NodeRemoverAction extends Action {
  49. //{{{ Constants
  50. private final static int FILE = 1;
  51. private final static int DIR = 2;
  52. private final static int PROJ = 3;
  53. private final static int MULTI = 4;
  54. //}}}
  55. //{{{ +NodeRemoverAction(boolean) : <init>
  56. /**
  57. * Cretes a new node remover actions. Delete defines what "remove" means:
  58. * "false" means it only removes the node from the tree, "true" means it
  59. * will try to delete it. Deletion is only available for file nodes at
  60. * this moment.
  61. */
  62. public NodeRemoverAction(boolean delete) {
  63. this.delete = delete;
  64. } //}}}
  65. //{{{ Instance variables
  66. private HashMap removedFiles;
  67. private HashSet changed;
  68. private boolean delete;
  69. //}}}
  70. //{{{ +getText() : String
  71. /** Returns the text to be shown on the button and/or menu item. */
  72. public String getText() {
  73. return (delete) ? jEdit.getProperty("projectviewer.action.delete")
  74. : null;
  75. } //}}}
  76. //{{{ +actionPerformed(ActionEvent) : void
  77. /** Try to remove nodes from the project, asking when necessary. */
  78. public void actionPerformed(ActionEvent e) {
  79. JTree tree = viewer.getCurrentTree();
  80. changed = new HashSet();
  81. switch (tree.getSelectionCount()) {
  82. case 0:
  83. // No Selecion! Shouldn't happen, but, just in case...
  84. return;
  85. case 1: {
  86. // Single selection!
  87. remove((VPTNode)tree.getLastSelectedPathComponent(), true);
  88. break;
  89. }
  90. default: {
  91. if (confirmAction(MULTI)) {
  92. // Any other thing == multiple selection
  93. ArrayList sel = getSelectedArtifacts(tree.getSelectionPaths());
  94. for (Iterator i = sel.iterator(); i.hasNext(); ) {
  95. remove((VPTNode) i.next(), false);
  96. }
  97. }
  98. }
  99. }
  100. ArrayList projects = new ArrayList();
  101. for (Iterator i = changed.iterator(); i.hasNext(); ) {
  102. VPTNode next = (VPTNode) i.next();
  103. if (next.isRoot()) {
  104. ProjectViewer.nodeStructureChangedFlat(next);
  105. } else {
  106. VPTProject p = VPTNode.findProjectFor(next);
  107. if (!projects.contains(p)) {
  108. ProjectViewer.nodeStructureChangedFlat(p);
  109. projects.add(p);
  110. }
  111. }
  112. }
  113. if (removedFiles != null)
  114. for (Iterator i = removedFiles.keySet().iterator(); i.hasNext(); ) {
  115. VPTProject p = (VPTProject) i.next();
  116. ArrayList lst = (ArrayList) removedFiles.get(p);
  117. if (lst.size() == 1) {
  118. p.fireFileRemoved((VPTFile)lst.get(0));
  119. } else {
  120. p.fireFilesChanged(null, lst);
  121. }
  122. }
  123. // cleanup
  124. removedFiles = null;
  125. changed = null;
  126. } //}}}
  127. //{{{ +prepareForNode(VPTNode) : void
  128. /** Enable action only for non-root nodes. */
  129. public void prepareForNode(VPTNode node) {
  130. if (delete) {
  131. if (node == null) {
  132. // if only writable files are selected, enable the "delete"
  133. // menu item
  134. cmItem.setVisible(true);
  135. JTree tree = viewer.getCurrentTree();
  136. TreePath[] paths = tree.getSelectionPaths();
  137. for (int i = 0; i < paths.length; i++) {
  138. VPTNode n = (VPTNode) paths[i].getLastPathComponent();
  139. if (!n.isFile() || !((VPTFile)n).canWrite()) {
  140. cmItem.setVisible(false);
  141. break;
  142. }
  143. }
  144. } else {
  145. cmItem.setVisible(node.isFile() && node.canWrite());
  146. }
  147. } else {
  148. if (node == null) {
  149. JTree tree = viewer.getCurrentTree();
  150. TreePath[] paths = tree.getSelectionPaths();
  151. // do not enable if there's a group in the multiple selection
  152. boolean enable = true;
  153. for (int i = 0; i < paths.length; i++) {
  154. VPTNode n = (VPTNode) paths[i].getLastPathComponent();
  155. if (n.isGroup()) {
  156. enable = false;
  157. break;
  158. }
  159. }
  160. if (enable) {
  161. ((JMenuItem)cmItem).setText(
  162. jEdit.getProperty("projectviewer.action.remove_multiple"));
  163. }
  164. cmItem.setVisible(enable);
  165. } else if (!node.isRoot()) {
  166. String text;
  167. if (node.isProject()) {
  168. text = jEdit.getProperty("projectviewer.action.remove_project");
  169. } else if (node.isGroup()) {
  170. text = jEdit.getProperty("projectviewer.action.remove_group");
  171. } else {
  172. text = jEdit.getProperty("projectviewer.action.remove");
  173. }
  174. ((JMenuItem)cmItem).setText(text);
  175. cmItem.setVisible(true);
  176. } else {
  177. cmItem.setVisible(false);
  178. }
  179. }
  180. } //}}}
  181. //{{{ -getSelectedArtifacts(TreePath[]) : ArrayList
  182. /**
  183. * Receives a collection of TreePath objects and returns the underlying
  184. * objects selected, removing a child when its parent has also been
  185. * selected.
  186. */
  187. private ArrayList getSelectedArtifacts(TreePath[] paths) {
  188. TreePath last = null;
  189. ArrayList objs = new ArrayList();
  190. for (int i = 0; i < paths.length; i++) {
  191. if (last != null && !last.isDescendant(paths[i])) {
  192. last = null;
  193. }
  194. if (last == null) {
  195. last = paths[i];
  196. objs.add(paths[i].getLastPathComponent());
  197. }
  198. }
  199. return objs;
  200. } //}}}
  201. //{{{ -confirmAction(int) : boolean
  202. /**
  203. * Asks the user if he reeeeeally wants to delete the selection he's
  204. * made.
  205. *
  206. * @param delete If the selection will be deleted or only removed
  207. * from the project;
  208. * @param type Type of object being removed. 1=File 2=Directory 3=Project
  209. * 4=Multiple objects
  210. */
  211. private boolean confirmAction(int type) {
  212. String message = null;
  213. // Sanity check
  214. if (type > MULTI || type < FILE) return false;
  215. if (delete) {
  216. switch (type) {
  217. case FILE: // File
  218. message = jEdit.getProperty("projectviewer.remove.confirm_file_del");
  219. break;
  220. case DIR: // Directory
  221. message = jEdit.getProperty("projectviewer.remove.confirm_dir_del");
  222. break;
  223. case MULTI: // Multiple
  224. message = jEdit.getProperty("projectviewer.remove.confim_multi_del");
  225. break;
  226. default: // No other deletion is supported (yet?)
  227. return false;
  228. }
  229. } else {
  230. switch(type) {
  231. case FILE: // File
  232. message = null;
  233. break;
  234. case DIR: // Directory
  235. message = jEdit.getProperty("projectviewer.remove.confirm_dir_remove");
  236. break;
  237. case PROJ: // Project
  238. message = jEdit.getProperty("projectviewer.remove.confirm_project_remove");
  239. break;
  240. case MULTI: // Multiple
  241. message = jEdit.getProperty("projectviewer.remove.confirm_multi_remove");
  242. break;
  243. default: // Won't happen, but...
  244. }
  245. }
  246. if (message == null) return true;
  247. return (JOptionPane.showConfirmDialog(viewer,
  248. message,
  249. jEdit.getProperty("projectviewer.remove.confirm.title"),
  250. JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION);
  251. } //}}}
  252. //{{{ -remove(VPTNode, boolean) : void
  253. /**
  254. * Removes an object from a project (or the project, if the object is one).
  255. *
  256. * @param o The node.
  257. * @param delete If deletion from disk should occur.
  258. * @param ask Is we should ask for confirmation.
  259. */
  260. private void remove(VPTNode o, boolean ask) {
  261. boolean removed = false;
  262. if(o == null || o.isRoot()) {
  263. Log.log(Log.WARNING, this, "Removing: unexpected object o: " + o);
  264. return;
  265. }
  266. if (o.isProject()) {
  267. if (!ask || confirmAction(PROJ)) {
  268. ProjectManager.getInstance().removeProject((VPTProject)o);
  269. changed.add(VPTRoot.getInstance());
  270. }
  271. } else if (o.isGroup()) {
  272. if (o.getChildCount() > 0) {
  273. JOptionPane.showMessageDialog(
  274. viewer,
  275. jEdit.getProperty("projectviewer.action.remove_group.not_empty"),
  276. jEdit.getProperty("projectviewer.action.remove_group.not_empty.title"),
  277. JOptionPane.WARNING_MESSAGE
  278. );
  279. } else {
  280. ProjectViewer.removeNodeFromParent(o);
  281. ProjectViewer.fireGroupRemovedEvent((VPTGroup)o);
  282. }
  283. } else {
  284. VPTProject project = VPTNode.findProjectFor(o);
  285. if (o.isFile()) {
  286. if (!delete || (!ask || confirmAction(FILE))) {
  287. addRemovedFile((VPTFile)o);
  288. ProjectViewer.removeNodeFromParent(o);
  289. if (delete) o.delete();
  290. removed = true;
  291. }
  292. } else if (o.isDirectory()) {
  293. if (!ask || o.getChildCount() == 0 || confirmAction(DIR)) {
  294. unregisterFiles((VPTDirectory)o, project);
  295. ProjectViewer.removeNodeFromParent(o);
  296. removed = true;
  297. }
  298. } else {
  299. ProjectViewer.removeNodeFromParent(o);
  300. }
  301. ProjectManager.getInstance().saveProject(project);
  302. if (removed) changed.add(project);
  303. }
  304. } //}}}
  305. //{{{ -unregisterFiles(VPTDirectory, VPTProject) : void
  306. /**
  307. * Recursively unregisters the files below the given directory from the
  308. * project.
  309. */
  310. private void unregisterFiles(VPTDirectory dir, VPTProject proj) {
  311. Enumeration e = dir.children();
  312. while (e.hasMoreElements()) {
  313. VPTNode n = (VPTNode) e.nextElement();
  314. if (n.isDirectory()) {
  315. unregisterFiles((VPTDirectory)n, proj);
  316. } else {
  317. proj.unregisterNodePath(n);
  318. if (n.isFile()) {
  319. addRemovedFile((VPTFile)n);
  320. }
  321. }
  322. }
  323. } //}}}
  324. //{{{ -addRemovedFile(VPTFile) : void
  325. private void addRemovedFile(VPTFile f) {
  326. VPTProject p = VPTProject.findProjectFor(f);
  327. if (p.hasListeners()) {
  328. if (removedFiles == null) removedFiles = new HashMap();
  329. ArrayList lst = (ArrayList) removedFiles.get(p);
  330. if (lst == null) {
  331. lst = new ArrayList();
  332. removedFiles.put(p, lst);
  333. }
  334. lst.add(f);
  335. }
  336. } //}}}
  337. }