blob: 4830bdade124374fc604a6a1ae350e9b352bb6a6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.ant.debugger;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.text.Collator;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.apache.tools.ant.module.AntModule;
import org.apache.tools.ant.module.api.AntProjectCookie;
import org.apache.tools.ant.module.api.AntTargetExecutor;
import org.apache.tools.ant.module.api.support.TargetLister;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.awt.Actions;
import org.openide.execution.ExecutorTask;
import org.openide.util.ContextAwareAction;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.actions.Presenter;
/**
* Submenu which permits the user to debug various targets from the project.
* Distinction made between the main target, other documented targets, and other
* undocumented targets.
*/
@ActionID(id = "org.netbeans.modules.ant.debugger.RunTargetsAction", category = "Build")
@ActionRegistration(displayName = "", lazy=false)
@ActionReference(path = "Loaders/text/x-ant+xml/Actions", position = 300)
@NbBundle.Messages("LBL_run_targets_action=Debug Target")
public final class RunTargetsAction extends AbstractAction implements ContextAwareAction {
@Override
public void actionPerformed(ActionEvent e) {
assert false : "Action should never be called without a context";
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new ContextAction(actionContext);
}
/**
* The particular instance of this action for a given project.
*/
private static final class ContextAction extends AbstractAction implements Presenter.Popup {
private final AntProjectCookie project;
public ContextAction(Lookup lkp) {
super(Bundle.LBL_run_targets_action());
Collection<? extends AntProjectCookie> apcs = lkp.lookupAll(AntProjectCookie.class);
AntProjectCookie _project = null;
if (apcs.size() == 1) {
_project = apcs.iterator().next();
if (_project.getParseException() != null) {
_project = null;
}
}
project = _project;
super.setEnabled(project != null);
}
@Override
public void actionPerformed(ActionEvent e) {
assert false : "Action should not be called directly";
}
@Override
public JMenuItem getPopupPresenter() {
if (project != null) {
return createMenu(project);
} else {
return new Actions.MenuItem(this, false);
}
}
@Override
public void setEnabled(boolean b) {
assert false : "No modifications to enablement status permitted";
}
}
/**
* Create the sub-menu.
*/
private static JMenu createMenu(AntProjectCookie project) {
return new LazyMenu(project);
}
private static final class LazyMenu extends JMenu {
private final AntProjectCookie project;
private boolean initialized = false;
public LazyMenu(AntProjectCookie project) {
super(Bundle.LBL_run_targets_action());
this.project = project;
}
@Override
public JPopupMenu getPopupMenu() {
if (!initialized) {
initialized = true;
Set<TargetLister.Target> allTargets;
try {
allTargets = TargetLister.getTargets(project);
} catch (IOException e) {
DialogDisplayer.getDefault().notify(
new NotifyDescriptor.Message(e.getLocalizedMessage()));
allTargets = Collections.emptySet();
}
String defaultTarget = null;
SortedSet<String> describedTargets = new TreeSet<>(Collator.getInstance());
SortedSet<String> otherTargets = new TreeSet<>(Collator.getInstance());
for (TargetLister.Target t : allTargets) {
if (t.isOverridden()) {
// Cannot be called.
continue;
}
if (t.isInternal()) {
// Don't present in GUI.
continue;
}
String name = t.getName();
if (t.isDefault()) {
defaultTarget = name;
} else if (t.isDescribed()) {
describedTargets.add(name);
} else {
otherTargets.add(name);
}
}
boolean needsep = false;
VerticalGridLayout vgl = new VerticalGridLayout();
getPopupMenu().setLayout(vgl);
if (defaultTarget != null) {
needsep = true;
JMenuItem menuitem = new JMenuItem(defaultTarget);
menuitem.addActionListener(new TargetMenuItemHandler(project, defaultTarget));
add(menuitem);
}
if (needsep) {
needsep = false;
addSeparator();
}
if (!describedTargets.isEmpty()) {
needsep = true;
for (String target : describedTargets) {
JMenuItem menuitem = new JMenuItem(target);
menuitem.addActionListener(new TargetMenuItemHandler(project, target));
add(menuitem);
}
}
if (needsep) {
needsep = false;
addSeparator();
}
if (!otherTargets.isEmpty()) {
needsep = true;
JMenu submenu = new JMenu(NbBundle.getMessage(RunTargetsAction.class, "LBL_run_other_targets"));
VerticalGridLayout submenuVgl = new VerticalGridLayout();
submenu.getPopupMenu().setLayout(submenuVgl);
for (String target : otherTargets) {
JMenuItem menuitem = new JMenuItem(target);
menuitem.addActionListener(new TargetMenuItemHandler(project, target));
submenu.add(menuitem);
}
add(submenu);
}
if (needsep) {
needsep = false;
addSeparator();
}
add(new AdvancedAction(project, allTargets));
}
return super.getPopupMenu();
}
}
/**
* Action handler for a menu item representing one target.
*/
static final class TargetMenuItemHandler implements ActionListener, Runnable {
private final AntProjectCookie project;
private final String target;
public TargetMenuItemHandler(AntProjectCookie project, String target) {
this.project = project;
this.target = target;
}
@Override
public void actionPerformed(ActionEvent ev) {
// #16720 part 2: don't do this in the event thread...
RequestProcessor.getDefault().post(this);
}
@Override
public void run() {
try {
DebuggerAntLogger.getDefault ().debugFile (project.getFile ());
AntTargetExecutor.Env env = new AntTargetExecutor.Env ();
AntTargetExecutor executor = AntTargetExecutor.createTargetExecutor
(env);
ExecutorTask executorTask = executor.execute
(project, new String[] {target});
DebuggerAntLogger.getDefault().fileExecutor(project.getFile(), executorTask);
} catch (IOException ioe) {
AntModule.err.notify(ioe);
}
}
}
/**
* Menu item to let the user select a random target(s), and set properties and verbosity.
*/
private static final class AdvancedAction extends AbstractAction {
private final AntProjectCookie project;
private final Set<TargetLister.Target> allTargets;
public AdvancedAction(AntProjectCookie project, Set/*<TargetLister.Target>*/ allTargets) {
super(NbBundle.getMessage(RunTargetsAction.class, "LBL_run_advanced"));
this.project = project;
this.allTargets = allTargets;
}
@Override
public void actionPerformed(ActionEvent e) {
String title = NbBundle.getMessage(RunTargetsAction.class, "TITLE_run_advanced");
AdvancedActionPanel panel = new AdvancedActionPanel(project, allTargets);
DialogDescriptor dd = new DialogDescriptor(panel, title);
dd.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION);
JButton run = new JButton(NbBundle.getMessage(RunTargetsAction.class, "LBL_run_advanced_run"));
run.setDefaultCapable(true);
JButton cancel = new JButton(NbBundle.getMessage(RunTargetsAction.class, "LBL_run_advanced_cancel"));
dd.setOptions(new Object[] {run, cancel});
dd.setModal(true);
Object result = DialogDisplayer.getDefault().notify(dd);
if (result.equals(run)) {
try {
panel.run();
} catch (IOException x) {
AntModule.err.notify(x);
}
}
}
}
}