001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.ui.templates;
011:
012: import java.net.MalformedURLException;
013: import java.net.URL;
014: import java.util.ArrayList;
015:
016: import org.eclipse.jface.wizard.IWizardContainer;
017: import org.eclipse.jface.wizard.WizardPage;
018: import org.eclipse.osgi.util.NLS;
019: import org.eclipse.pde.internal.ui.PDEUIMessages;
020:
021: /**
022: * This class adds some conventions to the class it is based on. For example, it
023: * expects to find the template content in the following location:
024: *
025: * <pre>
026: *
027: * [install location]/[templateDirectory]/[sectionId]
028: *
029: * </pre>
030: *
031: * where <code>templateDirectory</code> is expected to be 'templates_3.0' (to
032: * distinguish from template designed for earlier Eclipse versions), and
033: * <code>sectionId</code> is the unique identifier as reported by the template
034: * section.
035: * <p>
036: * It also assumes that all wizard pages associated with this template will be
037: * based on <code>OptionTemplateWizardPage</code>.
038: *
039: *
040: * @since 2.0
041: */
042:
043: public abstract class OptionTemplateSection extends
044: BaseOptionTemplateSection {
045: private ArrayList pages = new ArrayList();
046:
047: private static class TemplatePage {
048: WizardPage page;
049: ArrayList options;
050:
051: public TemplatePage() {
052: options = new ArrayList();
053: }
054: }
055:
056: /**
057: * The default constructor.
058: */
059: public OptionTemplateSection() {
060: }
061:
062: /**
063: * Returns the unique name of this section. This name will be used to
064: * construct name and description lookup keys, as well as the template file
065: * location in the contributing plug-in.
066: *
067: * @return the unique section Id
068: * @see #getLabel()
069: * @see #getDescription()
070: * @see #getTemplateLocation()
071: */
072: public abstract String getSectionId();
073:
074: /**
075: * Returns the directory where all the templates are located in the
076: * contributing plug-in.
077: *
078: * @return "templates_[schemaVersion]" for code since Eclipse 3.0, or
079: * "templates" for pre-3.0 code.
080: */
081: protected String getTemplateDirectory() {
082: String schemaVersion = model.getPluginBase().getSchemaVersion();
083: if (schemaVersion != null)
084: return "templates_" + schemaVersion; //$NON-NLS-1$
085: return "templates"; //$NON-NLS-1$
086: }
087:
088: /**
089: * Returns the install URL of the plug-in that contributes this template.
090: *
091: * @return the install URL of the contributing plug-in
092: */
093: protected abstract URL getInstallURL();
094:
095: /**
096: * Implements the abstract method by looking for templates using the
097: * following path:
098: * <p>
099: * [install location]/[templateDirectory]/[sectionId]
100: *
101: * @return the URL of the location where files to be emitted by this
102: * template are located.
103: */
104: public URL getTemplateLocation() {
105: URL url = getInstallURL();
106: try {
107: String location = getTemplateDirectory() + "/" //$NON-NLS-1$
108: + getSectionId() + "/"; //$NON-NLS-1$
109: return new URL(url, location);
110: } catch (MalformedURLException e) {
111: return null;
112: }
113: }
114:
115: /**
116: * Returns the wizard page at the specified index. Pages must be created
117: * prior to calling this method.
118: *
119: * @return the wizard page at the specified index or <samp>null </samp> if
120: * invalid index.
121: * @see #createPage(int)
122: */
123: public WizardPage getPage(int pageIndex) {
124: if (pageIndex < 0 || pageIndex >= pages.size())
125: return null;
126: TemplatePage tpage = (TemplatePage) pages.get(pageIndex);
127: return tpage.page;
128: }
129:
130: /**
131: * Creates the wizard page for the specified page index. This method cannot
132: * be called before setPageCount(int). The page will be created with all the
133: * options registered for that page index. Therefore, make all the calls to
134: * addOption() before calling this method.
135: *
136: * @param pageIndex
137: * a zero-based index of the page relative to this template. For
138: * example, if a template needs to have two pages, you have to
139: * call this method twice (once with index 0 and again with index
140: * 1).
141: * @see #setPageCount(int)
142: * @see BaseOptionTemplateSection#addOption
143: */
144: public WizardPage createPage(int pageIndex) {
145: if (pageIndex < 0 || pageIndex >= pages.size())
146: return null;
147: TemplatePage tpage = (TemplatePage) pages.get(pageIndex);
148: tpage.page = new OptionTemplateWizardPage(this , tpage.options,
149: null);
150: return tpage.page;
151: }
152:
153: /**
154: * Creates the wizard page for the specified page index. This method cannot
155: * be called before setPageCount(int). The page will be created with all the
156: * options registered for that page index. Therefore, make all the calls to
157: * addOption() before calling this method.
158: *
159: * @param pageIndex
160: * a zero-based index of the page relative to this template. For
161: * example, if a template need to have two pages, you have to
162: * call this method twice (once with index 0 and again with index
163: * 1).
164: * @param helpContextId
165: * the Id of the help context defined in the contributing plug-in
166: * that will be used to locate content of the info-pop displayed
167: * when F1 is pressed.
168: * @see #setPageCount(int)
169: * @see BaseOptionTemplateSection#addOption
170: */
171: public WizardPage createPage(int pageIndex, String helpContextId) {
172: if (pageIndex < 0 || pageIndex >= pages.size())
173: return null;
174: TemplatePage tpage = (TemplatePage) pages.get(pageIndex);
175: tpage.page = new OptionTemplateWizardPage(this , tpage.options,
176: helpContextId);
177: return tpage.page;
178: }
179:
180: /**
181: * Returns a number of pages that this template contributes to the wizard.
182: *
183: * @return the number of pages
184: * @see #setPageCount(int)
185: */
186: public int getPageCount() {
187: return pages.size();
188: }
189:
190: /**
191: * Sets the number of pages this template will manage. This method must be
192: * called prior to adding pages and options in order to initialize the
193: * template. Once the method has been called, you can call methods that
194: * accept page index in the range [0..count-1].
195: *
196: * @param count
197: * number of pages that this template will contribute to the
198: * template wizard
199: */
200: public void setPageCount(int count) {
201: pages.clear();
202: for (int i = 0; i < count; i++) {
203: pages.add(new TemplatePage());
204: }
205: }
206:
207: /**
208: * Returns options that belong to the page with the given index.
209: *
210: * @param pageIndex
211: * 0-based index of the template page
212: * @return @see #setPageCount(int)
213: */
214:
215: public TemplateOption[] getOptions(int pageIndex) {
216: if (pageIndex < 0 || pageIndex >= pages.size())
217: return new TemplateOption[0];
218: TemplatePage page = (TemplatePage) pages.get(pageIndex);
219: return (TemplateOption[]) page.options
220: .toArray(new TemplateOption[page.options.size()]);
221: }
222:
223: /**
224: * Returns options that are added to the provided wizard page.
225: *
226: * @param page
227: * wizard page that hosts required options
228: * @return array of options added to the provided wizard page
229: */
230:
231: public TemplateOption[] getOptions(WizardPage page) {
232: for (int i = 0; i < pages.size(); i++) {
233: TemplatePage tpage = (TemplatePage) pages.get(i);
234: if (tpage.page.equals(page))
235: return getOptions(i);
236: }
237: return new TemplateOption[0];
238: }
239:
240: /**
241: * Returns the zero-based index of a page that hosts the the given option.
242: *
243: * @param option
244: * template option for which a page index is being requested
245: * @return zero-based index of a page that hosts the option or -1 if none of
246: * the pages contain the option.
247: */
248: public int getPageIndex(TemplateOption option) {
249: for (int i = 0; i < pages.size(); i++) {
250: TemplatePage tpage = (TemplatePage) pages.get(i);
251: if (tpage.options.contains(option))
252: return i;
253: }
254: return -1;
255: }
256:
257: /**
258: * Returns the label of this template to be used in the UI. The label is
259: * obtained by creating a lookup key using the following rule:
260: * "template.[section-id].name". This key is used to locate the label in the
261: * plugin.properties file of the plug-in that contributed this template.
262: *
263: * @return the translated label of this template
264: */
265: public String getLabel() {
266: String key = "template." + getSectionId() + ".name"; //$NON-NLS-1$ //$NON-NLS-2$
267: return getPluginResourceString(key);
268: }
269:
270: /**
271: * Returns the description of this template to be used in the UI. The
272: * description is obtained by creating a lookup key using the following
273: * rule: "template.[section-id].desc". This key is used to locate the label
274: * in the plugin.properties file of the plug-in that contributed this
275: * template.
276: *
277: * @return the translated description of this template
278: */
279: public String getDescription() {
280: String key = "template." + getSectionId() + ".desc"; //$NON-NLS-1$ //$NON-NLS-2$
281: return getPluginResourceString(key);
282: }
283:
284: /**
285: * Locates the page that this option is presented in and flags that the
286: * option is required and is currently not set. The flagging is done by
287: * setting the page incomplete and setting the error message that uses
288: * option's message label.
289: *
290: * @param option
291: * the option that is required and currently not set
292: */
293: protected void flagMissingRequiredOption(TemplateOption option) {
294: WizardPage page = null;
295: for (int i = 0; i < pages.size(); i++) {
296: TemplatePage tpage = (TemplatePage) pages.get(i);
297: ArrayList list = tpage.options;
298: if (list.contains(option)) {
299: page = tpage.page;
300: break;
301: }
302: }
303: if (page != null) {
304: page.setPageComplete(false);
305: String message = NLS.bind(
306: PDEUIMessages.OptionTemplateSection_mustBeSet,
307: option.getMessageLabel());
308: page.setErrorMessage(message);
309: }
310: }
311:
312: /**
313: * Resets the current page state by clearing the error message and making
314: * the page complete, thereby allowing users to flip to the next page.
315: */
316: protected void resetPageState() {
317: if (pages.size() == 0)
318: return;
319: WizardPage firstPage = ((TemplatePage) pages.get(0)).page;
320: IWizardContainer container = firstPage.getWizard()
321: .getContainer();
322: WizardPage currentPage = (WizardPage) container
323: .getCurrentPage();
324: currentPage.setErrorMessage(null);
325: currentPage.setPageComplete(true);
326: }
327:
328: protected void registerOption(TemplateOption option, Object value,
329: int pageIndex) {
330: super .registerOption(option, value, pageIndex);
331: if (pageIndex >= 0 && pageIndex < pages.size()) {
332: TemplatePage tpage = (TemplatePage) pages.get(pageIndex);
333: tpage.options.add(option);
334: }
335: }
336:
337: /**
338: * Validate options given a template option
339: */
340: public void validateOptions(TemplateOption source) {
341: if (source.isRequired() && source.isEmpty()) {
342: flagMissingRequiredOption(source);
343: }
344: validateContainerPage(source);
345: }
346:
347: private void validateContainerPage(TemplateOption source) {
348: TemplateOption[] allPageOptions = getOptions(0);
349: for (int i = 0; i < allPageOptions.length; i++) {
350: TemplateOption nextOption = allPageOptions[i];
351: if (nextOption.isRequired() && nextOption.isEmpty()) {
352: flagMissingRequiredOption(nextOption);
353: return;
354: }
355: }
356: resetPageState();
357: }
358:
359: }
|