/plugins/ProjectViewer/tags/pv_2_0_3/projectviewer/vpt/VPTContextMenu.java

# · Java · 312 lines · 193 code · 46 blank · 73 comment · 32 complexity · 6811a2ba75126a9293c5422d1b19d345 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.Iterator;
  22. import java.util.ArrayList;
  23. import java.util.Comparator;
  24. import java.util.Collection;
  25. import java.util.Collections;
  26. import java.util.StringTokenizer;
  27. import java.awt.Component;
  28. import java.awt.event.MouseEvent;
  29. import java.awt.event.MouseAdapter;
  30. import javax.swing.JTree;
  31. import javax.swing.JPopupMenu;
  32. import javax.swing.tree.TreePath;
  33. import javax.swing.SwingUtilities;
  34. import org.gjt.sp.util.Log;
  35. import org.gjt.sp.jedit.jEdit;
  36. import org.gjt.sp.jedit.PluginJAR;
  37. import org.gjt.sp.jedit.GUIUtilities;
  38. import projectviewer.PVActions;
  39. import projectviewer.ProjectViewer;
  40. import projectviewer.action.Action;
  41. import projectviewer.action.SearchAction;
  42. import projectviewer.action.ArchiveAction;
  43. import projectviewer.action.ReimportAction;
  44. import projectviewer.action.ActionSeparator;
  45. import projectviewer.action.FileImportAction;
  46. import projectviewer.action.EditProjectAction;
  47. import projectviewer.action.NodeRemoverAction;
  48. import projectviewer.action.NodeRenamerAction;
  49. import projectviewer.action.OpenWithAppAction;
  50. import projectviewer.action.LaunchBrowserAction;
  51. import projectviewer.action.VFSFileImportAction;
  52. import projectviewer.action.OpenWithEncodingAction;
  53. import projectviewer.config.AppLauncher;
  54. import projectviewer.config.ProjectViewerConfig;
  55. //}}}
  56. /**
  57. * A handler for context menu requests on the tree, providing node-sensitive
  58. * functionality.
  59. *
  60. * @author Marcelo Vanzin
  61. * @version $Id: VPTContextMenu.java 6216 2003-10-29 04:41:32Z vanza $
  62. */
  63. public class VPTContextMenu extends MouseAdapter {
  64. //{{{ Static Members
  65. private static final ArrayList actions = new ArrayList();
  66. private static final ArrayList intActions = new ArrayList();
  67. private static long lastMod = System.currentTimeMillis();
  68. /** Initializes the internal action list. */
  69. static {
  70. intActions.add(new EditProjectAction());
  71. intActions.add(new FileImportAction());
  72. intActions.add(new VFSFileImportAction());
  73. intActions.add(new ReimportAction());
  74. intActions.add(new NodeRemoverAction(false));
  75. intActions.add(new NodeRemoverAction(true));
  76. intActions.add(new NodeRenamerAction());
  77. intActions.add(new LaunchBrowserAction());
  78. intActions.add(new OpenWithAppAction());
  79. if (ProjectViewerConfig.getInstance().isJEdit42()) {
  80. intActions.add(new OpenWithEncodingAction());
  81. }
  82. intActions.add(new SearchAction());
  83. intActions.add(new ArchiveAction());
  84. }
  85. //{{{ +_registerAction(Action)_ : void
  86. /**
  87. * Adds an action to be shown on the context menu. Actions are shown in the
  88. * same order as they are registered.
  89. */
  90. public static void registerAction(Action action) {
  91. actions.add(action);
  92. sortMenu();
  93. lastMod = System.currentTimeMillis();
  94. } //}}}
  95. //{{{ +_unregisterAction(Action)_ : void
  96. /** Removes an action from the context menu. */
  97. public static void unregisterAction(Action action) {
  98. actions.remove(action);
  99. lastMod = System.currentTimeMillis();
  100. } //}}}
  101. //{{{ +_unregisterActions(PluginJAR)_ : void
  102. /** Removes all actions from the given plugin. */
  103. public static void unregisterActions(PluginJAR jar) {
  104. boolean removed = false;
  105. for (Iterator i = actions.iterator(); i.hasNext(); ) {
  106. Object o = i.next();
  107. if (o.getClass().getClassLoader() == jar.getClassLoader()) {
  108. i.remove();
  109. removed = true;
  110. }
  111. }
  112. if (removed) {
  113. lastMod = System.currentTimeMillis();
  114. }
  115. } //}}}
  116. //{{{ +_registerActions(PluginJAR)_ : void
  117. /** Registers actions from the given plugin. */
  118. public static void registerActions(PluginJAR jar) {
  119. if (jar.getPlugin() == null) return;
  120. String list = jEdit.getProperty("plugin.projectviewer." +
  121. jar.getPlugin().getClassName() + ".context-menu-actions");
  122. boolean added = false;
  123. Collection aList = PVActions.listToObjectCollection(list, jar, Action.class);
  124. if (aList != null && aList.size() > 0) {
  125. actions.addAll(aList);
  126. sortMenu();
  127. lastMod = System.currentTimeMillis();
  128. }
  129. } //}}}
  130. //{{{ +_userMenuChanged()_ : void
  131. /** Updates "lastMod" so that the menu is rebuilt at the next invocation. */
  132. public static void userMenuChanged() {
  133. lastMod = System.currentTimeMillis();
  134. } //}}}
  135. //{{{ -_sortMenu()_ : void
  136. /** Sorts the menu in alphabetical order. */
  137. private static void sortMenu() {
  138. class ActionComparer implements Comparator {
  139. public int compare(Object o1, Object o2) {
  140. return ((Action)o1).getText().compareTo(
  141. ((Action)o2).getText());
  142. }
  143. }
  144. Collections.sort(actions, new ActionComparer());
  145. } //}}}
  146. //}}}
  147. //{{{ Instance Variables
  148. private final ProjectViewer viewer;
  149. private final AppLauncher appList;
  150. private final JPopupMenu popupMenu;
  151. private final ArrayList internalActions;
  152. private long pmLastBuilt;
  153. //}}}
  154. //{{{ +VPTContextMenu(ProjectViewer) : <init>
  155. /**
  156. * Constructs a listener that will ask the provided viewer instance for
  157. * information about the nodes clicked.
  158. */
  159. public VPTContextMenu(ProjectViewer viewer) {
  160. this.viewer = viewer;
  161. appList = AppLauncher.getInstance();
  162. internalActions = new ArrayList();
  163. popupMenu = new JPopupMenu();
  164. loadGUI();
  165. }
  166. //}}}
  167. //{{{ Event Handling
  168. //{{{ +mousePressed(MouseEvent) : void
  169. /** Context-menus are shown on the "pressed" event. */
  170. public void mousePressed(MouseEvent me) {
  171. handleMouseEvent(me);
  172. } //}}}
  173. //{{{ +mouseReleased(MouseEvent) : void
  174. /** Context-menus are shown on the "pressed" event. */
  175. public void mouseReleased(MouseEvent me) {
  176. handleMouseEvent(me);
  177. } //}}}
  178. //}}}
  179. //{{{ Private Methods
  180. //{{{ -handleMouseEvent(MouseEvent) : void
  181. /** Handles the mouse event internally. */
  182. private void handleMouseEvent(MouseEvent me) {
  183. if (me.isPopupTrigger()) {
  184. JTree tree = viewer.getCurrentTree();
  185. TreePath tp = tree.getClosestPathForLocation(me.getX(),me.getY());
  186. if (tp != null && !tree.isPathSelected(tp)) {
  187. if ((me.getModifiers() & MouseEvent.CTRL_MASK) == MouseEvent.CTRL_MASK) {
  188. tree.addSelectionPath(tp);
  189. } else {
  190. tree.setSelectionPath(tp);
  191. }
  192. }
  193. if (tree.getSelectionCount() != 0) {
  194. prepareMenu( tree.getSelectionCount() > 1 ? null : viewer.getSelectedNode() );
  195. popupMenu.show(me.getComponent(), me.getX(), me.getY());
  196. }
  197. }
  198. } //}}}
  199. //{{{ -loadGUI() : void
  200. /** Constructs the menus' GUI. */
  201. private void loadGUI() {
  202. internalActions.clear();
  203. popupMenu.removeAll();
  204. Action a;
  205. for (Iterator it = intActions.iterator(); it.hasNext(); ) {
  206. a = (Action) it.next();
  207. a = (Action) a.clone();
  208. a.setViewer(viewer);
  209. internalActions.add(a);
  210. popupMenu.add(a.getMenuItem());
  211. // hacks to add some separators to the menu...
  212. if (a instanceof EditProjectAction) {
  213. ActionSeparator as = new ActionSeparator();
  214. as.setLinkedAction(a);
  215. as.setViewer(viewer);
  216. internalActions.add(as);
  217. popupMenu.add(as.getMenuItem());
  218. }
  219. if (a instanceof NodeRenamerAction) {
  220. ActionSeparator as = new ActionSeparator();
  221. as.setViewer(viewer);
  222. internalActions.add(as);
  223. popupMenu.add(as.getMenuItem());
  224. }
  225. }
  226. String menu = ProjectViewerConfig.getInstance().getUserContextMenu();
  227. if (menu != null) {
  228. jEdit.setTemporaryProperty("projectviewer.tmp_menu", menu);
  229. JPopupMenu pm = GUIUtilities.loadPopupMenu("projectviewer.tmp_menu");
  230. Component[] userActions = pm.getComponents();
  231. if (userActions != null && userActions.length > 0) {
  232. popupMenu.addSeparator();
  233. for (int i = 0; i < userActions.length; i++) {
  234. popupMenu.add(userActions[i]);
  235. }
  236. }
  237. }
  238. if (actions.size() > 0) {
  239. popupMenu.addSeparator();
  240. for (Iterator it = actions.iterator(); it.hasNext(); ) {
  241. a = (Action) it.next();
  242. a = (Action) a.clone();
  243. a.setViewer(viewer);
  244. internalActions.add(a);
  245. popupMenu.add(a.getMenuItem());
  246. }
  247. }
  248. pmLastBuilt = System.currentTimeMillis();
  249. } //}}}
  250. //{{{ -prepareMenu(VPTNode) : void
  251. /**
  252. * Prepares the context menu for the given node. Shows only menu items
  253. * that are allowed for the node (e.g., "Add Project" only applies for
  254. * the root node). If the node is null, the method guesses that multiple
  255. * nodes are selected, and chooses the appropriate entries.
  256. */
  257. private void prepareMenu(VPTNode selectedNode) {
  258. if (pmLastBuilt < lastMod) {
  259. loadGUI();
  260. }
  261. for (Iterator it = internalActions.iterator(); it.hasNext(); ) {
  262. ((Action)it.next()).prepareForNode(selectedNode);
  263. }
  264. } //}}}
  265. //}}}
  266. }