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.util.ArrayList;
013: import java.util.Iterator;
014:
015: import org.eclipse.core.runtime.CoreException;
016: import org.eclipse.jface.action.Action;
017: import org.eclipse.jface.action.IMenuManager;
018: import org.eclipse.jface.action.Separator;
019: import org.eclipse.jface.action.ToolBarManager;
020: import org.eclipse.jface.viewers.ISelection;
021: import org.eclipse.jface.viewers.IStructuredContentProvider;
022: import org.eclipse.jface.viewers.IStructuredSelection;
023: import org.eclipse.jface.viewers.StructuredSelection;
024: import org.eclipse.jface.viewers.TableViewer;
025: import org.eclipse.jface.window.Window;
026: import org.eclipse.pde.core.IModelChangedEvent;
027: import org.eclipse.pde.core.plugin.IPluginBase;
028: import org.eclipse.pde.core.plugin.IPluginModelBase;
029: import org.eclipse.pde.core.plugin.ModelEntry;
030: import org.eclipse.pde.core.plugin.PluginRegistry;
031: import org.eclipse.pde.internal.core.IFeatureModelDelta;
032: import org.eclipse.pde.internal.core.IFeatureModelListener;
033: import org.eclipse.pde.internal.core.IPluginModelListener;
034: import org.eclipse.pde.internal.core.PDECore;
035: import org.eclipse.pde.internal.core.PluginModelDelta;
036: import org.eclipse.pde.internal.core.feature.FeatureImport;
037: import org.eclipse.pde.internal.core.ifeature.IFeature;
038: import org.eclipse.pde.internal.core.ifeature.IFeatureImport;
039: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
040: import org.eclipse.pde.internal.core.ifeature.IFeaturePlugin;
041: import org.eclipse.pde.internal.ui.PDEPlugin;
042: import org.eclipse.pde.internal.ui.PDEUIMessages;
043: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
044: import org.eclipse.pde.internal.ui.editor.ModelDataTransfer;
045: import org.eclipse.pde.internal.ui.editor.TableSection;
046: import org.eclipse.pde.internal.ui.editor.actions.SortAction;
047: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
048: import org.eclipse.pde.internal.ui.parts.TablePart;
049: import org.eclipse.pde.internal.ui.wizards.FeatureSelectionDialog;
050: import org.eclipse.pde.internal.ui.wizards.ListUtil;
051: import org.eclipse.pde.internal.ui.wizards.PluginSelectionDialog;
052: import org.eclipse.swt.SWT;
053: import org.eclipse.swt.custom.BusyIndicator;
054: import org.eclipse.swt.dnd.Clipboard;
055: import org.eclipse.swt.events.DisposeEvent;
056: import org.eclipse.swt.events.DisposeListener;
057: import org.eclipse.swt.graphics.Cursor;
058: import org.eclipse.swt.layout.GridData;
059: import org.eclipse.swt.widgets.Button;
060: import org.eclipse.swt.widgets.Composite;
061: import org.eclipse.swt.widgets.Display;
062: import org.eclipse.swt.widgets.ToolBar;
063: import org.eclipse.ui.actions.ActionFactory;
064: import org.eclipse.ui.forms.widgets.FormToolkit;
065: import org.eclipse.ui.forms.widgets.Section;
066:
067: public class RequiresSection extends TableSection implements
068: IPluginModelListener, IFeatureModelListener {
069: private Button fSyncButton;
070:
071: private TableViewer fPluginViewer;
072:
073: private Action fDeleteAction;
074:
075: private SortAction fSortAction;
076:
077: class ImportContentProvider extends DefaultContentProvider
078: implements IStructuredContentProvider {
079: public Object[] getElements(Object parent) {
080: if (parent instanceof IFeature) {
081: IFeatureImport[] imports = ((IFeature) parent)
082: .getImports();
083: ArrayList displayable = new ArrayList();
084: for (int i = 0; i < imports.length; i++) {
085: if (imports[i].isPatch())
086: continue;
087: displayable.add(imports[i]);
088: }
089:
090: return displayable.toArray();
091: }
092: return new Object[0];
093: }
094: }
095:
096: public RequiresSection(FeatureDependenciesPage page,
097: Composite parent) {
098: super (page, parent, Section.DESCRIPTION, new String[] {
099: PDEUIMessages.FeatureEditor_RequiresSection_plugin,
100: PDEUIMessages.FeatureEditor_RequiresSection_feature,
101: null,
102: PDEUIMessages.FeatureEditor_RequiresSection_compute });
103: getSection().setText(
104: PDEUIMessages.FeatureEditor_RequiresSection_title);
105: getSection().setDescription(
106: PDEUIMessages.FeatureEditor_RequiresSection_desc);
107: getTablePart().setEditable(false);
108: }
109:
110: public void commit(boolean onSave) {
111: super .commit(onSave);
112: }
113:
114: public void createClient(Section section, FormToolkit toolkit) {
115:
116: section.setLayout(FormLayoutFactory.createClearGridLayout(
117: false, 1));
118: GridData data = new GridData(GridData.FILL_BOTH);
119: section.setLayoutData(data);
120:
121: Composite container = createClientContainer(section, 2, toolkit);
122:
123: fSyncButton = toolkit.createButton(container,
124: PDEUIMessages.FeatureEditor_RequiresSection_sync,
125: SWT.CHECK);
126: // syncButton.setSelection(true);
127: GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
128: gd.horizontalSpan = 2;
129: fSyncButton.setLayoutData(gd);
130:
131: createViewerPartControl(container, SWT.MULTI, 2, toolkit);
132:
133: TablePart tablePart = getTablePart();
134: fPluginViewer = tablePart.getTableViewer();
135: fPluginViewer.setContentProvider(new ImportContentProvider());
136: fPluginViewer.setComparator(ListUtil.NAME_COMPARATOR);
137: fPluginViewer.setLabelProvider(PDEPlugin.getDefault()
138: .getLabelProvider());
139:
140: fDeleteAction = new Action() {
141: public void run() {
142: handleDelete();
143: }
144: };
145: fDeleteAction.setText(PDEUIMessages.Actions_delete_label);
146: toolkit.paintBordersFor(container);
147: section.setClient(container);
148: initialize();
149: createSectionToolbar(section, toolkit);
150: }
151:
152: /**
153: * @param section
154: * @param toolkit
155: */
156: private void createSectionToolbar(Section section,
157: FormToolkit toolkit) {
158:
159: ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
160: ToolBar toolbar = toolBarManager.createControl(section);
161: final Cursor handCursor = new Cursor(Display.getCurrent(),
162: SWT.CURSOR_HAND);
163: toolbar.setCursor(handCursor);
164: // Cursor needs to be explicitly disposed
165: toolbar.addDisposeListener(new DisposeListener() {
166: public void widgetDisposed(DisposeEvent e) {
167: if ((handCursor != null)
168: && (handCursor.isDisposed() == false)) {
169: handCursor.dispose();
170: }
171: }
172: });
173: // Add sort action to the tool bar
174: fSortAction = new SortAction(getStructuredViewerPart()
175: .getViewer(),
176: PDEUIMessages.FeatureEditor_RequiresSection_sortAlpha,
177: ListUtil.NAME_COMPARATOR, null, null);
178:
179: toolBarManager.add(fSortAction);
180:
181: toolBarManager.update(true);
182:
183: section.setTextClient(toolbar);
184: }
185:
186: protected void buttonSelected(int index) {
187: switch (index) {
188: case 0:
189: handleNewPlugin();
190: break;
191: case 1:
192: handleNewFeature();
193: break;
194: case 2:
195: break;
196: case 3:
197: recomputeImports();
198: break;
199: }
200: }
201:
202: private void handleNewPlugin() {
203: BusyIndicator.showWhile(fPluginViewer.getTable().getDisplay(),
204: new Runnable() {
205: public void run() {
206: IPluginModelBase[] allModels = PluginRegistry
207: .getActiveModels();
208: ArrayList newModels = new ArrayList();
209: for (int i = 0; i < allModels.length; i++) {
210: if (canAdd(allModels[i]))
211: newModels.add(allModels[i]);
212: }
213: IPluginModelBase[] candidateModels = (IPluginModelBase[]) newModels
214: .toArray(new IPluginModelBase[newModels
215: .size()]);
216: PluginSelectionDialog dialog = new PluginSelectionDialog(
217: fPluginViewer.getTable().getShell(),
218: candidateModels, true);
219: if (dialog.open() == Window.OK) {
220: Object[] models = dialog.getResult();
221: try {
222: doAdd(models);
223: } catch (CoreException e) {
224: PDEPlugin.log(e);
225: }
226: }
227: }
228: });
229: }
230:
231: private boolean canAdd(IPluginModelBase candidate) {
232: IPluginBase plugin = candidate.getPluginBase();
233: if (candidate.isFragmentModel())
234: return false;
235:
236: IFeatureModel model = (IFeatureModel) getPage().getModel();
237: IFeatureImport[] imports = model.getFeature().getImports();
238:
239: for (int i = 0; i < imports.length; i++) {
240: IFeatureImport fimport = imports[i];
241: if (plugin.getId().equals(fimport.getId()))
242: return false;
243: }
244: // don't show plug-ins that are listed in this feature
245: IFeaturePlugin[] fplugins = model.getFeature().getPlugins();
246: for (int i = 0; i < fplugins.length; i++) {
247: IFeaturePlugin fplugin = fplugins[i];
248: if (plugin.getId().equals(fplugin.getId()))
249: return false;
250: }
251: return true;
252: }
253:
254: private void handleNewFeature() {
255: BusyIndicator.showWhile(fPluginViewer.getTable().getDisplay(),
256: new Runnable() {
257: public void run() {
258: IFeatureModel[] allModels = PDECore
259: .getDefault().getFeatureModelManager()
260: .getModels();
261: ArrayList newModels = new ArrayList();
262: for (int i = 0; i < allModels.length; i++) {
263: if (canAdd(allModels[i]))
264: newModels.add(allModels[i]);
265: }
266: IFeatureModel[] candidateModels = (IFeatureModel[]) newModels
267: .toArray(new IFeatureModel[newModels
268: .size()]);
269: FeatureSelectionDialog dialog = new FeatureSelectionDialog(
270: fPluginViewer.getTable().getShell(),
271: candidateModels, true);
272: if (dialog.open() == Window.OK) {
273: Object[] models = dialog.getResult();
274: try {
275: doAdd(models);
276: } catch (CoreException e) {
277: PDECore.log(e);
278: }
279: }
280: }
281: });
282: }
283:
284: private void doAdd(Object[] candidates) throws CoreException {
285: IFeatureModel model = (IFeatureModel) getPage().getModel();
286: IFeature feature = model.getFeature();
287: IFeatureImport[] added = new IFeatureImport[candidates.length];
288: for (int i = 0; i < candidates.length; i++) {
289: FeatureImport fimport = (FeatureImport) model.getFactory()
290: .createImport();
291: if (candidates[i] instanceof IFeatureModel) {
292: IFeatureModel candidate = (IFeatureModel) candidates[i];
293: fimport.loadFrom(candidate.getFeature());
294: } else { // instanceof IPluginModelBase
295: IPluginModelBase candidate = (IPluginModelBase) candidates[i];
296: IPluginBase pluginBase = candidate.getPluginBase();
297: fimport.setId(pluginBase.getId());
298: }
299: added[i] = fimport;
300: }
301: feature.addImports(added);
302: }
303:
304: private boolean canAdd(IFeatureModel candidate) {
305: IFeature cfeature = candidate.getFeature();
306:
307: IFeatureModel model = (IFeatureModel) getPage().getModel();
308: IFeature feature = model.getFeature();
309:
310: if (cfeature.getId().equals(feature.getId())
311: && cfeature.getVersion().equals(feature.getVersion())) {
312: return false;
313: }
314:
315: IFeatureImport[] features = feature.getImports();
316:
317: for (int i = 0; i < features.length; i++) {
318: if (features[i].getId().equals(cfeature.getId())
319: && features[i].getVersion() != null
320: && features[i].getVersion().equals(
321: cfeature.getVersion()))
322: return false;
323: }
324: return true;
325: }
326:
327: private void handleDelete() {
328: IFeatureModel model = (IFeatureModel) getPage().getModel();
329: if (!model.isEditable()) {
330: return;
331: }
332: IFeature feature = model.getFeature();
333: IStructuredSelection selection = (IStructuredSelection) fPluginViewer
334: .getSelection();
335: if (selection.isEmpty())
336: return;
337:
338: try {
339: IFeatureImport[] deleted = new IFeatureImport[selection
340: .size()];
341: int i = 0;
342: for (Iterator iter = selection.iterator(); iter.hasNext();) {
343: IFeatureImport iimport = (IFeatureImport) iter.next();
344: deleted[i++] = iimport;
345: }
346: feature.removeImports(deleted);
347: } catch (CoreException e) {
348: PDEPlugin.logException(e);
349: }
350: }
351:
352: private void handleSelectAll() {
353: IStructuredContentProvider provider = (IStructuredContentProvider) fPluginViewer
354: .getContentProvider();
355: Object[] elements = provider.getElements(fPluginViewer
356: .getInput());
357: StructuredSelection ssel = new StructuredSelection(elements);
358: fPluginViewer.setSelection(ssel);
359: }
360:
361: public void dispose() {
362: IFeatureModel model = (IFeatureModel) getPage().getModel();
363: if (model != null)
364: model.removeModelChangedListener(this );
365: PDECore.getDefault().getModelManager()
366: .removePluginModelListener(this );
367: PDECore.getDefault().getFeatureModelManager()
368: .removeFeatureModelListener(this );
369: super .dispose();
370: }
371:
372: public boolean doGlobalAction(String actionId) {
373: if (actionId.equals(ActionFactory.DELETE.getId())) {
374: BusyIndicator.showWhile(fPluginViewer.getTable()
375: .getDisplay(), new Runnable() {
376: public void run() {
377: handleDelete();
378: }
379: });
380: return true;
381: }
382: if (actionId.equals(ActionFactory.CUT.getId())) {
383: // delete here and let the editor transfer
384: // the selection to the clipboard
385: handleDelete();
386: return false;
387: }
388: if (actionId.equals(ActionFactory.PASTE.getId())) {
389: doPaste();
390: return true;
391: }
392: if (actionId.equals(ActionFactory.SELECT_ALL.getId())) {
393: BusyIndicator.showWhile(fPluginViewer.getTable()
394: .getDisplay(), new Runnable() {
395: public void run() {
396: handleSelectAll();
397: }
398: });
399: return true;
400: }
401: return false;
402: }
403:
404: public void expandTo(Object object) {
405: if (object instanceof IFeatureImport) {
406: StructuredSelection ssel = new StructuredSelection(object);
407: fPluginViewer.setSelection(ssel);
408: }
409: }
410:
411: protected void fillContextMenu(IMenuManager manager) {
412: IStructuredSelection selection = (StructuredSelection) fPluginViewer
413: .getSelection();
414: if (!selection.isEmpty()) {
415: manager.add(fDeleteAction);
416: manager.add(new Separator());
417: }
418: getPage().getPDEEditor().getContributor()
419: .contextMenuAboutToShow(manager);
420: }
421:
422: protected void selectionChanged(IStructuredSelection selection) {
423: getPage().getPDEEditor().setSelection(selection);
424: getPage().getManagedForm()
425: .fireSelectionChanged(this , selection);
426: }
427:
428: public void initialize() {
429: IFeatureModel model = (IFeatureModel) getPage().getModel();
430: refresh();
431: if (model.isEditable() == false) {
432: getTablePart().setButtonEnabled(0, false);
433: getTablePart().setButtonEnabled(1, false);
434: getTablePart().setButtonEnabled(3, false);
435: fSyncButton.setEnabled(false);
436: }
437: model.addModelChangedListener(this );
438: PDECore.getDefault().getModelManager().addPluginModelListener(
439: this );
440: PDECore.getDefault().getFeatureModelManager()
441: .addFeatureModelListener(this );
442: }
443:
444: public void modelChanged(IModelChangedEvent e) {
445: if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
446: markStale();
447: return;
448: } else if (e.getChangeType() == IModelChangedEvent.CHANGE) {
449: Object obj = e.getChangedObjects()[0];
450: if (obj instanceof IFeatureImport) {
451: fPluginViewer.refresh(obj);
452: }
453: } else {
454: Object obj = e.getChangedObjects()[0];
455: if (obj instanceof IFeatureImport) {
456: if (e.getChangeType() == IModelChangedEvent.INSERT) {
457: fPluginViewer.add(e.getChangedObjects());
458: if (e.getChangedObjects().length > 0) {
459: fPluginViewer
460: .setSelection(new StructuredSelection(e
461: .getChangedObjects()[0]));
462: }
463: } else
464: fPluginViewer.remove(e.getChangedObjects());
465: } else if (obj instanceof IFeaturePlugin) {
466: if (fSyncButton.getSelection()) {
467: recomputeImports();
468: }
469: }
470: }
471: }
472:
473: private void recomputeImports() {
474: IFeatureModel model = (IFeatureModel) getPage().getModel();
475: IFeature feature = model.getFeature();
476: try {
477: feature.computeImports();
478: } catch (CoreException e) {
479: PDEPlugin.logException(e);
480: }
481: }
482:
483: public void modelsChanged(final PluginModelDelta delta) {
484: getSection().getDisplay().asyncExec(new Runnable() {
485: public void run() {
486: if (getSection().isDisposed()) {
487: return;
488: }
489: ModelEntry[] added = delta.getAddedEntries();
490: ModelEntry[] removed = delta.getRemovedEntries();
491: ModelEntry[] changed = delta.getChangedEntries();
492: if (hasModels(added) || hasModels(removed)
493: || hasModels(changed))
494: markStale();
495: }
496: });
497: }
498:
499: private boolean hasModels(ModelEntry[] entries) {
500: if (entries == null)
501: return false;
502: return entries.length > 0;
503: }
504:
505: public void modelsChanged(final IFeatureModelDelta delta) {
506: getSection().getDisplay().asyncExec(new Runnable() {
507: public void run() {
508: if (getSection().isDisposed()) {
509: return;
510: }
511: IFeatureModel[] added = delta.getAdded();
512: IFeatureModel[] removed = delta.getRemoved();
513: IFeatureModel[] changed = delta.getChanged();
514: if (hasModels(added) || hasModels(removed)
515: || hasModels(changed))
516: markStale();
517: }
518: });
519: }
520:
521: private boolean hasModels(IFeatureModel[] models) {
522: if (models == null)
523: return false;
524: IFeatureModel this Model = (IFeatureModel) getPage().getModel();
525: for (int i = 0; i < models.length; i++) {
526: if (models[i] != this Model) {
527: return true;
528: }
529: }
530: return false;
531: }
532:
533: public void setFocus() {
534: if (fPluginViewer != null)
535: fPluginViewer.getTable().setFocus();
536: }
537:
538: public void refresh() {
539: IFeatureModel model = (IFeatureModel) getPage().getModel();
540: IFeature feature = model.getFeature();
541: fPluginViewer.setInput(feature);
542: super .refresh();
543: }
544:
545: /**
546: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(Clipboard)
547: */
548: public boolean canPaste(Clipboard clipboard) {
549: Object[] objects = (Object[]) clipboard
550: .getContents(ModelDataTransfer.getInstance());
551: if (objects != null && objects.length > 0) {
552: return canPaste(null, objects);
553: }
554: return false;
555: }
556:
557: /**
558: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(Object,
559: * Object[])
560: */
561: protected boolean canPaste(Object target, Object[] objects) {
562: for (int i = 0; i < objects.length; i++) {
563: if (!(objects[i] instanceof FeatureImport))
564: return false;
565: }
566: return true;
567: }
568:
569: /**
570: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste()
571: */
572: protected void doPaste() {
573: Clipboard clipboard = getPage().getPDEEditor().getClipboard();
574: Object[] objects = (Object[]) clipboard
575: .getContents(ModelDataTransfer.getInstance());
576: if (objects != null && canPaste(null, objects))
577: doPaste(null, objects);
578: }
579:
580: /**
581: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste(Object,
582: * Object[])
583: */
584: protected void doPaste(Object target, Object[] objects) {
585: IFeatureModel model = (IFeatureModel) getPage().getModel();
586: IFeature feature = model.getFeature();
587: if (!model.isEditable()) {
588: return;
589: }
590:
591: IFeatureImport[] imports = new IFeatureImport[objects.length];
592: try {
593: for (int i = 0; i < objects.length; i++) {
594: FeatureImport fImport = (FeatureImport) objects[i];
595: fImport.setModel(model);
596: fImport.setParent(feature);
597: imports[i] = fImport;
598: }
599: feature.addImports(imports);
600: } catch (CoreException e) {
601: PDEPlugin.logException(e);
602: }
603:
604: }
605:
606: void fireSelection() {
607: ISelection sel = fPluginViewer.getSelection();
608: if (!sel.isEmpty()) {
609: fPluginViewer.setSelection(fPluginViewer.getSelection());
610: } else if (fPluginViewer.getElementAt(0) != null) {
611: fPluginViewer.setSelection(new StructuredSelection(
612: fPluginViewer.getElementAt(0)));
613: }
614: }
615:
616: protected boolean createCount() {
617: return true;
618: }
619:
620: }
|