001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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.internal.ui.editor.feature;
011:
012: import java.net.MalformedURLException;
013: import java.net.URL;
014:
015: import org.eclipse.core.runtime.CoreException;
016: import org.eclipse.jface.dialogs.MessageDialog;
017: import org.eclipse.jface.window.Window;
018: import org.eclipse.jface.wizard.WizardDialog;
019: import org.eclipse.pde.core.IModelChangedEvent;
020: import org.eclipse.pde.core.plugin.IPlugin;
021: import org.eclipse.pde.core.plugin.IPluginModel;
022: import org.eclipse.pde.core.plugin.PluginRegistry;
023: import org.eclipse.pde.internal.core.feature.FeatureImport;
024: import org.eclipse.pde.internal.core.ifeature.IFeature;
025: import org.eclipse.pde.internal.core.ifeature.IFeatureImport;
026: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
027: import org.eclipse.pde.internal.core.ifeature.IFeatureURL;
028: import org.eclipse.pde.internal.core.ifeature.IFeatureURLElement;
029: import org.eclipse.pde.internal.core.util.VersionUtil;
030: import org.eclipse.pde.internal.ui.PDEPlugin;
031: import org.eclipse.pde.internal.ui.PDEUIMessages;
032: import org.eclipse.pde.internal.ui.editor.FormEntryAdapter;
033: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
034: import org.eclipse.pde.internal.ui.editor.PDESection;
035: import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
036: import org.eclipse.pde.internal.ui.parts.FormEntry;
037: import org.eclipse.pde.internal.ui.util.SWTUtil;
038: import org.eclipse.pde.internal.ui.wizards.PluginSelectionDialog;
039: import org.eclipse.pde.internal.ui.wizards.plugin.NewPluginProjectWizard;
040: import org.eclipse.swt.dnd.Clipboard;
041: import org.eclipse.swt.dnd.RTFTransfer;
042: import org.eclipse.swt.dnd.TextTransfer;
043: import org.eclipse.swt.dnd.Transfer;
044: import org.eclipse.swt.dnd.TransferData;
045: import org.eclipse.swt.layout.GridData;
046: import org.eclipse.swt.widgets.Composite;
047: import org.eclipse.ui.forms.events.HyperlinkEvent;
048: import org.eclipse.ui.forms.widgets.FormToolkit;
049: import org.eclipse.ui.forms.widgets.Section;
050: import org.eclipse.ui.forms.widgets.TableWrapData;
051:
052: public class FeatureSpecSection extends PDESection {
053: private FormEntry fIdText;
054:
055: private FormEntry fTitleText;
056:
057: private FormEntry fVersionText;
058:
059: private FormEntry fProviderText;
060:
061: private FormEntry fPluginText;
062:
063: private FormEntry fUpdateSiteNameText;
064:
065: private FormEntry fUpdateSiteUrlText;
066:
067: private FormEntry fPatchedIdText;
068:
069: private FormEntry fPatchedVersionText;
070:
071: private boolean fPatch = false;
072:
073: public FeatureSpecSection(FeatureFormPage page, Composite parent) {
074: super (page, parent, Section.DESCRIPTION);
075: getSection().setText(
076: PDEUIMessages.FeatureEditor_SpecSection_title);
077: createClient(getSection(), page.getManagedForm().getToolkit());
078: }
079:
080: public void commit(boolean onSave) {
081: fTitleText.commit();
082: fProviderText.commit();
083: fIdText.commit();
084: fPluginText.commit();
085: fVersionText.commit();
086: if (fPatchedIdText != null) {
087: fPatchedIdText.commit();
088: fPatchedVersionText.commit();
089: }
090: fUpdateSiteUrlText.commit();
091: fUpdateSiteNameText.commit();
092: super .commit(onSave);
093: }
094:
095: private void commitSiteUrl(String value) {
096: IFeatureModel model = (IFeatureModel) getPage().getModel();
097: IFeature feature = model.getFeature();
098:
099: IFeatureURL urlElement = feature.getURL();
100: if (urlElement == null) {
101: urlElement = model.getFactory().createURL();
102: try {
103: feature.setURL(urlElement);
104: } catch (CoreException e) {
105: return;
106: }
107: }
108: try {
109: IFeatureURLElement updateElement = urlElement.getUpdate();
110: if (value.length() > 0) {
111: URL siteUrl = new URL(value);
112: if (updateElement == null) {
113: // element needed, create it
114: updateElement = model.getFactory()
115: .createURLElement(urlElement,
116: IFeatureURLElement.UPDATE);
117: updateElement.setURL(siteUrl);
118: urlElement.setUpdate(updateElement);
119: } else {
120: updateElement.setURL(siteUrl);
121: }
122: } else {
123: if (updateElement == null) {
124: // do nothing
125: } else {
126: if (updateElement.getLabel() != null
127: && updateElement.getLabel().length() > 0) {
128: updateElement.setURL(null);
129: } else {
130: // element not needed, remove it
131: urlElement.setUpdate(null);
132: }
133: }
134: }
135: } catch (CoreException e) {
136: PDEPlugin.logException(e);
137: } catch (MalformedURLException e) {
138: PDEPlugin.logException(e);
139: }
140: }
141:
142: private void commitSiteName(String value) {
143: IFeatureModel model = (IFeatureModel) getPage().getModel();
144: IFeature feature = model.getFeature();
145:
146: IFeatureURL urlElement = feature.getURL();
147: if (urlElement == null) {
148: urlElement = model.getFactory().createURL();
149: try {
150: feature.setURL(urlElement);
151: } catch (CoreException e) {
152: return;
153: }
154: }
155: try {
156: IFeatureURLElement updateElement = urlElement.getUpdate();
157: if (value.length() > 0) {
158: if (updateElement == null) {
159: // element needed, create it
160: updateElement = model.getFactory()
161: .createURLElement(urlElement,
162: IFeatureURLElement.UPDATE);
163: updateElement.setLabel(value);
164: // URL not set, so element will be flagged during validation
165: urlElement.setUpdate(updateElement);
166: } else {
167: updateElement.setLabel(value);
168: }
169: } else {
170: if (updateElement == null) {
171: // do nothing
172: } else {
173: if (updateElement.getURL() != null) {
174: updateElement.setLabel(null);
175: } else {
176: // element not needed, remove it
177: urlElement.setUpdate(null);
178: }
179: }
180: }
181: } catch (CoreException e) {
182: PDEPlugin.logException(e);
183: }
184: }
185:
186: /**
187: * Obtains or creates a feature import with patch="true"
188: *
189: * @return
190: */
191: private IFeatureImport getPatchedFeature() {
192: IFeatureModel model = (IFeatureModel) getPage().getModel();
193: IFeature feature = model.getFeature();
194: IFeatureImport[] imports = feature.getImports();
195: for (int i = 0; i < imports.length; i++) {
196: if (imports[i].isPatch()) {
197: return imports[i];
198: }
199: }
200: // need to recreate the import element
201: FeatureImport fimport = (FeatureImport) model.getFactory()
202: .createImport();
203: try {
204: fimport.setType(IFeatureImport.FEATURE);
205: fimport.setPatch(true);
206: feature.addImports(new IFeatureImport[] { fimport });
207: } catch (CoreException ce) {
208: PDEPlugin.logException(ce);
209: }
210: return null;
211: }
212:
213: private boolean isPatch() {
214: return fPatch;
215: }
216:
217: public void createClient(Section section, FormToolkit toolkit) {
218:
219: section.setLayout(FormLayoutFactory.createClearTableWrapLayout(
220: false, 1));
221: TableWrapData twd = new TableWrapData();
222: twd.grabHorizontal = true;
223: section.setLayoutData(twd);
224:
225: fPatch = ((FeatureEditor) getPage().getEditor())
226: .isPatchEditor();
227:
228: final IFeatureModel model = (IFeatureModel) getPage()
229: .getModel();
230: final IFeature feature = model.getFeature();
231:
232: if (isPatch()) {
233: getSection().setDescription(
234: PDEUIMessages.FeatureEditor_SpecSection_desc_patch);
235: } else {
236: getSection().setDescription(
237: PDEUIMessages.FeatureEditor_SpecSection_desc);
238: }
239:
240: Composite container = toolkit.createComposite(section);
241: container.setLayout(FormLayoutFactory
242: .createSectionClientGridLayout(false, 3));
243: container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
244:
245: fIdText = new FormEntry(container, toolkit,
246: PDEUIMessages.FeatureEditor_SpecSection_id, null, false);
247: fIdText.setFormEntryListener(new FormEntryAdapter(this ) {
248: public void textValueChanged(FormEntry text) {
249: try {
250: feature.setId(text.getValue());
251: } catch (CoreException e) {
252: PDEPlugin.logException(e);
253: }
254: }
255: });
256:
257: fVersionText = new FormEntry(container, toolkit,
258: PDEUIMessages.FeatureEditor_SpecSection_version, null,
259: false);
260: fVersionText.setFormEntryListener(new FormEntryAdapter(this ) {
261: public void textValueChanged(FormEntry text) {
262: if (verifySetVersion(feature, text.getValue()) == false) {
263: warnBadVersionFormat(text.getValue());
264: text.setValue(feature.getVersion());
265: }
266: }
267: });
268:
269: fTitleText = new FormEntry(container, toolkit,
270: PDEUIMessages.FeatureEditor_SpecSection_name, null,
271: false);
272: fTitleText.setFormEntryListener(new FormEntryAdapter(this ) {
273: public void textValueChanged(FormEntry text) {
274: try {
275: feature.setLabel(text.getValue());
276: } catch (CoreException e) {
277: PDEPlugin.logException(e);
278: }
279: getPage().getManagedForm().getForm().setText(
280: model.getResourceString(feature.getLabel()));
281: ((FeatureEditor) getPage().getEditor()).updateTitle();
282: }
283: });
284: fProviderText = new FormEntry(container, toolkit,
285: PDEUIMessages.FeatureEditor_SpecSection_provider, null,
286: false);
287: fProviderText.setFormEntryListener(new FormEntryAdapter(this ) {
288: public void textValueChanged(FormEntry text) {
289: try {
290: String value = text.getValue();
291: feature.setProviderName((value.length() > 0 ? value
292: : null));
293: } catch (CoreException e) {
294: PDEPlugin.logException(e);
295: }
296: }
297: });
298:
299: fPluginText = new FormEntry(container, toolkit,
300: PDEUIMessages.FeatureEditor_SpecSection_plugin,
301: PDEUIMessages.GeneralInfoSection_browse, isEditable());
302:
303: fPluginText.setFormEntryListener(new FormEntryAdapter(this ) {
304: public void textValueChanged(FormEntry text) {
305: try {
306: String value = text.getValue();
307: feature.setPlugin((value.length() > 0 ? value
308: : null));
309: } catch (CoreException e) {
310: PDEPlugin.logException(e);
311: }
312: }
313:
314: public void linkActivated(HyperlinkEvent e) {
315: String plugin = fPluginText.getValue();
316: if (PluginRegistry.findModel(plugin) == null) {
317: createFeaturePlugin();
318: }
319: ManifestEditor.openPluginEditor(fPluginText.getValue());
320: }
321:
322: public void browseButtonSelected(FormEntry entry) {
323: handleOpenDialog();
324: }
325:
326: private void createFeaturePlugin() {
327: NewPluginProjectWizard wizard = new NewPluginProjectWizard();
328: WizardDialog dialog = new WizardDialog(PDEPlugin
329: .getActiveWorkbenchShell(), wizard);
330: dialog.create();
331: SWTUtil.setDialogSize(dialog, 400, 500);
332: if (dialog.open() == Window.OK) {
333: String plugin = wizard.getPluginId();
334: try {
335: feature.setPlugin(plugin);
336: fPluginText.setValue(plugin, false);
337: } catch (CoreException ce) {
338: PDEPlugin.logException(ce);
339: }
340: }
341: }
342: });
343:
344: if (isPatch()) {
345: fPatchedIdText = new FormEntry(container, toolkit,
346: PDEUIMessages.FeatureEditor_SpecSection_patchedId,
347: null, false);
348: fPatchedIdText.setFormEntryListener(new FormEntryAdapter(
349: this ) {
350: public void textValueChanged(FormEntry text) {
351: try {
352: IFeatureImport patchImport = getPatchedFeature();
353: if (patchImport != null) {
354: patchImport.setId(text.getValue());
355: }
356: } catch (CoreException e) {
357: PDEPlugin.logException(e);
358: }
359: }
360: });
361:
362: fPatchedVersionText = new FormEntry(
363: container,
364: toolkit,
365: PDEUIMessages.FeatureEditor_SpecSection_patchedVersion,
366: null, false);
367: fPatchedVersionText
368: .setFormEntryListener(new FormEntryAdapter(this ) {
369: public void textValueChanged(FormEntry text) {
370: IFeatureImport patchImport = getPatchedFeature();
371: if (patchImport != null) {
372: if (verifySetVersion(patchImport, text
373: .getValue()) == false) {
374: warnBadVersionFormat(text
375: .getValue());
376: text.setValue(patchImport
377: .getVersion());
378: }
379: }
380: }
381: });
382:
383: }
384:
385: fUpdateSiteUrlText = new FormEntry(container, toolkit,
386: PDEUIMessages.FeatureEditor_SpecSection_updateUrl,
387: null, false);
388: fUpdateSiteUrlText.setFormEntryListener(new FormEntryAdapter(
389: this ) {
390: public void textValueChanged(FormEntry text) {
391: String url = text.getValue() != null ? text.getValue()
392: : ""; //$NON-NLS-1$
393: if (url.length() > 0 && !verifySiteUrl(feature, url)) {
394: warnBadUrl(url);
395: setUpdateSiteUrlText();
396: } else {
397: commitSiteUrl(url);
398: }
399: }
400: });
401:
402: fUpdateSiteNameText = new FormEntry(container, toolkit,
403: PDEUIMessages.FeatureEditor_SpecSection_updateUrlLabel,
404: null, false);
405: fUpdateSiteNameText.setFormEntryListener(new FormEntryAdapter(
406: this ) {
407: public void textValueChanged(FormEntry text) {
408: String name = text.getValue() != null ? text.getValue()
409: : ""; //$NON-NLS-1$
410: commitSiteName(name);
411: }
412: });
413:
414: GridData gd = (GridData) fIdText.getText().getLayoutData();
415: gd.widthHint = 150;
416:
417: toolkit.paintBordersFor(container);
418: section.setClient(container);
419: initialize();
420: }
421:
422: private boolean verifySetVersion(IFeature feature, String value) {
423: try {
424: if (VersionUtil.validateVersion(value).isOK())
425: feature.setVersion(value);
426: } catch (Exception e) {
427: return false;
428: }
429: return true;
430: }
431:
432: private boolean verifySetVersion(IFeatureImport featureImport,
433: String value) {
434: try {
435: if (VersionUtil.validateVersion(value).isOK())
436: featureImport.setVersion(value);
437: } catch (Exception e) {
438: return false;
439: }
440: return true;
441: }
442:
443: private boolean verifySiteUrl(IFeature feature, String value) {
444: try {
445: new URL(value);
446: } catch (MalformedURLException e) {
447: return false;
448: }
449: return true;
450: }
451:
452: private void warnBadVersionFormat(String text) {
453: MessageDialog
454: .openError(
455: PDEPlugin.getActiveWorkbenchShell(),
456: PDEUIMessages.FeatureEditor_SpecSection_badVersionTitle,
457: PDEUIMessages.FeatureEditor_SpecSection_badVersionMessage);
458: }
459:
460: private void warnBadUrl(String text) {
461: MessageDialog.openError(PDEPlugin.getActiveWorkbenchShell(),
462: PDEUIMessages.FeatureEditor_SpecSection_badUrlTitle,
463: PDEUIMessages.FeatureEditor_SpecSection_badUrlMessage);
464: }
465:
466: public void dispose() {
467: IFeatureModel model = (IFeatureModel) getPage().getModel();
468: if (model != null)
469: model.removeModelChangedListener(this );
470: super .dispose();
471: }
472:
473: public void initialize() {
474: IFeatureModel model = (IFeatureModel) getPage().getModel();
475: refresh();
476: if (!model.isEditable()) {
477: fIdText.getText().setEditable(false);
478: fTitleText.getText().setEditable(false);
479: fVersionText.getText().setEditable(false);
480: fProviderText.getText().setEditable(false);
481: fPluginText.getText().setEditable(false);
482: if (isPatch()) {
483: fPatchedIdText.getText().setEditable(false);
484: fPatchedVersionText.getText().setEditable(false);
485: }
486: fUpdateSiteUrlText.getText().setEditable(false);
487: fUpdateSiteNameText.getText().setEditable(false);
488: }
489: model.addModelChangedListener(this );
490: }
491:
492: public void modelChanged(IModelChangedEvent e) {
493: if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
494: markStale();
495: return;
496: }
497: if (e.getChangeType() == IModelChangedEvent.CHANGE) {
498: Object objs[] = e.getChangedObjects();
499: if (objs.length > 0 && objs[0] instanceof IFeature) {
500: markStale();
501: }
502: }
503: if (e.getChangeType() == IModelChangedEvent.CHANGE) {
504: Object objs[] = e.getChangedObjects();
505: if (objs.length > 0 && objs[0] instanceof IFeatureURL) {
506: markStale();
507: }
508: }
509: Object objs[] = e.getChangedObjects();
510: if (objs.length > 0 && objs[0] instanceof IFeatureURLElement) {
511: markStale();
512: }
513: if (isPatch() && objs.length > 0
514: && objs[0] instanceof IFeatureImport) {
515: markStale();
516: }
517: }
518:
519: public void setFocus() {
520: if (fIdText != null)
521: fIdText.getText().setFocus();
522: }
523:
524: private void setIfDefined(FormEntry formText, String value) {
525: if (value != null) {
526: formText.setValue(value, true);
527: }
528: }
529:
530: public void refresh() {
531: IFeatureModel model = (IFeatureModel) getPage().getModel();
532: IFeature feature = model.getFeature();
533: setIfDefined(fIdText, feature.getId());
534: setIfDefined(fTitleText, feature.getLabel());
535: getPage().getManagedForm().getForm().setText(
536: model.getResourceString(feature.getLabel()));
537: setIfDefined(fVersionText, feature.getVersion());
538: setIfDefined(fProviderText, feature.getProviderName());
539: setIfDefined(fPluginText, feature.getPlugin());
540: if (isPatch()) {
541: IFeatureImport featureImport = getPatchedFeature();
542: if (featureImport != null) {
543: fPatchedIdText.setValue(
544: featureImport.getId() != null ? featureImport
545: .getId() : "", true); //$NON-NLS-1$
546: fPatchedVersionText
547: .setValue(
548: featureImport.getVersion() != null ? featureImport
549: .getVersion()
550: : "", true); //$NON-NLS-1$
551: } else {
552: fPatchedIdText.setValue("", true); //$NON-NLS-1$
553: fPatchedVersionText.setValue("", true); //$NON-NLS-1$
554: }
555: }
556: setUpdateSiteUrlText();
557: setUpdateSiteNameText();
558: super .refresh();
559: }
560:
561: private void setUpdateSiteUrlText() {
562: IFeatureModel model = (IFeatureModel) getPage().getModel();
563: IFeature feature = model.getFeature();
564:
565: String updateSiteUrl = ""; //$NON-NLS-1$
566: IFeatureURL featureUrl = feature.getURL();
567: if (featureUrl != null) {
568: IFeatureURLElement urlElement = featureUrl.getUpdate();
569: if (urlElement != null) {
570: updateSiteUrl = urlElement.getURL() != null ? urlElement
571: .getURL().toExternalForm()
572: : null;
573: }
574: }
575: fUpdateSiteUrlText.setValue(
576: updateSiteUrl != null ? updateSiteUrl : "", //$NON-NLS-1$
577: true);
578:
579: }
580:
581: private void setUpdateSiteNameText() {
582: IFeatureModel model = (IFeatureModel) getPage().getModel();
583: IFeature feature = model.getFeature();
584:
585: String updateSiteLabel = ""; //$NON-NLS-1$
586: IFeatureURL featureUrl = feature.getURL();
587: if (featureUrl != null) {
588: IFeatureURLElement urlElement = featureUrl.getUpdate();
589: if (urlElement != null) {
590: updateSiteLabel = urlElement.getLabel();
591: }
592: }
593: fUpdateSiteNameText.setValue(
594: updateSiteLabel != null ? updateSiteLabel : "", true); //$NON-NLS-1$
595: }
596:
597: public void cancelEdit() {
598: fIdText.cancelEdit();
599: fTitleText.cancelEdit();
600: fVersionText.cancelEdit();
601: fProviderText.cancelEdit();
602: fPluginText.cancelEdit();
603: if (isPatch()) {
604: fPatchedIdText.cancelEdit();
605: fPatchedVersionText.cancelEdit();
606: }
607: fUpdateSiteNameText.cancelEdit();
608: fUpdateSiteUrlText.cancelEdit();
609: super .cancelEdit();
610: }
611:
612: /**
613: * @see org.eclipse.update.ui.forms.internal.FormSection#canPaste(Clipboard)
614: */
615: public boolean canPaste(Clipboard clipboard) {
616: TransferData[] types = clipboard.getAvailableTypes();
617: Transfer[] transfers = new Transfer[] {
618: TextTransfer.getInstance(), RTFTransfer.getInstance() };
619: for (int i = 0; i < types.length; i++) {
620: for (int j = 0; j < transfers.length; j++) {
621: if (transfers[j].isSupportedType(types[i]))
622: return true;
623: }
624: }
625: return false;
626: }
627:
628: protected void handleOpenDialog() {
629: PluginSelectionDialog dialog = new PluginSelectionDialog(
630: getSection().getShell(), false, false);
631: dialog.create();
632: if (dialog.open() == Window.OK) {
633: IPluginModel model = (IPluginModel) dialog.getFirstResult();
634: IPlugin plugin = model.getPlugin();
635: fPluginText.setValue(plugin.getId());
636: }
637: }
638: }
|