ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / plugins / ant / src / com / intellij / lang / ant / config / explorer / AntExplorer.java
blob8d850cc6525419b76f0c96fa64e6cc7f9fa0920d
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.lang.ant.config.explorer;
18 import com.intellij.execution.RunManagerEx;
19 import com.intellij.execution.RunManagerListener;
20 import com.intellij.ide.CommonActionsManager;
21 import com.intellij.ide.DataManager;
22 import com.intellij.ide.TreeExpander;
23 import com.intellij.ide.actions.ContextHelpAction;
24 import com.intellij.lang.ant.AntBundle;
25 import com.intellij.lang.ant.config.*;
26 import com.intellij.lang.ant.config.actions.AntBuildFilePropertiesAction;
27 import com.intellij.lang.ant.config.actions.RemoveBuildFileAction;
28 import com.intellij.lang.ant.config.execution.ExecutionHandler;
29 import com.intellij.lang.ant.config.impl.*;
30 import com.intellij.lang.ant.config.impl.configuration.BuildFilePropertiesPanel;
31 import com.intellij.openapi.Disposable;
32 import com.intellij.openapi.actionSystem.*;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.diagnostic.Logger;
35 import com.intellij.openapi.fileChooser.FileChooser;
36 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
37 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
38 import com.intellij.openapi.fileTypes.FileTypeManager;
39 import com.intellij.openapi.fileTypes.StdFileTypes;
40 import com.intellij.openapi.keymap.Keymap;
41 import com.intellij.openapi.keymap.KeymapManagerListener;
42 import com.intellij.openapi.keymap.ex.KeymapManagerEx;
43 import com.intellij.openapi.keymap.impl.ui.EditKeymapsDialog;
44 import com.intellij.openapi.project.Project;
45 import com.intellij.openapi.ui.Messages;
46 import com.intellij.openapi.ui.SimpleToolWindowPanel;
47 import com.intellij.openapi.util.Disposer;
48 import com.intellij.openapi.util.IconLoader;
49 import com.intellij.openapi.vfs.VfsUtil;
50 import com.intellij.openapi.vfs.VirtualFile;
51 import com.intellij.ui.*;
52 import com.intellij.ui.treeStructure.Tree;
53 import com.intellij.util.ArrayUtil;
54 import com.intellij.util.StringBuilderSpinAllocator;
55 import com.intellij.util.ui.tree.TreeUtil;
56 import org.jetbrains.annotations.NonNls;
57 import org.jetbrains.annotations.Nullable;
59 import javax.swing.*;
60 import javax.swing.tree.DefaultMutableTreeNode;
61 import javax.swing.tree.DefaultTreeModel;
62 import javax.swing.tree.TreePath;
63 import java.awt.*;
64 import java.awt.event.ActionEvent;
65 import java.awt.event.KeyEvent;
66 import java.awt.event.MouseAdapter;
67 import java.awt.event.MouseEvent;
68 import java.util.ArrayList;
69 import java.util.Arrays;
70 import java.util.List;
72 public class AntExplorer extends SimpleToolWindowPanel implements DataProvider {
74 private static final Logger LOG = Logger.getInstance("#com.intellij.lang.ant.config.explorer.AntExplorer");
76 private Project myProject;
77 private AntExplorerTreeBuilder myBuilder;
78 private Tree myTree;
79 private KeymapListener myKeymapListener;
80 private final List<Disposable> myDisposables = new ArrayList<Disposable>();
81 private final AntBuildFilePropertiesAction myAntBuildFilePropertiesAction;
83 private final TreeExpander myTreeExpander = new TreeExpander() {
84 public void expandAll() {
85 myBuilder.expandAll();
88 public boolean canExpand() {
89 return AntConfiguration.getInstance(myProject).getBuildFiles().length != 0;
92 public void collapseAll() {
93 myBuilder.collapseAll();
96 public boolean canCollapse() {
97 return canExpand();
100 private static final Icon ICON_RUN = IconLoader.getIcon("/actions/execute.png");
101 private static final Icon ICON_REMOVE = IconLoader.getIcon("/general/remove.png");
102 private static final Icon ICON_ADD = IconLoader.getIcon("/general/add.png");
103 private static final Icon ICON_FILTER = IconLoader.getIcon("/ant/filter.png");
105 public AntExplorer(final Project project) {
106 super(true, true);
107 myProject = project;
108 final DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode());
109 myTree = new Tree(model);
110 myTree.setRootVisible(false);
111 myTree.setShowsRootHandles(true);
112 myTree.setCellRenderer(new NodeRenderer());
113 myBuilder = new AntExplorerTreeBuilder(project, myTree, model);
114 myBuilder.setTargetsFiltered(AntConfigurationBase.getInstance(project).isFilterTargets());
115 TreeToolTipHandler.install(myTree);
116 TreeUtil.installActions(myTree);
117 new TreeSpeedSearch(myTree);
118 myTree.addMouseListener(new PopupHandler() {
119 public void invokePopup(final Component comp, final int x, final int y) {
120 popupInvoked(comp, x, y);
123 myTree.addMouseListener(new MouseAdapter() {
124 public void mouseClicked(MouseEvent e) {
125 if (e.getClickCount() == 2) {
126 final TreePath path = myTree.getPathForLocation(e.getX(), e.getY());
127 if (path != null) {
128 runSelection(DataManager.getInstance().getDataContext(myTree));
133 myTree.registerKeyboardAction(new AbstractAction() {
134 public void actionPerformed(ActionEvent e) {
135 runSelection(DataManager.getInstance().getDataContext(myTree));
137 }, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), WHEN_FOCUSED);
138 myTree.expandRow(0);
139 myTree.setLineStyleAngled();
140 myAntBuildFilePropertiesAction = new AntBuildFilePropertiesAction(this);
141 setToolbar(createToolbarPanel());
142 setContent(new JScrollPane(myTree));
143 ToolTipManager.sharedInstance().registerComponent(myTree);
144 myKeymapListener = new KeymapListener();
146 RunManagerEx.getInstanceEx(myProject).addRunManagerListener(new RunManagerListener() {
147 public void beforeRunTasksChanged() {
148 myBuilder.refresh();
153 public void dispose() {
154 for (final Disposable disposable : myDisposables) {
155 disposable.dispose();
157 myDisposables.clear();
158 myProject = null;
159 if (myKeymapListener != null) {
160 myKeymapListener.stopListen();
161 myKeymapListener = null;
163 else {
164 LOG.error("already disposed");
166 if (myBuilder != null) {
167 Disposer.dispose(myBuilder);
169 myBuilder = null;
170 if (myTree != null) {
171 ToolTipManager.sharedInstance().unregisterComponent(myTree);
172 final KeyStroke[] strokes = myTree.getRegisteredKeyStrokes();
173 for (KeyStroke keyStroke : strokes) {
174 myTree.unregisterKeyboardAction(keyStroke);
176 myTree = null;
180 private JPanel createToolbarPanel() {
181 final DefaultActionGroup group = new DefaultActionGroup();
182 group.add(new AddAction());
183 group.add(new RemoveAction());
184 group.add(new RunAction());
185 group.add(new ShowAllTargetsAction());
186 AnAction action = CommonActionsManager.getInstance().createExpandAllAction(myTreeExpander, this);
187 action.getTemplatePresentation().setDescription(AntBundle.message("ant.explorer.expand.all.nodes.action.description"));
188 group.add(action);
189 action = CommonActionsManager.getInstance().createCollapseAllAction(myTreeExpander, this);
190 action.getTemplatePresentation().setDescription(AntBundle.message("ant.explorer.collapse.all.nodes.action.description"));
191 group.add(action);
192 group.add(myAntBuildFilePropertiesAction);
193 group.add(new ContextHelpAction(HelpID.ANT));
195 final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar(ActionPlaces.ANT_EXPLORER_TOOLBAR, group, true);
196 final JPanel buttonsPanel = new JPanel(new BorderLayout());
197 buttonsPanel.add(actionToolBar.getComponent(), BorderLayout.CENTER);
198 return buttonsPanel;
201 private void addBuildFile() {
202 final FileChooserDescriptor descriptor = createXmlDescriptor();
203 descriptor.setTitle(AntBundle.message("select.ant.build.file.dialog.title"));
204 descriptor.setDescription(AntBundle.message("select.ant.build.file.dialog.description"));
205 final VirtualFile[] files = FileChooser.chooseFiles(myProject, descriptor);
206 if (files.length == 0) {
207 return;
209 ApplicationManager.getApplication().invokeLater(new Runnable() {
210 public void run() {
211 final AntConfiguration antConfiguration = AntConfiguration.getInstance(myProject);
212 final ArrayList<VirtualFile> ignoredFiles = new ArrayList<VirtualFile>();
213 for (VirtualFile file : files) {
214 try {
215 antConfiguration.addBuildFile(file);
217 catch (AntNoFileException e) {
218 ignoredFiles.add(e.getFile());
221 if (ignoredFiles.size() != 0) {
222 String messageText;
223 final StringBuilder message = StringBuilderSpinAllocator.alloc();
224 try {
225 String separator = "";
226 for (final VirtualFile virtualFile : ignoredFiles) {
227 message.append(separator);
228 message.append(virtualFile.getPresentableUrl());
229 separator = "\n";
231 messageText = message.toString();
233 finally {
234 StringBuilderSpinAllocator.dispose(message);
236 Messages.showWarningDialog(myProject, messageText, AntBundle.message("cannot.add.ant.files.dialog.title"));
242 public void removeBuildFile() {
243 final AntBuildFile buildFile = getCurrentBuildFile();
244 if (buildFile == null) {
245 return;
247 final String fileName = buildFile.getPresentableUrl();
248 final int result = Messages.showYesNoDialog(myProject, AntBundle.message("remove.the.reference.to.file.confirmation.text", fileName),
249 AntBundle.message("confirm.remove.dialog.title"), Messages.getQuestionIcon());
250 if (result != 0) {
251 return;
253 AntConfiguration.getInstance(myProject).removeBuildFile(buildFile);
256 public void setBuildFileProperties(DataContext dataContext) {
257 final AntBuildFile buildFile = getCurrentBuildFile();
258 if (BuildFilePropertiesPanel.editBuildFile(getCurrentBuildFile())) {
259 final AntConfiguration antConfiguration = AntConfiguration.getInstance(myProject);
260 antConfiguration.updateBuildFile(buildFile);
261 myBuilder.refresh();
262 myTree.repaint();
266 private void runSelection(final DataContext dataContext) {
267 if (!canRunSelection()) {
268 return;
270 final AntBuildFileBase buildFile = getCurrentBuildFile();
271 final TreePath[] paths = myTree.getSelectionPaths();
272 final String[] targets = getTargetNamesFromPaths(paths);
273 ExecutionHandler.runBuild(buildFile, targets, null, dataContext, AntBuildListener.NULL);
276 private boolean canRunSelection() {
277 if (myTree == null) {
278 return false;
280 final TreePath[] paths = myTree.getSelectionPaths();
281 if (paths == null) {
282 return false;
284 final AntBuildFile buildFile = getCurrentBuildFile();
285 if (buildFile == null || !buildFile.exists()) {
286 return false;
288 for (final TreePath path : paths) {
289 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
290 final Object userObject = node.getUserObject();
291 final AntBuildFileNodeDescriptor buildFileNodeDescriptor;
292 if (userObject instanceof AntTargetNodeDescriptor) {
293 buildFileNodeDescriptor = (AntBuildFileNodeDescriptor)((DefaultMutableTreeNode)node.getParent()).getUserObject();
295 else if (userObject instanceof AntBuildFileNodeDescriptor){
296 buildFileNodeDescriptor = (AntBuildFileNodeDescriptor)userObject;
298 else {
299 buildFileNodeDescriptor = null;
301 if (buildFileNodeDescriptor == null || buildFileNodeDescriptor.getBuildFile() != buildFile) {
302 return false;
305 return true;
308 private static String[] getTargetNamesFromPaths(TreePath[] paths) {
309 final List<String> targets = new ArrayList<String>();
310 for (final TreePath path : paths) {
311 final Object userObject = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
312 if (!(userObject instanceof AntTargetNodeDescriptor)) {
313 continue;
315 final AntBuildTarget target = ((AntTargetNodeDescriptor)userObject).getTarget();
316 if (target instanceof MetaTarget) {
317 targets.addAll(Arrays.asList(((MetaTarget)target).getTargetNames()));
319 else {
320 targets.add(target.getName());
323 return ArrayUtil.toStringArray(targets);
326 private static AntBuildTarget[] getTargetObjectsFromPaths(TreePath[] paths) {
327 final List<AntBuildTargetBase> targets = new ArrayList<AntBuildTargetBase>();
328 for (final TreePath path : paths) {
329 final Object userObject = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
330 if (!(userObject instanceof AntTargetNodeDescriptor)) {
331 continue;
333 final AntBuildTargetBase target = ((AntTargetNodeDescriptor)userObject).getTarget();
334 targets.add(target);
337 return targets.toArray(new AntBuildTargetBase[targets.size()]);
340 public boolean isBuildFileSelected() {
341 if( myProject == null) return false;
342 final AntBuildFileBase file = getCurrentBuildFile();
343 return file != null && file.exists();
346 @Nullable
347 private AntBuildFileBase getCurrentBuildFile() {
348 final AntBuildFileNodeDescriptor descriptor = getCurrentBuildFileNodeDescriptor();
349 return (AntBuildFileBase)((descriptor == null) ? null : descriptor.getBuildFile());
352 @Nullable
353 private AntBuildFileNodeDescriptor getCurrentBuildFileNodeDescriptor() {
354 if (myTree == null) {
355 return null;
357 final TreePath path = myTree.getSelectionPath();
358 if (path == null) {
359 return null;
361 DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
362 while (node != null) {
363 final Object userObject = node.getUserObject();
364 if (userObject instanceof AntBuildFileNodeDescriptor) {
365 return (AntBuildFileNodeDescriptor)userObject;
367 node = (DefaultMutableTreeNode)node.getParent();
369 return null;
372 private void popupInvoked(final Component comp, final int x, final int y) {
373 Object userObject = null;
374 final TreePath path = myTree.getSelectionPath();
375 if (path != null) {
376 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
377 if (node != null) {
378 userObject = node.getUserObject();
381 final DefaultActionGroup group = new DefaultActionGroup();
382 group.add(new RunAction());
383 group.add(new CreateMetaTargetAction());
384 group.add(new RemoveMetaTargetsOrBuildFileAction());
385 group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
386 if (userObject instanceof AntBuildFileNodeDescriptor) {
387 group.add(new RemoveBuildFileAction(this));
389 if (userObject instanceof AntTargetNodeDescriptor) {
390 final AntBuildTargetBase target = ((AntTargetNodeDescriptor)userObject).getTarget();
391 final DefaultActionGroup executeOnGroup =
392 new DefaultActionGroup(AntBundle.message("ant.explorer.execute.on.action.group.name"), true);
393 executeOnGroup.add(new ExecuteOnEventAction(target, ExecuteBeforeCompilationEvent.getInstance()));
394 executeOnGroup.add(new ExecuteOnEventAction(target, ExecuteAfterCompilationEvent.getInstance()));
395 executeOnGroup.addSeparator();
396 executeOnGroup.add(new ExecuteBeforeRunAction(target));
397 group.add(executeOnGroup);
398 group.add(new AssignShortcutAction(target.getActionId()));
400 group.add(myAntBuildFilePropertiesAction);
401 final ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.ANT_EXPLORER_POPUP, group);
402 popupMenu.getComponent().show(comp, x, y);
405 @Nullable
406 public Object getData(@NonNls String dataId) {
407 if (PlatformDataKeys.NAVIGATABLE.is(dataId)) {
408 final AntBuildFile buildFile = getCurrentBuildFile();
409 if (buildFile == null) {
410 return null;
412 final VirtualFile file = buildFile.getVirtualFile();
413 if (file == null) {
414 return null;
416 final TreePath treePath = myTree.getLeadSelectionPath();
417 if (treePath == null) {
418 return null;
420 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)treePath.getLastPathComponent();
421 if (node == null) {
422 return null;
424 if (node.getUserObject() instanceof AntTargetNodeDescriptor) {
425 final AntTargetNodeDescriptor targetNodeDescriptor = (AntTargetNodeDescriptor)node.getUserObject();
426 final AntBuildTargetBase buildTarget = targetNodeDescriptor.getTarget();
427 final OpenFileDescriptor descriptor = buildTarget.getOpenFileDescriptor();
428 if (descriptor != null) {
429 final VirtualFile descriptorFile = descriptor.getFile();
430 if (descriptorFile.isValid()) {
431 return descriptor;
435 if (file.isValid()) {
436 return new OpenFileDescriptor(myProject, file);
439 else if (PlatformDataKeys.HELP_ID.is(dataId)) {
440 return HelpID.ANT;
442 else if (PlatformDataKeys.TREE_EXPANDER.is(dataId)) {
443 return myTreeExpander;
445 else if (PlatformDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) {
446 final TreePath[] paths = myTree.getSelectionPaths();
447 if (paths == null) {
448 return null;
450 final ArrayList<VirtualFile> result = new ArrayList<VirtualFile>();
451 for (final TreePath path : paths) {
452 for (DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
453 node != null;
454 node = (DefaultMutableTreeNode)node.getParent()) {
455 final Object userObject = node.getUserObject();
456 if (!(userObject instanceof AntBuildFileNodeDescriptor)) {
457 continue;
459 final AntBuildFile buildFile = ((AntBuildFileNodeDescriptor)userObject).getBuildFile();
460 if (buildFile != null) {
461 final VirtualFile virtualFile = buildFile.getVirtualFile();
462 if (virtualFile != null && virtualFile.isValid()) {
463 result.add(virtualFile);
466 break;
469 if (result.size() == 0) {
470 return null;
472 return VfsUtil.toVirtualFileArray(result);
474 return null;
477 public static FileChooserDescriptor createXmlDescriptor() {
478 return new FileChooserDescriptor(true, false, false, false, false, true){
479 public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
480 boolean b = super.isFileVisible(file, showHiddenFiles);
481 if (!file.isDirectory()) {
482 b &= StdFileTypes.XML.equals(FileTypeManager.getInstance().getFileTypeByFile(file));
484 return b;
489 private static final class NodeRenderer extends ColoredTreeCellRenderer {
490 public void customizeCellRenderer(JTree tree,
491 Object value,
492 boolean selected,
493 boolean expanded,
494 boolean leaf,
495 int row,
496 boolean hasFocus) {
497 final Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
498 if (userObject instanceof AntNodeDescriptor) {
499 final AntNodeDescriptor descriptor = (AntNodeDescriptor)userObject;
500 descriptor.customize(this);
502 else {
503 append(tree.convertValueToText(value, selected, expanded, leaf, row, hasFocus), SimpleTextAttributes.REGULAR_ATTRIBUTES);
508 private final class AddAction extends AnAction {
509 public AddAction() {
510 super(AntBundle.message("add.ant.file.action.name"), AntBundle.message("add.ant.file.action.description"), ICON_ADD);
513 public void actionPerformed(AnActionEvent e) {
514 addBuildFile();
518 private final class RemoveAction extends AnAction {
519 public RemoveAction() {
520 super(AntBundle.message("remove.ant.file.action.name"), AntBundle.message("remove.ant.file.action.description"), ICON_REMOVE);
523 public void actionPerformed(AnActionEvent e) {
524 removeBuildFile();
527 public void update(AnActionEvent event) {
528 event.getPresentation().setEnabled(getCurrentBuildFile() != null);
532 private final class RunAction extends AnAction {
533 public RunAction() {
534 super(AntBundle.message("run.ant.file.or.target.action.name"), AntBundle.message("run.ant.file.or.target.action.description"), ICON_RUN);
537 public void actionPerformed(AnActionEvent e) {
538 runSelection(e.getDataContext());
541 public void update(AnActionEvent event) {
542 final Presentation presentation = event.getPresentation();
543 final String place = event.getPlace();
544 if (ActionPlaces.ANT_EXPLORER_TOOLBAR.equals(place)) {
545 presentation.setText(AntBundle.message("run.ant.file.or.target.action.name"));
547 else {
548 final TreePath[] paths = myTree.getSelectionPaths();
549 if (paths != null && paths.length == 1 &&
550 ((DefaultMutableTreeNode)paths[0].getLastPathComponent()).getUserObject() instanceof AntBuildFileNodeDescriptor) {
551 presentation.setText(AntBundle.message("run.ant.build.action.name"));
553 else {
554 if (paths == null || paths.length == 1) {
555 presentation.setText(AntBundle.message("run.ant.target.action.name"));
557 else {
558 presentation.setText(AntBundle.message("run.ant.targets.action.name"));
563 presentation.setEnabled(canRunSelection());
567 private final class ShowAllTargetsAction extends ToggleAction {
568 public ShowAllTargetsAction() {
569 super(AntBundle.message("filter.ant.targets.action.name"), AntBundle.message("filter.ant.targets.action.description"), ICON_FILTER);
572 public boolean isSelected(AnActionEvent event) {
573 final Project project = myProject;
574 return project != null? AntConfigurationBase.getInstance(project).isFilterTargets() : false;
577 public void setSelected(AnActionEvent event, boolean flag) {
578 setTargetsFiltered(flag);
582 private void setTargetsFiltered(boolean value) {
583 myBuilder.setTargetsFiltered(value);
584 AntConfigurationBase.getInstance(myProject).setFilterTargets(value);
587 private final class ExecuteOnEventAction extends ToggleAction {
588 private final AntBuildTargetBase myTarget;
589 private final ExecutionEvent myExecutionEvent;
591 public ExecuteOnEventAction(final AntBuildTargetBase target, final ExecutionEvent executionEvent) {
592 super(executionEvent.getPresentableName());
593 myTarget = target;
594 myExecutionEvent = executionEvent;
597 public boolean isSelected(AnActionEvent e) {
598 return myTarget.equals(AntConfigurationBase.getInstance(myProject).getTargetForEvent(myExecutionEvent));
601 public void setSelected(AnActionEvent event, boolean state) {
602 final AntConfigurationBase antConfiguration = AntConfigurationBase.getInstance(myProject);
603 if (state) {
604 final AntBuildFileBase buildFile =
605 (AntBuildFileBase)((myTarget instanceof MetaTarget) ? ((MetaTarget)myTarget).getBuildFile() : myTarget.getModel().getBuildFile());
606 antConfiguration.setTargetForEvent(buildFile, myTarget.getName(), myExecutionEvent);
608 else {
609 antConfiguration.clearTargetForEvent(myExecutionEvent);
611 myBuilder.refresh();
614 public void update(AnActionEvent e) {
615 super.update(e);
616 final AntBuildFile buildFile = myTarget.getModel().getBuildFile();
617 e.getPresentation().setEnabled(buildFile != null && buildFile.exists());
621 private final class ExecuteBeforeRunAction extends AnAction {
622 private final AntBuildTarget myTarget;
624 public ExecuteBeforeRunAction(final AntBuildTarget target) {
625 super(AntBundle.message("executes.before.run.debug.acton.name"));
626 myTarget = target;
629 public void actionPerformed(AnActionEvent e) {
630 final AntExecuteBeforeRunDialog dialog = new AntExecuteBeforeRunDialog(myProject, myTarget);
631 dialog.show();
634 public void update(AnActionEvent e) {
635 e.getPresentation().setEnabled(myTarget.getModel().getBuildFile().exists());
639 private final class CreateMetaTargetAction extends AnAction {
641 public CreateMetaTargetAction() {
642 super(AntBundle.message("ant.create.meta.target.action.name"), AntBundle.message("ant.create.meta.target.action.description"), null
643 /*IconLoader.getIcon("/actions/execute.png")*/);
646 public void actionPerformed(AnActionEvent e) {
647 final AntBuildFile buildFile = getCurrentBuildFile();
648 final String[] targets = getTargetNamesFromPaths(myTree.getSelectionPaths());
649 final ExecuteCompositeTargetEvent event = new ExecuteCompositeTargetEvent(targets);
650 final SaveMetaTargetDialog dialog = new SaveMetaTargetDialog(myTree, event, AntConfigurationBase.getInstance(myProject), buildFile);
651 dialog.setTitle(e.getPresentation().getText());
652 dialog.show();
653 if (dialog.isOK()) {
654 myBuilder.refresh();
655 myTree.repaint();
659 public void update(AnActionEvent e) {
660 final TreePath[] paths = myTree.getSelectionPaths();
661 e.getPresentation().setEnabled(paths != null && paths.length > 1 && canRunSelection());
665 private final class RemoveMetaTargetsOrBuildFileAction extends AnAction {
667 public RemoveMetaTargetsOrBuildFileAction() {
668 super(AntBundle.message("remove.meta.targets.action.name"), AntBundle.message("remove.meta.targets.action.description"), null);
669 registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)), myTree);
670 myDisposables.add(new Disposable() {
671 public void dispose() {
672 RemoveMetaTargetsOrBuildFileAction.this.unregisterCustomShortcutSet(myTree);
675 myTree.registerKeyboardAction(new AbstractAction() {
676 public void actionPerformed(ActionEvent e) {
677 doAction();
679 }, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
682 public void actionPerformed(AnActionEvent e) {
683 doAction();
686 private void doAction() {
687 final TreePath[] paths = myTree.getSelectionPaths();
688 if (paths == null) {
689 return;
691 try {
692 // try to remove build file
693 if (paths.length == 1) {
694 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)paths[0].getLastPathComponent();
695 if (node.getUserObject() instanceof AntBuildFileNodeDescriptor) {
696 final AntBuildFileNodeDescriptor descriptor = (AntBuildFileNodeDescriptor)node.getUserObject();
697 if (descriptor.getBuildFile().equals(getCurrentBuildFile())) {
698 removeBuildFile();
699 return;
703 // try to remove meta targets
704 final AntBuildTarget[] targets = getTargetObjectsFromPaths(paths);
705 final AntConfigurationBase antConfiguration = AntConfigurationBase.getInstance(myProject);
706 for (final AntBuildTarget buildTarget : targets) {
707 if (buildTarget instanceof MetaTarget) {
708 for (final ExecutionEvent event : antConfiguration.getEventsForTarget(buildTarget)) {
709 if (event instanceof ExecuteCompositeTargetEvent) {
710 antConfiguration.clearTargetForEvent(event);
716 finally {
717 myBuilder.refresh();
718 myTree.repaint();
722 public void update(AnActionEvent e) {
723 final Presentation presentation = e.getPresentation();
724 final TreePath[] paths = myTree.getSelectionPaths();
725 if (paths == null) {
726 presentation.setEnabled(false);
727 return;
730 if (paths.length == 1) {
731 String text = AntBundle.message("remove.meta.target.action.name");
732 boolean enabled = false;
733 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)paths[0].getLastPathComponent();
734 if (node.getUserObject() instanceof AntBuildFileNodeDescriptor) {
735 final AntBuildFileNodeDescriptor descriptor = (AntBuildFileNodeDescriptor)node.getUserObject();
736 if (descriptor.getBuildFile().equals(getCurrentBuildFile())) {
737 text = AntBundle.message("remove.selected.build.file.action.name");
738 enabled = true;
741 else {
742 if (node.getUserObject() instanceof AntTargetNodeDescriptor) {
743 final AntTargetNodeDescriptor descr = (AntTargetNodeDescriptor)node.getUserObject();
744 final AntBuildTargetBase target = descr.getTarget();
745 if (target instanceof MetaTarget) {
746 enabled = true;
750 presentation.setText(text);
751 presentation.setEnabled(enabled);
753 else {
754 presentation.setText(AntBundle.message("remove.selected.meta.targets.action.name"));
755 final AntBuildTarget[] targets = getTargetObjectsFromPaths(paths);
756 boolean enabled = targets.length > 0;
757 for (final AntBuildTarget buildTarget : targets) {
758 if (!(buildTarget instanceof MetaTarget)) {
759 enabled = false;
760 break;
763 presentation.setEnabled(enabled);
768 private final class AssignShortcutAction extends AnAction {
769 private final String myActionId;
771 public AssignShortcutAction(String actionId) {
772 super(AntBundle.message("ant.explorer.assign.shortcut.action.name"));
773 myActionId = actionId;
776 public void actionPerformed(AnActionEvent e) {
777 new EditKeymapsDialog(myProject, myActionId).show();
780 public void update(AnActionEvent e) {
781 e.getPresentation().setEnabled(myActionId != null && ActionManager.getInstance().getAction(myActionId) != null);
785 private class KeymapListener implements KeymapManagerListener, Keymap.Listener {
786 private Keymap myCurrentKeymap = null;
788 public KeymapListener() {
789 final KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx();
790 final Keymap activeKeymap = keymapManager.getActiveKeymap();
791 listenTo(activeKeymap);
792 keymapManager.addKeymapManagerListener(this);
795 public void activeKeymapChanged(Keymap keymap) {
796 listenTo(keymap);
797 updateTree();
800 private void listenTo(Keymap keymap) {
801 if (myCurrentKeymap != null) {
802 myCurrentKeymap.removeShortcutChangeListener(this);
804 myCurrentKeymap = keymap;
805 if (myCurrentKeymap != null) {
806 myCurrentKeymap.addShortcutChangeListener(this);
810 private void updateTree() {
811 myBuilder.updateFromRoot();
814 public void onShortcutChanged(String actionId) {
815 updateTree();
818 public void stopListen() {
819 listenTo(null);
820 KeymapManagerEx.getInstanceEx().removeKeymapManagerListener(this);