001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.apache.tools.ant.module.nodes;
043:
044: import java.awt.event.ActionEvent;
045: import java.awt.event.ActionListener;
046: import java.io.IOException;
047: import java.text.Collator;
048: import java.util.Collection;
049: import java.util.Collections;
050: import java.util.Set;
051: import java.util.SortedSet;
052: import java.util.TreeSet;
053: import javax.swing.AbstractAction;
054: import javax.swing.Action;
055: import javax.swing.JButton;
056: import javax.swing.JMenu;
057: import javax.swing.JMenuItem;
058: import javax.swing.JPopupMenu;
059: import org.apache.tools.ant.module.AntModule;
060: import org.apache.tools.ant.module.api.AntProjectCookie;
061: import org.apache.tools.ant.module.api.support.TargetLister;
062: import org.apache.tools.ant.module.run.TargetExecutor;
063: import org.openide.DialogDescriptor;
064: import org.openide.DialogDisplayer;
065: import org.openide.ErrorManager;
066: import org.openide.NotifyDescriptor;
067: import org.openide.awt.Actions;
068: import org.openide.util.ContextAwareAction;
069: import org.openide.util.HelpCtx;
070: import org.openide.util.Lookup;
071: import org.openide.util.NbBundle;
072: import org.openide.util.RequestProcessor;
073: import org.openide.util.actions.Presenter;
074: import org.openide.util.actions.SystemAction;
075:
076: /**
077: * Submenu which permits the user to run various targets from the project.
078: * Distinction made between the main target, other documented targets, and other
079: * undocumented targets.
080: */
081: public final class RunTargetsAction extends SystemAction implements
082: ContextAwareAction {
083:
084: @Override
085: public String getName() {
086: return NbBundle.getMessage(RunTargetsAction.class,
087: "LBL_run_targets_action");
088: }
089:
090: @Override
091: public HelpCtx getHelpCtx() {
092: return HelpCtx.DEFAULT_HELP;
093: }
094:
095: @Override
096: public void actionPerformed(ActionEvent e) {
097: assert false : "Action should never be called without a context";
098: }
099:
100: public Action createContextAwareInstance(Lookup actionContext) {
101: return new ContextAction(actionContext);
102: }
103:
104: /**
105: * The particular instance of this action for a given project.
106: */
107: private static final class ContextAction extends AbstractAction
108: implements Presenter.Popup {
109:
110: private final AntProjectCookie project;
111:
112: public ContextAction(Lookup lkp) {
113: super (SystemAction.get(RunTargetsAction.class).getName());
114: Collection<? extends AntProjectCookie> apcs = lkp
115: .lookupAll(AntProjectCookie.class);
116: AntProjectCookie _project = null;
117: if (apcs.size() == 1) {
118: _project = apcs.iterator().next();
119: if (_project.getParseException() != null) {
120: _project = null;
121: }
122: }
123: project = _project;
124: super .setEnabled(project != null);
125: }
126:
127: public void actionPerformed(ActionEvent e) {
128: assert false : "Action should not be called directly";
129: }
130:
131: public JMenuItem getPopupPresenter() {
132: if (project != null) {
133: return createMenu(project);
134: } else {
135: return new Actions.MenuItem(this , false);
136: }
137: }
138:
139: @Override
140: public void setEnabled(boolean b) {
141: assert false : "No modifications to enablement status permitted";
142: }
143:
144: }
145:
146: /**
147: * Create the submenu.
148: */
149: private static JMenu createMenu(AntProjectCookie project) {
150: return new LazyMenu(project);
151: }
152:
153: private static final class LazyMenu extends JMenu {
154:
155: private final AntProjectCookie project;
156: private boolean initialized = false;
157:
158: public LazyMenu(AntProjectCookie project) {
159: super (SystemAction.get(RunTargetsAction.class).getName());
160: this .project = project;
161: }
162:
163: @Override
164: public JPopupMenu getPopupMenu() {
165: if (!initialized) {
166: initialized = true;
167: Set<TargetLister.Target> allTargets;
168: try {
169: allTargets = TargetLister.getTargets(project);
170: } catch (IOException e) {
171: // XXX how to notify properly?
172: AntModule.err.notify(ErrorManager.INFORMATIONAL, e);
173: allTargets = Collections.emptySet();
174: }
175: String defaultTarget = null;
176: SortedSet<String> describedTargets = new TreeSet<String>(
177: Collator.getInstance());
178: SortedSet<String> otherTargets = new TreeSet<String>(
179: Collator.getInstance());
180: for (TargetLister.Target t : allTargets) {
181: if (t.isOverridden()) {
182: // Cannot be called.
183: continue;
184: }
185: if (t.isInternal()) {
186: // Don't present in GUI.
187: continue;
188: }
189: String name = t.getName();
190: if (t.isDefault()) {
191: defaultTarget = name;
192: } else if (t.isDescribed()) {
193: describedTargets.add(name);
194: } else {
195: otherTargets.add(name);
196: }
197: }
198: boolean needsep = false;
199: if (defaultTarget != null) {
200: needsep = true;
201: JMenuItem menuitem = new JMenuItem(defaultTarget);
202: menuitem
203: .addActionListener(new TargetMenuItemHandler(
204: project, defaultTarget));
205: add(menuitem);
206: }
207: if (needsep) {
208: needsep = false;
209: addSeparator();
210: }
211: if (!describedTargets.isEmpty()) {
212: needsep = true;
213: for (String target : describedTargets) {
214: JMenuItem menuitem = new JMenuItem(target);
215: menuitem
216: .addActionListener(new TargetMenuItemHandler(
217: project, target));
218: add(menuitem);
219: }
220: }
221: if (needsep) {
222: needsep = false;
223: addSeparator();
224: }
225: if (!otherTargets.isEmpty()) {
226: needsep = true;
227: JMenu submenu = new JMenu(NbBundle.getMessage(
228: RunTargetsAction.class,
229: "LBL_run_other_targets"));
230: for (String target : otherTargets) {
231: JMenuItem menuitem = new JMenuItem(target);
232: menuitem
233: .addActionListener(new TargetMenuItemHandler(
234: project, target));
235: submenu.add(menuitem);
236: }
237: add(submenu);
238: }
239: if (needsep) {
240: needsep = false;
241: addSeparator();
242: }
243: add(new AdvancedAction(project, allTargets));
244: }
245: return super .getPopupMenu();
246: }
247:
248: }
249:
250: /**
251: * Action handler for a menu item representing one target.
252: */
253: private static final class TargetMenuItemHandler implements
254: ActionListener, Runnable {
255:
256: private final AntProjectCookie project;
257: private final String target;
258:
259: public TargetMenuItemHandler(AntProjectCookie project,
260: String target) {
261: this .project = project;
262: this .target = target;
263: }
264:
265: public void actionPerformed(ActionEvent ev) {
266: // #16720 part 2: don't do this in the event thread...
267: RequestProcessor.getDefault().post(this );
268: }
269:
270: public void run() {
271: try {
272: TargetExecutor te = new TargetExecutor(project,
273: new String[] { target });
274: te.execute();
275: } catch (IOException ioe) {
276: AntModule.err.notify(ioe);
277: }
278: }
279:
280: }
281:
282: /**
283: * Menu item to let the user select a random target(s), and set properties and verbosity.
284: */
285: private static final class AdvancedAction extends AbstractAction {
286:
287: private final AntProjectCookie project;
288: private final Set<TargetLister.Target> allTargets;
289:
290: public AdvancedAction(AntProjectCookie project,
291: Set<TargetLister.Target> allTargets) {
292: super (NbBundle.getMessage(RunTargetsAction.class,
293: "LBL_run_advanced"));
294: this .project = project;
295: this .allTargets = allTargets;
296: }
297:
298: public void actionPerformed(ActionEvent e) {
299: String title = NbBundle.getMessage(RunTargetsAction.class,
300: "TITLE_run_advanced");
301: AdvancedActionPanel panel = new AdvancedActionPanel(
302: project, allTargets);
303: DialogDescriptor dd = new DialogDescriptor(panel, title);
304: dd.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION);
305: JButton run = new JButton(NbBundle.getMessage(
306: RunTargetsAction.class, "LBL_run_advanced_run"));
307: run.setDefaultCapable(true);
308: JButton cancel = new JButton(NbBundle.getMessage(
309: RunTargetsAction.class, "LBL_run_advanced_cancel"));
310: dd.setOptions(new Object[] { run, cancel });
311: dd.setModal(true);
312: Object result = DialogDisplayer.getDefault().notify(dd);
313: if (result.equals(run)) {
314: try {
315: panel.run();
316: } catch (IOException x) {
317: AntModule.err.notify(x);
318: }
319: }
320: }
321:
322: }
323:
324: }
|