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-2007 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.netbeans.modules.cnd.makewizard;
043:
044: import java.awt.BorderLayout;
045: import java.awt.GridBagConstraints;
046: import java.awt.GridBagLayout;
047: import java.awt.Insets;
048: import java.util.ArrayList;
049: import java.util.StringTokenizer;
050: import javax.swing.JEditorPane;
051: import javax.swing.JLabel;
052: import javax.swing.JPanel;
053: import javax.swing.JScrollPane;
054: import javax.swing.JTextField;
055: import javax.swing.event.DocumentEvent;
056: import javax.swing.event.DocumentListener;
057: import javax.swing.text.AbstractDocument;
058: import javax.swing.text.BadLocationException;
059: import javax.swing.text.DefaultStyledDocument;
060: import javax.swing.text.Element;
061: import javax.swing.text.StyledDocument;
062: import org.netbeans.modules.cnd.MIMENames;
063: import org.netbeans.modules.cnd.api.utils.IpeUtils;
064: import org.openide.text.NbDocument;
065:
066: /**
067: * Create a panel used for gathering the binary name and output directory for
068: * the simple application cases (all Makefile types other than complex).
069: */
070:
071: public class CustomTargetPanel extends MakefileWizardPanel {
072:
073: /** Serial version number */
074: static final long serialVersionUID = -5820333613938630399L;
075:
076: /** Dependencies for this target */
077: private JTextField dependsOn;
078:
079: /**
080: * An editor showing both the target name, dependencies, and actions.
081: * The target name and dependencies are in a guarded block. However, the
082: * user may add actions/commands after that.
083: */
084: private JEditorPane actionText;
085:
086: /** The Document behind actionText */
087: private StyledDocument actionDoc;
088:
089: /** String version of dependsOn */
090: private String depends;
091:
092: /** Tells if we have created the gui or not */
093: private boolean initialized;
094:
095: /** Suppress inserting dependencies into actionText if set */
096: private boolean inAddNotify = false;
097:
098: /** Store the target key */
099: private int key;
100:
101: /**
102: * Constructor for the custom target panel.
103: */
104: CustomTargetPanel(MakefileWizard wd) {
105: super (wd);
106: String subtitle = getString("LBL_CustomTargetPanel"); // NOI18N
107: setSubTitle(subtitle);
108: this .getAccessibleContext().setAccessibleDescription(subtitle);
109: initialized = false;
110: }
111:
112: /** Defer widget creation until the panel needs to be displayed */
113: private void create() {
114:
115: setLayout(new BorderLayout());
116:
117: JPanel panel = new JPanel(new GridBagLayout());
118: GridBagConstraints grid = new GridBagConstraints();
119:
120: // Set the GridBagLayout constraints for the first label
121: JLabel label = new JLabel(getString("LBL_DependsOn")); // NOI18N
122: label.setDisplayedMnemonic(getString("MNEM_DependsOn")
123: .charAt(0)); // NOI18N
124: grid.anchor = GridBagConstraints.WEST;
125: grid.gridx = 0;
126: grid.gridy = 0;
127: panel.add(label, grid);
128:
129: // Now do the textfield
130: dependsOn = new JTextField();
131: label.setLabelFor(dependsOn);
132: grid.gridx = 1;
133: grid.gridwidth = GridBagConstraints.REMAINDER;
134: grid.weightx = 1.0;
135: grid.fill = GridBagConstraints.HORIZONTAL;
136: grid.anchor = GridBagConstraints.NORTHWEST;
137: grid.insets = new Insets(0, 5, 0, 0);
138: panel.add(dependsOn, grid);
139:
140: // Create the actionText's label
141: label = new JLabel(getString("LBL_ActionDisplay")); // NOI18N
142: label.setDisplayedMnemonic(getString("MNEM_ActionDisplay")
143: .charAt(0)); // NOI18N
144: grid.gridx = 0;
145: grid.gridy = 1;
146: grid.gridwidth = 1;
147: grid.weightx = 0.0;
148: grid.fill = GridBagConstraints.NONE;
149: grid.insets = new Insets(10, 0, 0, 0);
150: panel.add(label, grid);
151: add(panel, BorderLayout.NORTH);
152:
153: // Finally, create the actionText
154: actionText = new JEditorPane(MIMENames.MAKEFILE_MIME_TYPE, ""); // NOI18N
155: label.setLabelFor(actionText);
156: // FIXUP:
157: if (!(actionText.getDocument() instanceof StyledDocument)) {
158: actionText.setDocument(new DefaultStyledDocument());
159: }
160: actionDoc = (StyledDocument) actionText.getDocument();
161: JScrollPane s = new JScrollPane(actionText);
162:
163: s
164: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
165: s
166: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
167: s.setMinimumSize(s.getPreferredSize());
168: add(s, BorderLayout.CENTER);
169:
170: dependsOn.getDocument().addDocumentListener(
171: new DocumentListener() {
172: public void changedUpdate(DocumentEvent e) {
173: }
174:
175: public void insertUpdate(DocumentEvent e) {
176: insertActionDisplay(e);
177: }
178:
179: public void removeUpdate(DocumentEvent e) {
180: removeActionDisplay(e);
181: }
182: });
183: }
184:
185: /** Insert the new dependency characters into actionText */
186: private void insertActionDisplay(DocumentEvent e) {
187:
188: if (!inAddNotify) {
189: TargetData target = (TargetData) getMakefileData()
190: .getCurrentTarget();
191: int off = e.getOffset();
192: String nueDependsOn = dependsOn.getText();
193: String nuePart = nueDependsOn.substring(off, off
194: + e.getLength());
195:
196: off += target.getName().length() + 2;
197: Element elem = actionDoc.getParagraphElement(0);
198: NbDocument.unmarkGuarded(actionDoc, elem.getStartOffset(),
199: elem.getEndOffset() - elem.getStartOffset() + 1);
200: try {
201: actionDoc.insertString(off, nuePart, null);
202: } catch (BadLocationException ex) {
203: if (IpeUtils.IfdefDiagnostics) {
204: System.out.println("BadLocationException: "
205: + // NOI18N
206: ex.getMessage() + "\n\toffset = "
207: + ex.offsetRequested()); // NOI18N
208: ex.printStackTrace();
209: }
210: }
211: depends = nueDependsOn;
212: NbDocument.markGuarded(actionDoc, elem.getStartOffset(),
213: target.getName().length() + depends.length() + 3);
214: }
215: }
216:
217: /** Remove characters from actionText */
218: private void removeActionDisplay(DocumentEvent e) {
219:
220: if (!inAddNotify) {
221: TargetData target = (TargetData) getMakefileData()
222: .getCurrentTarget();
223: int off = target.getName().length() + 2 + e.getOffset();
224:
225: Element elem = actionDoc.getParagraphElement(0);
226: NbDocument.unmarkGuarded(actionDoc, elem.getStartOffset(),
227: elem.getEndOffset() - elem.getStartOffset() + 1);
228: try {
229: actionDoc.remove(off, e.getLength());
230: } catch (BadLocationException ex) {
231: if (IpeUtils.IfdefDiagnostics) {
232: System.out.println("BadLocationException[6]: "
233: + // NOI18N
234: ex.getMessage() + "\n\toffset = "
235: + ex.offsetRequested()); // NOI18N
236: ex.printStackTrace();
237: }
238: }
239: depends = dependsOn.getText();
240: NbDocument.markGuarded(actionDoc, elem.getStartOffset(),
241: target.getName().length() + depends.length() + 3);
242: }
243: }
244:
245: /** Validate the binary name and output directory */
246: public void validateData(ArrayList msgs, int key) {
247: AbstractDocument doc = (AbstractDocument) actionText
248: .getDocument();
249: String action;
250: int extraLines = 0;
251: int invalidLines = 0;
252:
253: try {
254: action = doc.getText(0, doc.getLength());
255: } catch (BadLocationException e) {
256: // Shouldn't happen but this will suppress NPE if it does
257: action = "";// NOI18N
258: if (IpeUtils.IfdefDiagnostics) {
259: System.out
260: .println("BadLocationException validating target"); // NOI18N
261: e.printStackTrace();
262: }
263: }
264:
265: StringTokenizer st = new StringTokenizer(action, "\n"); // NOI18N
266: st.nextToken(); // skip target line
267: while (st.hasMoreTokens()) {
268: String line = st.nextToken();
269: if (line.length() == 0 || extraLines > 0) {
270: extraLines++;
271: } else if (!line.startsWith("\t")) { // NOI18N
272: invalidLines++;
273: }
274: }
275:
276: if (extraLines > 0) {
277: warn(msgs, WARN_EXTRA_LINES_IN_TARGET, new Integer(
278: extraLines).toString());
279: }
280: if (invalidLines > 0) {
281: warn(msgs, WARN_INVALID_LINES_IN_TARGET, new Integer(
282: invalidLines).toString());
283: }
284: }
285:
286: /** Create and initialize the target */
287: public void addNotify() {
288: TargetData target = (TargetData) getMakefileData()
289: .getCurrentTarget();
290: int i;
291:
292: if (!initialized) {
293: create();
294: initialized = true;
295: }
296:
297: key = target.getKey();
298: inAddNotify = true;
299: depends = target.getDependsOn();
300: if (depends == null) {
301: depends = "";// NOI18N
302: }
303: dependsOn.setText(depends); // set the textfield
304: Element elem = actionDoc.getParagraphElement(0);
305: NbDocument.unmarkGuarded(actionDoc, elem.getStartOffset(), elem
306: .getEndOffset()
307: - elem.getStartOffset() + 1);
308: try {
309: actionDoc.remove(0, actionDoc.getLength());
310: } catch (BadLocationException e) {
311: if (IpeUtils.IfdefDiagnostics) {
312: System.out.println("BadLocationException[1]: "
313: + // NOI18N
314: e.getMessage() + "\n\toffset = "
315: + e.offsetRequested()); // NOI18N
316: e.printStackTrace();
317: }
318: }
319:
320: // Compute the strings for the action are and display them
321: StringBuffer depline = new StringBuffer(target.getName());
322: if (target.getName().equals("clean")) { // NOI18N
323: // This allows the user to add duplicate clean targets
324: depline.append(":: "); // NOI18N
325: } else {
326: depline.append(": "); // NOI18N
327: }
328: if (depends.length() > 0) {
329: depline.append(depends);
330: }
331: depline.append("\n"); // NOI18N
332: try {
333: actionDoc.insertString(0, depline.toString(), null);
334: } catch (BadLocationException e) {
335: if (IpeUtils.IfdefDiagnostics) {
336: System.out.println("BadLocationException[2]: "
337: + // NOI18N
338: e.getMessage() + "\n\toffset = "
339: + e.offsetRequested()); // NOI18N
340: e.printStackTrace();
341: }
342: }
343: NbDocument.markGuarded(actionDoc, 0, depline.length());
344:
345: ArrayList list = target.getActions();
346: StringBuffer action = new StringBuffer();
347: for (i = 0; i < list.size(); i++) {
348: String line = list.get(i).toString();
349: // XXX - Will the "\t" be needed when we get an indentation engine?
350: action.append("\t").append(line).append("\n"); // NOI18N
351: }
352: if (action.length() == 0) {
353: // initial tab (XXX - until indentation engine?)
354: action.append("\t"); // NOI18N
355: }
356:
357: try {
358: actionDoc.insertString(depline.length(), action.toString(),
359: null);
360: } catch (BadLocationException e) {
361: if (IpeUtils.IfdefDiagnostics) {
362: System.out.println("BadLocationException[3]: "
363: + // NOI18N
364: e.getMessage() + "\n\toffset = "
365: + e.offsetRequested()); // NOI18N
366: e.printStackTrace();
367: }
368: }
369:
370: super .addNotify();
371: inAddNotify = false;
372: }
373:
374: /** Get the data from the panel and update the target */
375: public void removeNotify() {
376: super .removeNotify();
377:
378: TargetData target = getMakefileData().getTarget(key);
379: String action = null;
380:
381: target.setDependsOn(depends);
382: try {
383: action = actionDoc.getText(0, actionDoc.getLength());
384: } catch (BadLocationException e) {
385: if (IpeUtils.IfdefDiagnostics) {
386: System.out.println("BadLocationException[4]: "
387: + // NOI18N
388: e.getMessage() + "\n\toffset = "
389: + e.offsetRequested()); // NOI18N
390: e.printStackTrace();
391: }
392: }
393:
394: if (action != null) {
395: ArrayList list = new ArrayList();
396: StringTokenizer st = new StringTokenizer(action, "\n"); // NOI18N
397:
398: st.nextToken(); // skip target line
399: while (st.hasMoreTokens()) {
400: String tmp = st.nextToken().trim();
401: if (tmp.length() > 0) {
402: list.add(tmp);
403: }
404: }
405: target.setActions(list);
406: }
407: }
408: }
|