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.apisupport.project.ui.wizard.options;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.util.Arrays;
047: import java.util.HashMap;
048: import java.util.List;
049: import java.util.Locale;
050: import java.util.Map;
051: import java.util.Set;
052: import org.netbeans.modules.apisupport.project.CreatedModifiedFiles;
053: import org.netbeans.modules.apisupport.project.spi.NbModuleProvider;
054: import org.netbeans.modules.apisupport.project.ui.UIUtil;
055: import org.netbeans.modules.apisupport.project.ui.wizard.BasicWizardIterator;
056: import org.openide.util.Utilities;
057: import org.openide.WizardDescriptor;
058: import org.openide.filesystems.FileObject;
059: import org.openide.util.NbBundle;
060:
061: /**
062: * Wizard for generating OptionsPanel
063: *
064: * @author Radek Matous
065: */
066: final class NewOptionsIterator extends BasicWizardIterator {
067:
068: private NewOptionsIterator.DataModel data;
069:
070: private NewOptionsIterator() { /* Use factory method. */
071: }
072:
073: public static NewOptionsIterator createIterator() {
074: return new NewOptionsIterator();
075: }
076:
077: public Set instantiate() throws IOException {
078: CreatedModifiedFiles cmf = data.getCreatedModifiedFiles();
079: cmf.run();
080: return getCreatedFiles(cmf, data.getProject());
081: }
082:
083: protected BasicWizardIterator.Panel[] createPanels(
084: WizardDescriptor wiz) {
085: data = new NewOptionsIterator.DataModel(wiz);
086: return new BasicWizardIterator.Panel[] {
087: new OptionsPanel0(wiz, data),
088: new OptionsPanel(wiz, data) };
089: }
090:
091: public @Override
092: void uninitialize(WizardDescriptor wiz) {
093: super .uninitialize(wiz);
094: data = null;
095: }
096:
097: static final class DataModel extends
098: BasicWizardIterator.BasicDataModel {
099:
100: private static final int ERR_BLANK_DISPLAYNAME = 1;
101: private static final int ERR_BLANK_TOOLTIP = 2;
102: private static final int ERR_BLANK_TITLE = 4;
103: private static final int ERR_BLANK_CATEGORY_NAME = 5;
104: private static final int ERR_BLANK_ICONPATH = 6;
105: private static final int ERR_BLANK_PACKAGE_NAME = 7;
106: private static final int ERR_BLANK_CLASSNAME_PREFIX = 8;
107: private static final int ERR_INVALID_CLASSNAME_PREFIX = 9;
108:
109: private static final int WARNING_INCORRECT_ICON_SIZE = -1;
110:
111: private static final String[] CATEGORY_BUNDLE_KEYS = {
112: "OptionsCategory_Title", // NOI18N
113: "OptionsCategory_Name", // NOI18N
114: };
115:
116: private static final String[] ADVANCED_BUNDLE_KEYS = {
117: "AdvancedOption_DisplayName", // NOI18N
118: "AdvancedOption_Tooltip" // NOI18N
119: };
120:
121: private static final String[] TOKENS = {
122: "PACKAGE_NAME", // NOI18N
123: "AdvancedOption_CLASS_NAME", // NOI18N
124: "OptionsCategory_CLASS_NAME", // NOI18N
125: "Panel_CLASS_NAME", // NOI18N
126: "OptionsPanelController_CLASS_NAME", // NOI18N
127: "ICON_PATH", // NOI18N
128: ADVANCED_BUNDLE_KEYS[0], ADVANCED_BUNDLE_KEYS[1],
129: CATEGORY_BUNDLE_KEYS[0], CATEGORY_BUNDLE_KEYS[1] };
130:
131: private static final String FORM_TEMPLATE_SUFFIXES[] = { "Panel" }; // NOI18N
132: private static final String[] JAVA_TEMPLATE_SUFFIXES = {
133: "AdvancedOption",//NOI18N
134: "OptionsCategory",//NOI18N
135: "Panel",//NOI18N
136: "OptionsPanelController"//NOI18N
137: };
138: private static final String JAVA_TEMPLATE_PREFIX = "template_myplugin"; // NOI18N
139: private static final String FORM_TEMPLATE_PREFIX = "template_myplugin_form"; // NOI18N
140:
141: private CreatedModifiedFiles files;
142: private String codeNameBase;
143: private boolean advanced;
144:
145: //Advanced panel
146: private String displayName;
147: private String tooltip;
148:
149: //OptionsCategory
150: private String title;
151: private String categoryName;
152: private String iconPath;
153:
154: private String classNamePrefix;
155:
156: DataModel(WizardDescriptor wiz) {
157: super (wiz);
158: }
159:
160: int setDataForAdvanced(final String displayName,
161: final String tooltip) {
162: this .advanced = true;
163: this .displayName = displayName;
164: this .tooltip = tooltip;
165: return checkFirstPanel();
166: }
167:
168: int setDataForOptionCategory(final String title,
169: final String categoryName, final String iconPath) {
170: this .advanced = false;
171: this .title = title;
172: this .categoryName = categoryName;
173: this .iconPath = iconPath;
174: return checkFirstPanel();
175: }
176:
177: public @Override
178: String getPackageName() {
179: String retValue;
180: retValue = super .getPackageName();
181: if (retValue == null) {
182: retValue = getCodeNameBase();
183: super .setPackageName(retValue);
184: }
185: return retValue;
186: }
187:
188: public int setPackageAndPrefix(String packageName,
189: String classNamePrefix) {
190: setPackageName(packageName);
191: this .classNamePrefix = classNamePrefix;
192: int errCode = checkFinalPanel();
193: if (isSuccessCode(errCode)) {
194: generateCreatedModifiedFiles();
195: }
196: return errCode;
197: }
198:
199: private Map<String, String> getTokenMap() {
200: Map<String, String> retval = new HashMap<String, String>();
201: for (int i = 0; i < TOKENS.length; i++) {
202: if (isAdvanced() && "ICON_PATH".equals(TOKENS[i])) { // NOI18N
203: continue;
204: }
205: retval.put(TOKENS[i], getReplacement(TOKENS[i]));
206: }
207: return retval;
208: }
209:
210: private String getReplacement(String key) {
211: if ("PACKAGE_NAME".equals(key)) {// NOI18N
212: return getPackageName();
213: } else if ("AdvancedOption_CLASS_NAME".equals(key)) {// NOI18N
214: return getAdvancedOptionClassName();
215: } else if ("OptionsCategory_CLASS_NAME".equals(key)) {// NOI18N
216: return getOptionsCategoryClassName();
217: } else if ("Panel_CLASS_NAME".equals(key)) {// NOI18N
218: return getPanelClassName();
219: } else if ("OptionsPanelController_CLASS_NAME".equals(key)) {// NOI18N
220: return getOptionsPanelControllerClassName();
221: } else if ("ICON_PATH".equals(key)) {// NOI18N
222: return addCreateIconOperation(new CreatedModifiedFiles(
223: getProject()), getIconPath());
224: } else {
225: return key + "_" + getClassNamePrefix();
226: }
227:
228: }
229:
230: private String getBundleValue(String key) {
231: if (key.startsWith("OptionsCategory_Title")) {// NOI18N
232: return getTitle();
233: } else if (key.startsWith("OptionsCategory_Name")) {// NOI18N
234: return getCategoryName();
235: } else if (key.startsWith("AdvancedOption_DisplayName")) {// NOI18N
236: return getDisplayName();
237: } else if (key.startsWith("AdvancedOption_Tooltip")) {// NOI18N
238: return getTooltip();
239: } else {
240: throw new AssertionError(key);
241: }
242: }
243:
244: /**
245: * getErrorCode() and getErrorMessage are tigthly coupled. Moreover the
246: * order should depend on ordering of textfields in panels.
247: */
248: String getErrorMessage(int errCode) {
249: assert errCode > 0;
250: String field = null;
251: switch (errCode) {
252: case ERR_BLANK_DISPLAYNAME:
253: field = "FIELD_DisplayName";//NOI18N
254: break;
255: case ERR_BLANK_TOOLTIP:
256: field = "FIELD_Tooltip";//NOI18N
257: break;
258: case ERR_BLANK_TITLE:
259: field = "FIELD_Title";//NOI18N
260: break;
261: case ERR_BLANK_CATEGORY_NAME:
262: field = "FIELD_CategoryName";//NOI18N
263: break;
264: case ERR_BLANK_ICONPATH:
265: field = "FIELD_IconPath";//NOI18N
266: break;
267: case ERR_BLANK_PACKAGE_NAME:
268: field = "FIELD_PackageName";//NOI18N
269: break;
270: case ERR_BLANK_CLASSNAME_PREFIX:
271: field = "FIELD_ClassNamePrefix";//NOI18N
272: break;
273: case ERR_INVALID_CLASSNAME_PREFIX:
274: return NbBundle.getMessage(NewOptionsIterator.class,
275: "ERR_Name_Prefix_Invalid");//NOI18N
276: default:
277: assert false : "Unknown errCode: " + errCode;
278: }
279: field = NbBundle
280: .getMessage(NewOptionsIterator.class, field);
281: return (errCode > 0) ? NbBundle
282: .getMessage(NewOptionsIterator.class,
283: "ERR_FieldInvalid", field) : "";//NOI18N
284: }
285:
286: /**
287: * getErrorCode() and getWarningMessage are tigthly coupled. Moreover the
288: * order should depend on ordering of textfields in panels.
289: */
290: String getWarningMessage(int warningCode) {
291: assert warningCode < 0;
292: String result;
293: switch (warningCode) {
294: case WARNING_INCORRECT_ICON_SIZE:
295: File icon = new File(getIconPath());
296: assert icon.exists();
297: result = UIUtil.getIconDimensionWarning(icon, 32, 32);
298: break;
299: default:
300: assert false : "Unknown warningCode: " + warningCode;
301: result = "";
302: }
303: return result;
304: }
305:
306: static boolean isSuccessCode(int code) {
307: return code == 0;
308: }
309:
310: static boolean isErrorCode(int code) {
311: return code > 0;
312: }
313:
314: static boolean isWarningCode(int code) {
315: return code < 0;
316: }
317:
318: private int checkFirstPanel() {
319: if (advanced) {
320: if (getDisplayName().length() == 0) {
321: return ERR_BLANK_DISPLAYNAME;
322: } else if (getTooltip().length() == 0) {
323: return ERR_BLANK_TOOLTIP;
324: }
325: } else {
326: if (getTitle().length() == 0) {
327: return ERR_BLANK_TITLE;
328: } else if (getCategoryName().length() == 0) {
329: return ERR_BLANK_CATEGORY_NAME;
330: } else if (getIconPath().length() == 0) {
331: return ERR_BLANK_ICONPATH;
332: } else if (getTitle().length() == 0) {
333: return ERR_BLANK_TITLE;
334: } else {
335: File icon = new File(getIconPath());
336: if (!icon.exists()) {
337: return ERR_BLANK_ICONPATH;
338: }
339: }
340: //warnings should go at latest
341: File icon = new File(getIconPath());
342: assert icon.exists();
343: if (!UIUtil.isValidIcon(icon, 32, 32)) {
344: return WARNING_INCORRECT_ICON_SIZE;
345: }
346: }
347: return 0;
348: }
349:
350: private int checkFinalPanel() {
351: if (getPackageName().length() == 0) {
352: return ERR_BLANK_PACKAGE_NAME;
353: } else if (getClassNamePrefix().length() == 0) {
354: return ERR_BLANK_CLASSNAME_PREFIX;
355: } else if (!Utilities
356: .isJavaIdentifier(getClassNamePrefix())) {
357: return ERR_INVALID_CLASSNAME_PREFIX;
358: }
359:
360: return 0;
361: }
362:
363: public CreatedModifiedFiles getCreatedModifiedFiles() {
364: if (files == null) {
365: files = generateCreatedModifiedFiles();
366: }
367: return files;
368: }
369:
370: private CreatedModifiedFiles generateCreatedModifiedFiles() {
371: assert isSuccessCode(checkFirstPanel())
372: || isWarningCode(checkFirstPanel());
373: assert isSuccessCode(checkFinalPanel());
374: files = new CreatedModifiedFiles(getProject());
375: generateFiles();
376: generateBundleKeys();
377: generateDependencies();
378: generateLayerEntry();
379: if (!isAdvanced()) {
380: addCreateIconOperation(files, getIconPath());
381: }
382: return files;
383: }
384:
385: private void generateFiles() {
386: List allForms = Arrays.asList(FORM_TEMPLATE_SUFFIXES);
387: for (int i = 0; i < JAVA_TEMPLATE_SUFFIXES.length; i++) {
388: boolean ommit = (isAdvanced()) ? "OptionsCategory"
389: .equals(JAVA_TEMPLATE_SUFFIXES[i]) : // NOI18N
390: "AdvancedOption"
391: .equals(JAVA_TEMPLATE_SUFFIXES[i]);// NOI18N
392: if (ommit) {
393: continue;
394: }
395: files
396: .add(createJavaFileCopyOperation(JAVA_TEMPLATE_SUFFIXES[i]));
397: if (allForms.contains(JAVA_TEMPLATE_SUFFIXES[i])) {
398: files
399: .add(createFormFileCopyOperation(JAVA_TEMPLATE_SUFFIXES[i]));
400: }
401: }
402: }
403:
404: private void generateBundleKeys() {
405: String[] bundleKeys = (isAdvanced()) ? ADVANCED_BUNDLE_KEYS
406: : CATEGORY_BUNDLE_KEYS;
407: for (int i = 0; i < bundleKeys.length; i++) {
408: String key = getReplacement(bundleKeys[i]);
409: String value = getBundleValue(key);
410: files.add(files.bundleKey(getDefaultPackagePath(
411: "Bundle.properties", true), key, value));// NOI18N
412: }
413: }
414:
415: private void generateDependencies() {
416: files.add(files.addModuleDependency("org.openide.util")); // NOI18N
417: files.add(files.addModuleDependency(
418: "org.netbeans.modules.options.api", "0-1", null,
419: true));// NOI18N
420: files.add(files.addModuleDependency("org.openide.awt")); // NOI18N
421: }
422:
423: private void generateLayerEntry() {
424: String resourcePathPrefix = (isAdvanced()) ? "OptionsDialog/Advanced/"
425: : "OptionsDialog/";// NOI18N
426: String instanceName = isAdvanced() ? getAdvancedOptionClassName()
427: : getOptionsCategoryClassName();
428: String instanceFullPath = resourcePathPrefix
429: + getPackageName().replace('.', '-') + "-"
430: + instanceName + ".instance";//NOI18N
431: files.add(files.createLayerEntry(instanceFullPath, null,
432: null, null, null));
433: }
434:
435: private CreatedModifiedFiles.Operation createJavaFileCopyOperation(
436: final String templateSuffix) {
437: FileObject template = CreatedModifiedFiles
438: .getTemplate(JAVA_TEMPLATE_PREFIX + templateSuffix
439: + ".java");
440: assert template != null : JAVA_TEMPLATE_PREFIX
441: + templateSuffix;
442: return files.createFileWithSubstitutions(
443: getFilePath(templateSuffix), template,
444: getTokenMap());
445: }
446:
447: private String getFilePath(final String templateSuffix) {
448: String fileName = getClassNamePrefix() + templateSuffix
449: + ".java"; // NOI18N
450: return getDefaultPackagePath(fileName, false);//NOI18N
451: }
452:
453: private CreatedModifiedFiles.Operation createFormFileCopyOperation(
454: final String templateSuffix) {
455: FileObject template = CreatedModifiedFiles
456: .getTemplate(FORM_TEMPLATE_PREFIX + templateSuffix
457: + ".form");
458: assert template != null : JAVA_TEMPLATE_PREFIX
459: + templateSuffix;
460: String fileName = getClassNamePrefix() + templateSuffix
461: + ".form";// NOI18N
462: String filePath = getDefaultPackagePath(fileName, false);
463: return files.createFile(filePath, template);
464: }
465:
466: private String getCodeNameBase() {
467: if (codeNameBase == null) {
468: NbModuleProvider mod = getProject().getLookup().lookup(
469: NbModuleProvider.class);
470: codeNameBase = mod.getCodeNameBase();
471: }
472: return codeNameBase;
473: }
474:
475: private String getDisplayName() {
476: assert !isAdvanced() || displayName != null;
477: return displayName;
478: }
479:
480: private String getTooltip() {
481: assert !isAdvanced() || tooltip != null;
482: return tooltip;
483: }
484:
485: private String getTitle() {
486: assert isAdvanced() || title != null;
487: return title;
488: }
489:
490: private String getCategoryName() {
491: assert isAdvanced() || categoryName != null;
492: return categoryName;
493: }
494:
495: private String getIconPath() {
496: assert isAdvanced() || iconPath != null;
497: return iconPath;
498: }
499:
500: String getClassNamePrefix() {
501: if (classNamePrefix == null) {
502: classNamePrefix = getCodeNameBase();
503: classNamePrefix = classNamePrefix
504: .substring(classNamePrefix.lastIndexOf(".") + 1);// NOI18N
505: classNamePrefix = classNamePrefix.substring(0, 1)
506: .toUpperCase(Locale.ENGLISH)
507: + classNamePrefix.substring(1); // NOI18N
508: }
509: return classNamePrefix;
510: }
511:
512: private boolean isAdvanced() {
513: return advanced;
514: }
515:
516: private String getAdvancedOptionClassName() {
517: return getClassName(JAVA_TEMPLATE_SUFFIXES[0]);
518: }
519:
520: private String getOptionsCategoryClassName() {
521: return getClassName(JAVA_TEMPLATE_SUFFIXES[1]);
522: }
523:
524: private String getPanelClassName() {
525: return getClassName(JAVA_TEMPLATE_SUFFIXES[2]);
526: }
527:
528: private String getOptionsPanelControllerClassName() {
529: return getClassName(JAVA_TEMPLATE_SUFFIXES[3]);
530: }
531:
532: private String getClassName(String suffix) {
533: return getClassNamePrefix() + suffix;
534: }
535:
536: }
537: }
|