0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.cnd.makewizard;
0043:
0044: import java.beans.PropertyChangeEvent;
0045: import java.beans.PropertyChangeListener;
0046: import java.io.File;
0047: import java.io.IOException;
0048: import java.text.MessageFormat;
0049: import java.util.ArrayList;
0050: import java.util.Collections;
0051: import java.util.HashSet;
0052: import java.util.Iterator;
0053: import java.util.LinkedList;
0054: import java.util.ListIterator;
0055: import java.util.NoSuchElementException;
0056: import java.util.Set;
0057: import java.util.Vector;
0058: import javax.swing.JButton;
0059: import javax.swing.JPanel;
0060: import javax.swing.event.ChangeEvent;
0061: import javax.swing.event.ChangeListener;
0062: import org.netbeans.modules.cnd.builds.MakeExecSupport;
0063: import org.netbeans.modules.cnd.settings.MakeSettings;
0064: import org.netbeans.modules.cnd.api.utils.IpeUtils;
0065: import org.openide.DialogDescriptor;
0066: import org.openide.WizardDescriptor;
0067: import org.openide.cookies.OpenCookie;
0068: import org.openide.filesystems.FileObject;
0069: import org.openide.filesystems.FileUtil;
0070: import org.openide.loaders.DataFolder;
0071: import org.openide.loaders.DataObject;
0072: import org.openide.loaders.TemplateWizard;
0073: import org.openide.util.NbBundle;
0074:
0075: public class MakefileWizard implements TemplateWizard.Iterator {
0076: /** Holds list of event listeners */
0077: private static Vector listenerList = null;
0078:
0079: protected TemplateWizard wd;
0080:
0081: /** Current array of panels */
0082: protected Object[] panels;
0083:
0084: /** Store a pointer to the current panel */
0085: private WizardDescriptor.Panel currentPanel;
0086:
0087: /** Array of panels for all types except
0088: * MakefileData.COMPLEX_MAKEFILE_TYPE.
0089: */
0090: protected Object[] normalPanels;
0091:
0092: /** LinkedList of panels for MakefileData.COMPLEX_MAKEFILE_TYPE */
0093: protected LinkedList complexPanels;
0094:
0095: /** Makefile data */
0096: private MakefileData makefileData;
0097:
0098: /** The MakefileWizard */
0099: private static MakefileWizard makefileWizard;
0100:
0101: /** Wizard title */
0102: private String title;
0103:
0104: /** Index into the array */
0105: private int index;
0106:
0107: /** The index into the displayed steps (different than index) */
0108: private int virtIndex;
0109:
0110: /** Index into complexPanels where new panels should be added */
0111: private int addIdx;
0112:
0113: /** The Next button is needed to reset the default button */
0114: private JButton nextButton;
0115:
0116: /** The Finish button is needed to change the label to Last */
0117: private JButton finishButton;
0118:
0119: /** The cancel button */
0120: private JButton cancelButton;
0121:
0122: /** Save the Finish button's original label */
0123: private String finishLabel;
0124:
0125: /** Save the Finish button's original mnemonic too */
0126: private int finishMnemonic;
0127:
0128: /** Are we doing Last updates to keep it enabled? */
0129: private boolean finishEnabled;
0130:
0131: /** Tells if we have output the Compilation Preferences yet */
0132: private boolean haveCompilerFlags;
0133:
0134: /** template wizard property change listener ... */
0135: private PropertyChangeListener listener = null;
0136:
0137: private WizardDescriptor.Panel targetChooserDescriptorPanel;
0138: private WizardDescriptor.Panel baseDirectoryDescriptorPanel;
0139: private WizardDescriptor.Panel targetNameDescriptorPanel;
0140: private WizardDescriptor.Panel makefileSourcesDescriptorPanel;
0141: private WizardDescriptor.Panel selectPreferencesDescriptorPanel;
0142: //private WizardDescriptor.Panel compilerTypeDescriptorPanel;
0143: private WizardDescriptor.Panel platformTypeDescriptorPanel;
0144: private WizardDescriptor.Panel createTargetsDescriptorPanel;
0145: private WizardDescriptor.Panel buildOutputDescriptorPanel;
0146: private WizardDescriptor.Panel makefileIncludesDescriptorPanel;
0147: private WizardDescriptor.Panel standardLibsDescriptorPanel;
0148: private WizardDescriptor.Panel userLibsDescriptorPanel;
0149: private WizardDescriptor.Panel compilerOptionsDescriptorPanel;
0150: private WizardDescriptor.Panel basicFlagsDescriptorPanel;
0151: private WizardDescriptor.Panel compilerPathDescriptorPanel;
0152: //private WizardDescriptor.Panel makeTargetDescriptorPanel;
0153: //private WizardDescriptor.Panel customTargetDescriptorPanel;
0154: private WizardDescriptor.Panel makefileReviewDescriptorPanel;
0155:
0156: /**
0157: * Constructor Note: A panel object gets created for each panel in this
0158: * constructor. However, the object creation is very light-weight
0159: * (mainly just creating the subtitle) and the real creation is deffered
0160: * until the panel is displayed for the first time.
0161: */
0162: public MakefileWizard() {
0163: makefileWizard = this ;
0164: String title = NbBundle.getBundle(MakefileWizard.class)
0165: .getString("LBL_MakefileWizardTitle"); // NOI18N
0166: setTitle(title);
0167: makefileData = new MakefileData();
0168: }
0169:
0170: private void initPanels() {
0171: // Panels used in both SIMPLE_* and COMPLEX_* targets
0172: targetChooserDescriptorPanel = wd.targetChooser();
0173: baseDirectoryDescriptorPanel = new MakefileWizardDescriptorPanel(
0174: new BaseDirectoryPanel(this ), "base_directory"); // NOI18N
0175: targetNameDescriptorPanel = new MakefileWizardDescriptorPanel(
0176: new TargetNamePanel(this ), "target_name"); // NOI18N
0177: makefileSourcesDescriptorPanel = new MakefileWizardDescriptorPanel(
0178: new MakefileSourcesPanel(this ), "source_files"); // NOI18N
0179: //compilerTypeDescriptorPanel = new MakefileWizardDescriptorPanel(new CompilerTypePanel(this));
0180: selectPreferencesDescriptorPanel = new MakefileWizardDescriptorPanel(
0181: new SelectPreferencesPanel(this ),
0182: "compiling_preference"); // NOI18N
0183:
0184: // Panels used by just the COMPLEX_* targets
0185: createTargetsDescriptorPanel = new MakefileWizardDescriptorPanel(
0186: new CreateTargetsPanel(this ), "list_of_targets"); // NOI18N
0187: platformTypeDescriptorPanel = new MakefileWizardDescriptorPanel(
0188: new PlatformTypePanel(this ), "type_and_platform"); // NOI18N
0189: buildOutputDescriptorPanel = new MakefileWizardDescriptorPanel(
0190: new BuildOutputPanel(this ), "build_output"); // NOI18N
0191: makefileIncludesDescriptorPanel = new MakefileWizardDescriptorPanel(
0192: new MakefileIncludesPanel(this ), "include_directories"); // NOI18N
0193: standardLibsDescriptorPanel = new MakefileWizardDescriptorPanel(
0194: new StandardLibsPanel(this ), "standard_libraries"); // NOI18N
0195: userLibsDescriptorPanel = new MakefileWizardDescriptorPanel(
0196: new UserLibsPanel(this ), "libraries"); // NOI18N
0197: basicFlagsDescriptorPanel = new MakefileWizardDescriptorPanel(
0198: new BasicFlagsPanel(this ), "basic_options"); // NOI18N
0199: compilerPathDescriptorPanel = new MakefileWizardDescriptorPanel(
0200: new CompilerPathPanel(this ), "compiler_paths"); // NOI18N
0201: //makeTargetDescriptorPanel = new MakefileWizardDescriptorPanel(new MakeTargetPanel(this));
0202: //customTargetDescriptorPanel = new MakefileWizardDescriptorPanel(new CustomTargetPanel(this));
0203: compilerOptionsDescriptorPanel = new MakefileWizardDescriptorPanel(
0204: new CompilerOptionsPanel(this ), "advanced_options"); // NOI18N
0205:
0206: // The review/summary panel
0207: makefileReviewDescriptorPanel = new MakefileWizardDescriptorPanel(
0208: new MakefileReviewPanel(this ), "review_makefile"); // NOI18N
0209:
0210: normalPanels = new WizardDescriptor.Panel[] {
0211: targetChooserDescriptorPanel,
0212: //compilerTypeDescriptorPanel,
0213: platformTypeDescriptorPanel, targetNameDescriptorPanel,
0214: makefileSourcesDescriptorPanel,
0215: selectPreferencesDescriptorPanel,
0216: makefileReviewDescriptorPanel };
0217:
0218: // Use a LinkedList for complexPanels because we add new panels to the
0219: // middle when new targets are added.
0220: complexPanels = new LinkedList();
0221: complexPanels.addLast(targetChooserDescriptorPanel);
0222: complexPanels.addLast(platformTypeDescriptorPanel);
0223: complexPanels.addLast(baseDirectoryDescriptorPanel);
0224: complexPanels.addLast(createTargetsDescriptorPanel);
0225: complexPanels.addLast(makefileReviewDescriptorPanel);
0226:
0227: panels = complexToArray();
0228: currentPanel = targetChooserDescriptorPanel;
0229:
0230: addIdx = 4;
0231: haveCompilerFlags = false;
0232: nextButton = null;
0233: finishButton = null;
0234: cancelButton = null;
0235: finishEnabled = false;
0236: }
0237:
0238: public TemplateWizard getTemplateWizard() {
0239: return wd;
0240: }
0241:
0242: /** Getter for the data associated with a panel */
0243: final public MakefileData getMakefileData() {
0244: return makefileData;
0245: }
0246:
0247: /** Setter for the title string */
0248: final public void setTitle(String title) {
0249: this .title = title;
0250: }
0251:
0252: /** Getter for Next button */
0253: public JButton getNextButton() {
0254: return nextButton;
0255: }
0256:
0257: /** Getter for Finish button */
0258: public JButton getFinishButton() {
0259: return finishButton;
0260: }
0261:
0262: /** Getter for Cancel button */
0263: public JButton getCancelButton() {
0264: return cancelButton;
0265: }
0266:
0267: /** Getter for Finish label */
0268: public String getFinishLabel() {
0269: return finishLabel;
0270: }
0271:
0272: /** Getter for Finish mnemonic */
0273: public int getFinishMnemonic() {
0274: return finishMnemonic;
0275: }
0276:
0277: /** Used to determine the current target's TargetData */
0278: public int getCurrentTargetKey() {
0279: int key = -1;
0280:
0281: if (makefileData.getMakefileType() < MakefileData.COMPLEX_MAKEFILE_TYPE) {
0282: key = 0;
0283: } else {
0284: for (int i = 0; i < panels.length; i++) {
0285: if (panels[i] instanceof StepHeader) {
0286: key = ((StepHeader) panels[i]).getKey();
0287: }
0288: if (i == index) {
0289: break;
0290: }
0291: }
0292: }
0293:
0294: return key;
0295: }
0296:
0297: /** The current panel.
0298: */
0299: public WizardDescriptor.Panel current() {
0300: return currentPanel;
0301: }
0302:
0303: /** Current name of the panel */
0304: public String name() {
0305: Object[] args = { new Integer(index + 1),
0306: new Integer(panels.length) };
0307: MessageFormat mf = new MessageFormat(NbBundle.getBundle(
0308: WizardDescriptor.class).getString(
0309: "CTL_ArrayIteratorName")); // NOI18N
0310:
0311: return mf.format(args);
0312: }
0313:
0314: /** Updates button state */
0315: public void updateStateHack() {
0316: //wd.updateState();
0317: // FIXUP: HACK - updateState is now protected in WizardDescriptor. Calling
0318: // FIXUP: setTitleFormat() has the sideeffect of calling updateState, so this works for now....
0319: if (wd != null)
0320: wd.setTitleFormat(new MessageFormat("{0}")); // NOI18N
0321: }
0322:
0323: /** Updates button state */
0324: public void updateState() {
0325: fireChangeEvent();
0326: }
0327:
0328: /**
0329: * Create the steps array for setting the Steps area in the wizard. Also,
0330: * set the virtIndex. The virtIndex is similar to index except it doesn't
0331: * count contracted panels. Its the index the WizardDescriptor uses to
0332: * correctly highlight the current step in the wizard.
0333: */
0334: private String[] getSteps() {
0335: String[] steps = new String[panels.length + 1];
0336: StepHeader hdr = null;
0337: int j = 1;
0338: int doingTarget = 0;
0339: int expand = 0;
0340: int virtIndex = 0;
0341:
0342: // Add templateChooser to 0th position...
0343: steps[0] = wd.templateChooser().getComponent().getName();
0344: for (int i = 0; i < panels.length; i++) {
0345: if (panels[i] instanceof StepHeader) {
0346: if (i < index) {
0347: virtIndex++;
0348: }
0349: hdr = (StepHeader) panels[i];
0350: steps[j++] = hdr.getTitle();
0351: doingTarget = hdr.getNum();
0352: if (index >= i && index <= (i + hdr.getNum())) {
0353: expand = hdr.getNum();
0354: }
0355: } else if (doingTarget-- > 0) {
0356: if (expand-- > 0) {
0357: if (i < index) {
0358: virtIndex++;
0359: }
0360: steps[j++] = NbBundle.getMessage(getClass(),
0361: "FMT_TARGET_PANEL", " ", // NOI18N
0362: ((WizardDescriptor.Panel) panels[i])
0363: .getComponent().getName());
0364: }
0365: } else {
0366: steps[j++] = ((WizardDescriptor.Panel) panels[i])
0367: .getComponent().getName();
0368: if (i < index) {
0369: virtIndex++;
0370: }
0371: }
0372: }
0373:
0374: // Now copy the overallocated steps array to nue
0375: String[] nue = new String[j];
0376: System.arraycopy(steps, 0, nue, 0, j);
0377: this .virtIndex = virtIndex;
0378: return nue;
0379: }
0380:
0381: /**
0382: * Set the current Makefile type. This has the side affect of changing the
0383: * array of panels wizard uses and the steps shown.
0384: */
0385: public void updatePanels(int type) {
0386: if (type >= MakefileData.COMPLEX_MAKEFILE_TYPE) {
0387: panels = complexToArray();
0388: } else {
0389: panels = normalPanels;
0390: }
0391: ((JPanel) currentPanel.getComponent()).putClientProperty(
0392: "WizardPanel_contentData", getSteps()); // NOI18N
0393: updateState();
0394: }
0395:
0396: /**
0397: * Is there a next panel?
0398: *
0399: * @return true if so
0400: */
0401: public boolean hasNext() {
0402: return (index) < (panels.length - 1);
0403: }
0404:
0405: /**
0406: * Is there a previous panel?
0407: *
0408: * @return true if so
0409: */
0410: public boolean hasPrevious() {
0411: return index > 0;
0412: }
0413:
0414: /**
0415: * Moves to the next panel. If the index points to a StepHeader then
0416: * skip that and show the next panel.
0417: *
0418: * @exception NoSuchElementException if the panel does not exist
0419: */
0420: public synchronized void nextPanel() {
0421: if (panels[++index] instanceof StepHeader) {
0422: index++;
0423: }
0424: currentPanel = (WizardDescriptor.Panel) panels[index];
0425: updatePanels(makefileData.getMakefileType());
0426:
0427: ((JPanel) currentPanel.getComponent()).putClientProperty(
0428: "WizardPanel_contentSelectedIndex", // NOI18N
0429: new Integer(virtIndex));
0430: }
0431:
0432: /**
0433: * Moves to previous panel.
0434: * @exception NoSuchElementException if the panel does not exist
0435: */
0436: public synchronized void previousPanel() {
0437:
0438: if (index == 0) {
0439: throw new NoSuchElementException();
0440: }
0441:
0442: if (panels[--index] instanceof StepHeader) {
0443: index--;
0444: }
0445: currentPanel = (WizardDescriptor.Panel) panels[index];
0446: updatePanels(makefileData.getMakefileType());
0447:
0448: ((JPanel) currentPanel.getComponent()).putClientProperty(
0449: "WizardPanel_contentSelectedIndex", // NOI18N
0450: new Integer(virtIndex));
0451: }
0452:
0453: /**
0454: * Convert the LinkedList of complexPanels to an array of
0455: * MakefileWizardPanel
0456: */
0457: private Object[] complexToArray() {
0458: Object[] p = new Object[complexPanels.size()];
0459:
0460: ListIterator iter = complexPanels.listIterator();
0461: for (int i = 0; i < complexPanels.size(); i++) {
0462: p[i] = iter.next();
0463: }
0464:
0465: return p;
0466: }
0467:
0468: /** Does a target with this key exist? */
0469: public boolean targetExists(int key) {
0470:
0471: for (int i = 0; i < complexPanels.size(); i++) {
0472: Object o = complexPanels.get(i);
0473: if (o instanceof StepHeader
0474: && ((StepHeader) o).getKey() == key) {
0475: return true;
0476: }
0477: }
0478:
0479: return false;
0480: }
0481:
0482: /** Create new panels for a target, based on the target type */
0483: public int addTarget(int type, String name, int key) {
0484: boolean needCompilerFlags = false;
0485: int count = 0;
0486:
0487: switch (type) {
0488: case TargetData.COMPLEX_EXECUTABLE:
0489: needCompilerFlags = true;
0490: count = 6;
0491: complexPanels.add(addIdx++, new TargetHeader(name, type,
0492: count - 1, key));
0493: complexPanels.add(addIdx++, buildOutputDescriptorPanel);
0494: complexPanels.add(addIdx++, makefileSourcesDescriptorPanel);
0495: complexPanels
0496: .add(addIdx++, makefileIncludesDescriptorPanel);
0497: complexPanels.add(addIdx++, standardLibsDescriptorPanel);
0498: complexPanels.add(addIdx++, userLibsDescriptorPanel);
0499: break;
0500:
0501: case TargetData.COMPLEX_ARCHIVE:
0502: needCompilerFlags = true;
0503: count = 4;
0504: complexPanels.add(addIdx++, new TargetHeader(name, type,
0505: count - 1, key));
0506: complexPanels.add(addIdx++, buildOutputDescriptorPanel);
0507: complexPanels.add(addIdx++, makefileSourcesDescriptorPanel);
0508: complexPanels
0509: .add(addIdx++, makefileIncludesDescriptorPanel);
0510: break;
0511:
0512: case TargetData.COMPLEX_SHAREDLIB:
0513: needCompilerFlags = true;
0514: count = 5;
0515: complexPanels.add(addIdx++, new TargetHeader(name, type,
0516: count - 1, key));
0517: complexPanels.add(addIdx++, buildOutputDescriptorPanel);
0518: complexPanels.add(addIdx++, makefileSourcesDescriptorPanel);
0519: complexPanels
0520: .add(addIdx++, makefileIncludesDescriptorPanel);
0521: complexPanels.add(addIdx++, userLibsDescriptorPanel);
0522: break;
0523:
0524: case TargetData.COMPLEX_MAKE_TARGET:
0525: complexPanels.add(addIdx++, new TargetHeader(name, type, 1,
0526: key));
0527: //complexPanels.add(addIdx++, makeTargetDescriptorPanel);
0528: complexPanels
0529: .add(addIdx++,
0530: new MakefileWizardDescriptorPanel(
0531: new MakeTargetPanel(this ),
0532: "recursive_make")); // NOI18N
0533: break;
0534:
0535: case TargetData.COMPLEX_CUSTOM_TARGET:
0536: complexPanels.add(addIdx++, new TargetHeader(name, type, 1,
0537: key));
0538: //complexPanels.add(addIdx++, customTargetPanel);
0539: complexPanels
0540: .add(addIdx++, new MakefileWizardDescriptorPanel(
0541: new CustomTargetPanel(this ), "custom_make")); // NOI18N
0542: break;
0543: }
0544:
0545: if (needCompilerFlags && !haveCompilerFlags) {
0546: complexPanels.add(addIdx, new StepHeader(NbBundle
0547: .getBundle(getClass()).getString("FMT_COMP_PREFS"),
0548: 3, -1)); // NOI18N
0549: complexPanels.add(addIdx + 1, basicFlagsDescriptorPanel);
0550: complexPanels.add(addIdx + 2,
0551: compilerOptionsDescriptorPanel);
0552: complexPanels.add(addIdx + 3, compilerPathDescriptorPanel);
0553: haveCompilerFlags = true;
0554: count += 4;
0555: }
0556:
0557: updatePanels(type);
0558:
0559: return count; // number of panels added
0560: }
0561:
0562: /** Delete the panels for the specified target */
0563: public void deleteTarget(int key) {
0564: deleteTarget(key, true);
0565: }
0566:
0567: /** Delete the panels for the specified target */
0568: public void deleteTarget(int key, boolean doUpdate) {
0569: boolean changed = false;
0570:
0571: for (int i = 0; i < complexPanels.size(); i++) {
0572: if (complexPanels.get(i) instanceof TargetHeader) {
0573: TargetHeader hdr = (TargetHeader) complexPanels.get(i);
0574: if (key == hdr.getKey()) {
0575: for (int j = 0; j <= hdr.getNum(); j++) {
0576: complexPanels.remove(i);
0577: changed = true;
0578: }
0579: addIdx -= hdr.getNum() + 1;
0580: break;
0581: }
0582: }
0583: }
0584:
0585: if (changed && doUpdate) {
0586: updatePanels(getMakefileData().getMakefileType());
0587: }
0588: }
0589:
0590: /** Change the panel name for the specified target */
0591: public void changeTarget(int key, String name, int type) {
0592: boolean changed = false;
0593:
0594: for (int i = 0; i < complexPanels.size(); i++) {
0595: if (complexPanels.get(i) instanceof TargetHeader) {
0596: TargetHeader hdr = (TargetHeader) complexPanels.get(i);
0597: if (key == hdr.getKey()) {
0598: if (type != hdr.getType()) {
0599: // Changing type of target - delete old target and create new
0600: deleteTarget(key, false);
0601: int saveIdx = addIdx;
0602: addIdx = i; // control where target is added
0603: int count = addTarget(type, name, key);
0604: addIdx = saveIdx + count;
0605: } else {
0606: // Just change the name of the target
0607: hdr.setName(name);
0608: hdr.setTitle(NbBundle.getMessage(getClass(),
0609: "FMT_TARGET_CREATE", name)); // NOI18N
0610: }
0611: changed = true;
0612: break;
0613: }
0614: }
0615: }
0616:
0617: if (changed) {
0618: updatePanels(getMakefileData().getMakefileType());
0619: }
0620: }
0621:
0622: /** Toplevel validation method. Gathers warnings from all panels */
0623: public ArrayList validateAllData() {
0624: ArrayList msgs = new ArrayList();
0625: int key = -1;
0626:
0627: for (int i = 0; i < panels.length; i++) {
0628: if (panels[i] instanceof WizardDescriptor.Panel
0629: && ((WizardDescriptor.Panel) panels[i])
0630: .getComponent() instanceof MakefileWizardPanel) {
0631: ((MakefileWizardPanel) ((WizardDescriptor.Panel) panels[i])
0632: .getComponent()).validateData(msgs, key);
0633: } else if (panels[i] instanceof StepHeader) {
0634: key = ((StepHeader) panels[i]).getKey();
0635: }
0636: }
0637:
0638: return msgs;
0639: }
0640:
0641: private transient Set listeners = new HashSet(1); // Set<ChangeListener>
0642:
0643: public final void addChangeListener(ChangeListener l) {
0644: synchronized (listeners) {
0645: listeners.add(l);
0646: }
0647: }
0648:
0649: public final void removeChangeListener(ChangeListener l) {
0650: synchronized (listeners) {
0651: listeners.remove(l);
0652: }
0653: }
0654:
0655: protected final void fireChangeEvent() {
0656: Iterator it;
0657:
0658: synchronized (listeners) {
0659: it = new HashSet(listeners).iterator();
0660: }
0661: ChangeEvent ev = new ChangeEvent(this );
0662: while (it.hasNext()) {
0663: ((ChangeListener) it.next()).stateChanged(ev);
0664: }
0665: }
0666:
0667: // Wizard methods
0668: public boolean onFinish() {
0669: MakefileGenerator gen = new MakefileGenerator(makefileData);
0670:
0671: /*
0672: * Remove any unused targets. A target is unused if its index > 0 and
0673: * the first target is a simple target.
0674: */
0675: ArrayList tlist = getMakefileData().getTargetList();
0676: if (tlist.size() > 1) {
0677: TargetData target = (TargetData) tlist.get(1);
0678:
0679: if (!target.isComplex()) {
0680: for (int i = tlist.size() - 1; i > 0; i--) {
0681: tlist.remove(i);
0682: }
0683: }
0684: }
0685: boolean status = gen.generate();
0686: return status;
0687: }
0688:
0689: /**
0690: * Returns whether the wizard has been completed and the code should
0691: * be generated.
0692: */
0693: public void executeWizard() {
0694: listener = new PropertyChangeListener() {
0695: public void propertyChange(PropertyChangeEvent event) {
0696: if (index == 0) {
0697: // FIXUP: don't know how to disable finish button on target chooser panel
0698: // FIXUP: this hack will just disable the finish button if on first panel...
0699: finishButton.setEnabled(false);
0700: }
0701: if (event.getPropertyName().equals(
0702: DialogDescriptor.PROP_VALUE)) {
0703: Object option = event.getNewValue();
0704: if (option == WizardDescriptor.FINISH_OPTION
0705: || option == WizardDescriptor.CANCEL_OPTION) {
0706: boolean done = false;
0707:
0708: if (option == WizardDescriptor.FINISH_OPTION) {
0709: if (hasNext()) {
0710: // Go to the Review panel
0711: index = panels.length - 2;
0712: nextPanel();
0713: nextButton.setEnabled(false);
0714: } else {
0715: ;//done = onFinish();
0716: }
0717: updateStateHack();
0718: } else {
0719: ; // nothing. The iterator will call 'instantiate' where the makefile is created
0720: }
0721: }
0722: }
0723: }
0724: };
0725:
0726: index = 0;
0727: currentPanel = (WizardDescriptor.Panel) panels[index];
0728: //wd = new MakefileWizardDescriptor(this);
0729: /*
0730: wd.putProperty("WizardPanel_autoWizardStyle", // NOI18N
0731: new Boolean(true));
0732: wd.putProperty("WizardPanel_contentDisplayed", // NOI18N
0733: new Boolean(true));
0734: wd.setTitleFormat(new MessageFormat("{0}")); // NOI18N
0735: wd.setTitle(title);
0736: */
0737: setupWizardButtons(wd);
0738:
0739: updatePanels(getMakefileData().getMakefileType()); //FIXUP
0740: ((JPanel) (currentPanel.getComponent())).putClientProperty(
0741: "WizardPanel_contentSelectedIndex", // NOI18N
0742: new Integer(0));
0743: wd.addPropertyChangeListener(listener);
0744: /*
0745: dialog = DialogDisplayer.getDefault().createDialog(wd);
0746: dialog.show();
0747: dialog.dispose();
0748: */
0749: }
0750:
0751: public void unexecuteWizard() {
0752: if (listener != null) {
0753: wd.removePropertyChangeListener(listener);
0754: listener = null;
0755: }
0756: }
0757:
0758: /**
0759: * We need to do several things with the buttons. First off, we want to
0760: * find the JButton for the Next and Finish buttons. We need the Next
0761: * button because we want to make another button default in some panels
0762: * but we need to return the 'default' status to the Next button at some
0763: * later point. We need the Finish button so we can change its label to
0764: * "Last" until we reach the review panel. We also want to reset the
0765: * closing buttons so only the Cancel button does a close.
0766: */
0767: private void setupWizardButtons(WizardDescriptor wd) {
0768: Object[] options = wd.getOptions(); // save original buttons
0769:
0770: wd.setOptions(new Object[] { WizardDescriptor.NEXT_OPTION,
0771: WizardDescriptor.FINISH_OPTION,
0772: WizardDescriptor.CANCEL_OPTION });
0773: Object[] objs = wd.getOptions();
0774: if (objs != null && objs.length == 3) {
0775: nextButton = (JButton) objs[0];
0776:
0777: finishButton = (JButton) objs[1];
0778: finishLabel = finishButton.getText();
0779: finishMnemonic = finishButton.getMnemonic();
0780: // finishButton.setText(NbBundle.getBundle(MakefileWizard.class).
0781: // getString("BTN_Last")); // NOI18N
0782: // finishButton.setMnemonic(NbBundle.getBundle(MakefileWizard.class).
0783: // getString("MNEM_Last").charAt(0)); // NOI18N
0784:
0785: cancelButton = (JButton) objs[2];
0786: }
0787: wd.setOptions(options); // restor original buttons
0788: setFinishClosingEnabled(false);
0789: }
0790:
0791: private void unsetupWizardButtons(WizardDescriptor wd) {
0792: setFinishClosingEnabled(true);
0793: // finishButton.setText(finishLabel);
0794: // finishButton.setMnemonic(finishMnemonic);
0795: }
0796:
0797: /**
0798: * Will enable the finish button to close the dialog or not.
0799: * The cancel button always closes the dialog.
0800: */
0801: public void setFinishClosingEnabled(boolean b) {
0802: if (b)
0803: wd.setClosingOptions(new Object[] { finishButton,
0804: cancelButton });
0805: else
0806: wd.setClosingOptions(new Object[] { cancelButton });
0807: }
0808:
0809: /**
0810: * We need to reenable often because each button press disables the
0811: * Finish button.
0812: */
0813: public void setFinishEnabled(boolean tf) {
0814: //wd.setFinishEnabled(tf); // FIXUP
0815: finishButton.setEnabled(tf); // FIXUP ???
0816: }
0817:
0818: final public static MakefileWizard getMakefileWizard() {
0819: return makefileWizard;
0820: }
0821:
0822: //
0823: // The following is the static portion of the class.
0824: //
0825:
0826: public static void showWizard() {
0827: makefileWizard = new MakefileWizard();
0828: makefileWizard.executeWizard();
0829: }
0830:
0831: /**
0832: * The StepHeader represents a group of panels which are collapsed to a
0833: * single line in the complexPanels steps list until one of those panels
0834: * is stepped into.
0835: */
0836: private class StepHeader {
0837:
0838: /** The line displayed in the Steps panel */
0839: private String title;
0840:
0841: /** The number of panels making up this step */
0842: private int num;
0843:
0844: /** A lookup key to map the StepHeader to a TargetData */
0845: private int key;
0846:
0847: /** The constructor */
0848: public StepHeader(String title, int num, int key) {
0849:
0850: this .title = title;
0851: this .num = num;
0852: this .key = key;
0853: }
0854:
0855: /** Getter for the title */
0856: public String getTitle() {
0857: return title;
0858: }
0859:
0860: /** Setter for the title */
0861: protected void setTitle(String title) {
0862: this .title = title;
0863: }
0864:
0865: /** Getter for the num */
0866: public int getNum() {
0867: return num;
0868: }
0869:
0870: /** Setter for the num */
0871: protected void setNum(int num) {
0872: this .num = num;
0873: }
0874:
0875: /** Getter for the key */
0876: public int getKey() {
0877: return key;
0878: }
0879:
0880: /** Setter for the key */
0881: protected void setKey(int key) {
0882: this .key = key;
0883: }
0884: }
0885:
0886: /**
0887: * The TargetHeader represents a target in the complexPanels list of steps.
0888: * Each target may have multiple panels but these panels are not shown
0889: * unless the wizard is ``stepped-into'' the TargetHeader.
0890: */
0891: private class TargetHeader extends MakefileWizard.StepHeader {
0892:
0893: /** The name is used to create the title */
0894: private String name;
0895:
0896: /** The type of the target this header is for */
0897: private int type;
0898:
0899: /** Constructor */
0900: public TargetHeader(String name, int type, int num, int key) {
0901:
0902: super (null, num, key);
0903: this .name = name;
0904: this .type = type;
0905: this .setTitle(NbBundle.getMessage(getClass(),
0906: "FMT_TARGET_CREATE", name)); // NOI18N
0907: }
0908:
0909: public String getName() {
0910: return name;
0911: }
0912:
0913: public void setName(String name) {
0914: this .name = name;
0915: }
0916:
0917: public int getType() {
0918: return type;
0919: }
0920:
0921: public void setType(int type) {
0922: this .type = type;
0923: }
0924: }
0925:
0926: public void initialize(TemplateWizard wiz) {
0927: wd = wiz;
0928: initPanels();
0929: executeWizard();
0930: }
0931:
0932: public void uninitialize(TemplateWizard wiz) {
0933: unexecuteWizard();
0934: unsetupWizardButtons(wiz);
0935: wd = null;
0936: }
0937:
0938: public Set instantiate(TemplateWizard wiz) throws IOException {
0939: DataFolder targetFolder = wiz.getTargetFolder();
0940: DataObject template = wiz.getTemplate();
0941: String makefileName;
0942: int pos = getMakefileData().getMakefileName().lastIndexOf(
0943: File.separatorChar);
0944: if (pos >= 0)
0945: makefileName = getMakefileData().getMakefileName()
0946: .substring(pos + 1);
0947: else
0948: makefileName = getMakefileData().getMakefileName();
0949:
0950: DataObject result;
0951: result = template
0952: .createFromTemplate(targetFolder, makefileName);
0953:
0954: if (result != null) {
0955: MakeExecSupport mes = (MakeExecSupport) result
0956: .getCookie(MakeExecSupport.class);
0957: if (mes != null) {
0958: // Add known targets to node
0959: // Add "all", "clean", and user defined targets...
0960: mes.addMakeTargets("all"); // NOI18N
0961: ArrayList tlist = getMakefileData().getTargetList();
0962: for (int i = 0; i < tlist.size(); i++) {
0963: TargetData t = (TargetData) tlist.get(i);
0964: switch (t.getTargetType()) {
0965: case TargetData.SIMPLE_EXECUTABLE:
0966: case TargetData.SIMPLE_ARCHIVE:
0967: case TargetData.SIMPLE_SHAREDLIB:
0968: case TargetData.COMPLEX_EXECUTABLE:
0969: case TargetData.COMPLEX_ARCHIVE:
0970: case TargetData.COMPLEX_SHAREDLIB:
0971: if (t.getOutputDirectory() != null
0972: && t.getOutputDirectory().length() > 0)
0973: mes.addMakeTargets(t.getOutputDirectory()
0974: + "/" + t.getName()); // NOI18N
0975: else
0976: mes.addMakeTargets(t.getName()); // NOI18N
0977: break;
0978: case TargetData.COMPLEX_MAKE_TARGET:
0979: case TargetData.COMPLEX_CUSTOM_TARGET:
0980: mes.addMakeTargets(t.getName());
0981: break;
0982: }
0983: }
0984: mes.addMakeTargets("clean"); // NOI18N
0985:
0986: // Set build (base) directory
0987: String makefileDir = getMakefileData()
0988: .getMakefileDirName();
0989: String baseDir = getMakefileData().getBaseDirectory();
0990: String buildDirectory;
0991: if (makefileDir.equals(baseDir))
0992: buildDirectory = ("."); // NOI18N
0993: else
0994: buildDirectory = IpeUtils.getRelativePath(
0995: makefileDir, baseDir);
0996: mes.setBuildDirectory(buildDirectory);
0997:
0998: String fullMakefilePath = result.getPrimaryFile()
0999: .getFileSystem().getDisplayName()
1000: + File.separator
1001: + result.getPrimaryFile().getPath();
1002: String fullBuildDirectoryPath = buildDirectory;
1003: int index = fullMakefilePath
1004: .lastIndexOf(File.separatorChar);
1005: if (index >= 0) {
1006: fullBuildDirectoryPath = IpeUtils.toAbsolutePath(
1007: fullMakefilePath.substring(0, index),
1008: fullBuildDirectoryPath);
1009: }
1010:
1011: // Send creation event
1012: ArrayList targets = new ArrayList();
1013: ArrayList executables = new ArrayList();
1014: for (int i = 0; i < tlist.size(); i++) {
1015: TargetData t = (TargetData) tlist.get(i);
1016: String outputDirectory = t.getOutputDirectory();
1017: if (outputDirectory == null
1018: || outputDirectory.length() == 0)
1019: outputDirectory = "."; // NOI18N
1020: switch (t.getTargetType()) {
1021: case TargetData.COMPLEX_EXECUTABLE:
1022: case TargetData.SIMPLE_EXECUTABLE:
1023: String fullTargetPath = null;
1024:
1025: if (t.getName().charAt(0) == File.separatorChar) {
1026: fullTargetPath = t.getName();
1027: } else if (outputDirectory.charAt(0) == File.separatorChar) {
1028: fullTargetPath = outputDirectory
1029: + File.separator + t.getName();
1030: } else {
1031: fullTargetPath = fullBuildDirectoryPath
1032: + File.separator + outputDirectory
1033: + File.separator + t.getName();
1034: }
1035: executables.add(fullTargetPath);
1036: // fall through...
1037: case TargetData.SIMPLE_ARCHIVE:
1038: case TargetData.SIMPLE_SHAREDLIB:
1039: case TargetData.COMPLEX_ARCHIVE:
1040: case TargetData.COMPLEX_SHAREDLIB:
1041: targets.add(t.getName());
1042: break;
1043: case TargetData.COMPLEX_MAKE_TARGET:
1044: case TargetData.COMPLEX_CUSTOM_TARGET:
1045: mes.addMakeTargets(t.getName());
1046: break;
1047: }
1048: }
1049: MakefileWizardEvent wizardEvent = new MakefileWizardEvent(
1050: this ,
1051: MakefileWizardEvent.MAKEFILE_NEW,
1052: fullMakefilePath,
1053: getMakefileData().getBaseDirectory(),
1054: MakeSettings.getDefault()
1055: .getDefaultMakeCommand(),
1056: (String[]) targets.toArray(new String[targets
1057: .size()]),
1058: (String[]) executables
1059: .toArray(new String[executables.size()]));
1060: fireMakefileWizardEvent(wizardEvent);
1061: }
1062: }
1063:
1064: boolean done = onFinish();
1065: if (done) {
1066: OpenCookie open = (OpenCookie) result
1067: .getCookie(OpenCookie.class);
1068: if (open != null) {
1069: open.open();
1070: }
1071: } else
1072: System.err.println("errors generating makefile..."); // FIXUP // NOI18N
1073: return Collections.singleton(result);
1074: }
1075:
1076: /*
1077: * Returns relative (to mounted filesystem) path to fileobject fo. Recursive.
1078: * Same funtionality as folder.getNameExt, which is now deprecated.
1079: */
1080: private String dirPath(FileObject fo, String path) {
1081: if (fo.getParent() != null && fo.getParent().getName() != null
1082: && fo.getParent().getName().length() > 0) {
1083: path = fo.getParent().getName() + File.separatorChar + path;
1084: return dirPath(fo.getParent(), path);
1085: }
1086: return path;
1087: }
1088:
1089: /** Set initial data in dialog */
1090: public void initDirPaths() {
1091: // Get dir folder and makefile name from targetChooser panel (default wizard panel)
1092: String fullFolderName = null;
1093: try {
1094: DataFolder targetFolder = getTemplateWizard()
1095: .getTargetFolder();
1096: FileObject fo = targetFolder.getPrimaryFile();
1097: fullFolderName = FileUtil.toFile(fo).getPath();
1098: } catch (IOException ioe) {
1099: ; // FIXUP
1100: }
1101: getMakefileData().setBaseDirectory(fullFolderName);
1102: getMakefileData().setMakefileDirName(fullFolderName);
1103: }
1104:
1105: private String uniqDefaultName(String dir, String makefileName) {
1106: String name = makefileName;
1107: File f = new File(dir + File.separator + name);
1108: int n = 1;
1109: while (f.exists()) {
1110: name = makefileName + "_" + n++; // NOI18N
1111: f = new File(dir + File.separator + name);
1112: }
1113: return name;
1114: }
1115:
1116: /** Update MakefileData if the data was changed */
1117: public void initMakefileName() {
1118: // Create and set makefile name based on name from targetChooser panel and basedirectory
1119: MakefileData md = getMakefileData();
1120: String makefileName = getTemplateWizard().getTargetName();
1121: String dir = IpeUtils.trimSlashes(md.getMakefileDirName());
1122: if (makefileName == null)
1123: makefileName = uniqDefaultName(dir, "Makefile"); // NOI18N
1124: String fullMakefileName = dir + File.separator + makefileName;
1125:
1126: String useMakefileName = null;
1127: if (dir.equals(md.getBaseDirectory()) || ".".equals(dir)
1128: || dir.length() == 0) // NOI18N
1129: useMakefileName = makefileName;
1130: else
1131: useMakefileName = fullMakefileName;
1132: md.setMakefileName(useMakefileName);
1133: }
1134:
1135: /** ---------------------------------------------------- */
1136:
1137: protected static void fireMakefileWizardEvent(MakefileWizardEvent e) {
1138: Vector listeners = getListenerList();
1139:
1140: for (int i = listeners.size() - 1; i >= 0; i--) {
1141: ((MakefileWizardListener) listeners.elementAt(i))
1142: .makefileCreated(e);
1143: }
1144: }
1145:
1146: private static Vector getListenerList() {
1147: if (listenerList == null) {
1148: listenerList = new Vector(0);
1149: }
1150: return listenerList;
1151: }
1152:
1153: public static void addMakefileWizardListener(
1154: MakefileWizardListener l) {
1155: getListenerList().add(l);
1156: }
1157:
1158: public static void removeMakefileWizardListener(
1159: MakefileWizardListener l) {
1160: getListenerList().remove(l);
1161: }
1162: }
|