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.IModel;
027: import org.eclipse.pde.core.IModelChangedEvent;
028: import org.eclipse.pde.internal.core.FeatureModelManager;
029: import org.eclipse.pde.internal.core.IFeatureModelDelta;
030: import org.eclipse.pde.internal.core.IFeatureModelListener;
031: import org.eclipse.pde.internal.core.PDECore;
032: import org.eclipse.pde.internal.core.feature.FeatureChild;
033: import org.eclipse.pde.internal.core.ifeature.IFeature;
034: import org.eclipse.pde.internal.core.ifeature.IFeatureChild;
035: import org.eclipse.pde.internal.core.ifeature.IFeatureImport;
036: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
037: import org.eclipse.pde.internal.ui.PDEPlugin;
038: import org.eclipse.pde.internal.ui.PDEUIMessages;
039: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
040: import org.eclipse.pde.internal.ui.editor.ModelDataTransfer;
041: import org.eclipse.pde.internal.ui.editor.PDEFormPage;
042: import org.eclipse.pde.internal.ui.editor.TableSection;
043: import org.eclipse.pde.internal.ui.editor.actions.SortAction;
044: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
045: import org.eclipse.pde.internal.ui.parts.TablePart;
046: import org.eclipse.pde.internal.ui.wizards.FeatureSelectionDialog;
047: import org.eclipse.pde.internal.ui.wizards.ListUtil;
048: import org.eclipse.swt.SWT;
049: import org.eclipse.swt.custom.BusyIndicator;
050: import org.eclipse.swt.dnd.Clipboard;
051: import org.eclipse.swt.events.DisposeEvent;
052: import org.eclipse.swt.events.DisposeListener;
053: import org.eclipse.swt.graphics.Cursor;
054: import org.eclipse.swt.layout.GridData;
055: import org.eclipse.swt.widgets.Composite;
056: import org.eclipse.swt.widgets.Display;
057: import org.eclipse.swt.widgets.ToolBar;
058: import org.eclipse.ui.actions.ActionFactory;
059: import org.eclipse.ui.forms.widgets.FormToolkit;
060: import org.eclipse.ui.forms.widgets.Section;
061:
062: public class IncludedFeaturesSection extends TableSection implements
063: IFeatureModelListener {
064: private TableViewer fIncludesViewer;
065:
066: private Action fNewAction;
067:
068: private Action fOpenAction;
069:
070: private Action fDeleteAction;
071:
072: private SortAction fSortAction;
073:
074: class IncludedFeaturesContentProvider extends
075: DefaultContentProvider implements
076: IStructuredContentProvider {
077: public Object[] getElements(Object parent) {
078: if (parent instanceof IFeature) {
079: return ((IFeature) parent).getIncludedFeatures();
080: }
081: return new Object[0];
082: }
083: }
084:
085: public IncludedFeaturesSection(PDEFormPage page, Composite parent) {
086: super (
087: page,
088: parent,
089: Section.DESCRIPTION,
090: new String[] { PDEUIMessages.FeatureEditor_IncludedFeatures_new });
091: getSection().setText(
092: PDEUIMessages.FeatureEditor_IncludedFeatures_title);
093: getSection().setDescription(
094: PDEUIMessages.FeatureEditor_IncludedFeatures_desc);
095: getTablePart().setEditable(false);
096: getSection().setLayoutData(new GridData(GridData.FILL_BOTH));
097: }
098:
099: public void commit(boolean onSave) {
100: super .commit(onSave);
101: }
102:
103: public void createClient(Section section, FormToolkit toolkit) {
104:
105: section.setLayout(FormLayoutFactory.createClearGridLayout(
106: false, 1));
107: GridData data = new GridData(GridData.FILL_BOTH);
108: section.setLayoutData(data);
109:
110: Composite container = createClientContainer(section, 2, toolkit);
111:
112: createViewerPartControl(container, SWT.MULTI, 2, toolkit);
113: TablePart tablePart = getTablePart();
114: fIncludesViewer = tablePart.getTableViewer();
115: fIncludesViewer
116: .setContentProvider(new IncludedFeaturesContentProvider());
117: fIncludesViewer.setLabelProvider(PDEPlugin.getDefault()
118: .getLabelProvider());
119: fIncludesViewer.setComparator(ListUtil.NAME_COMPARATOR);
120: toolkit.paintBordersFor(container);
121: makeActions();
122: section.setClient(container);
123: initialize();
124: createSectionToolbar(section, toolkit);
125: }
126:
127: /**
128: * @param section
129: * @param toolkit
130: */
131: private void createSectionToolbar(Section section,
132: FormToolkit toolkit) {
133:
134: ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
135: ToolBar toolbar = toolBarManager.createControl(section);
136: final Cursor handCursor = new Cursor(Display.getCurrent(),
137: SWT.CURSOR_HAND);
138: toolbar.setCursor(handCursor);
139: // Cursor needs to be explicitly disposed
140: toolbar.addDisposeListener(new DisposeListener() {
141: public void widgetDisposed(DisposeEvent e) {
142: if ((handCursor != null)
143: && (handCursor.isDisposed() == false)) {
144: handCursor.dispose();
145: }
146: }
147: });
148: // Add sort action to the tool bar
149: fSortAction = new SortAction(getStructuredViewerPart()
150: .getViewer(),
151: PDEUIMessages.FeatureEditor_IncludedFeatures_sortAlpha,
152: ListUtil.NAME_COMPARATOR, null, null);
153:
154: toolBarManager.add(fSortAction);
155:
156: toolBarManager.update(true);
157:
158: section.setTextClient(toolbar);
159: }
160:
161: protected void handleDoubleClick(IStructuredSelection selection) {
162: fOpenAction.run();
163: }
164:
165: protected void buttonSelected(int index) {
166: if (index == 0)
167: handleNew();
168: }
169:
170: public void dispose() {
171: IFeatureModel model = (IFeatureModel) getPage().getModel();
172: if (model != null)
173: model.removeModelChangedListener(this );
174: FeatureModelManager mng = PDECore.getDefault()
175: .getFeatureModelManager();
176: mng.removeFeatureModelListener(this );
177: super .dispose();
178: }
179:
180: public boolean setFormInput(Object object) {
181: if (object instanceof IFeatureChild) {
182: fIncludesViewer.setSelection(
183: new StructuredSelection(object), true);
184: return true;
185: }
186: return false;
187: }
188:
189: protected void fillContextMenu(IMenuManager manager) {
190: manager.add(fOpenAction);
191: manager.add(new Separator());
192: manager.add(fNewAction);
193: manager.add(fDeleteAction);
194: manager.add(new Separator());
195: getPage().getPDEEditor().getContributor()
196: .contextMenuAboutToShow(manager);
197: }
198:
199: private void handleNew() {
200: BusyIndicator.showWhile(
201: fIncludesViewer.getTable().getDisplay(),
202: new Runnable() {
203: public void run() {
204: IFeatureModel[] allModels = PDECore
205: .getDefault().getFeatureModelManager()
206: .getModels();
207: ArrayList newModels = new ArrayList();
208: for (int i = 0; i < allModels.length; i++) {
209: if (canAdd(allModels[i]))
210: newModels.add(allModels[i]);
211: }
212: IFeatureModel[] candidateModels = (IFeatureModel[]) newModels
213: .toArray(new IFeatureModel[newModels
214: .size()]);
215: FeatureSelectionDialog dialog = new FeatureSelectionDialog(
216: fIncludesViewer.getTable().getShell(),
217: candidateModels, true);
218: if (dialog.open() == Window.OK) {
219: Object[] models = dialog.getResult();
220: try {
221: doAdd(models);
222: } catch (CoreException e) {
223: PDEPlugin.log(e);
224: }
225: }
226: }
227: });
228: }
229:
230: private void doAdd(Object[] candidates) throws CoreException {
231: IFeatureModel model = (IFeatureModel) getPage().getModel();
232: IFeature feature = model.getFeature();
233: IFeatureChild[] added = new IFeatureChild[candidates.length];
234: for (int i = 0; i < candidates.length; i++) {
235: IFeatureModel candidate = (IFeatureModel) candidates[i];
236: FeatureChild child = (FeatureChild) model.getFactory()
237: .createChild();
238: child.loadFrom(candidate.getFeature());
239: child.setVersion("0.0.0"); //$NON-NLS-1$
240: added[i] = child;
241: }
242: feature.addIncludedFeatures(added);
243: }
244:
245: private boolean canAdd(IFeatureModel candidate) {
246: IFeature cfeature = candidate.getFeature();
247:
248: IFeatureModel model = (IFeatureModel) getPage().getModel();
249: IFeature feature = model.getFeature();
250:
251: if (cfeature.getId().equals(feature.getId())
252: && cfeature.getVersion().equals(feature.getVersion())) {
253: return false;
254: }
255:
256: boolean isPatchEditor = ((FeatureEditor) getPage().getEditor())
257: .isPatchEditor();
258: if (isPatchEditor && !isFeaturePatch(candidate.getFeature())) {
259: return false;
260: }
261:
262: IFeatureChild[] features = feature.getIncludedFeatures();
263:
264: for (int i = 0; i < features.length; i++) {
265: if (features[i].getId().equals(cfeature.getId())
266: && features[i].getVersion().equals(
267: cfeature.getVersion()))
268: return false;
269: }
270: return true;
271: }
272:
273: private static boolean isFeaturePatch(IFeature feature) {
274: IFeatureImport[] imports = feature.getImports();
275: for (int i = 0; i < imports.length; i++) {
276: if (imports[i].isPatch())
277: return true;
278: }
279: return false;
280: }
281:
282: private void handleSelectAll() {
283: IStructuredContentProvider provider = (IStructuredContentProvider) fIncludesViewer
284: .getContentProvider();
285: Object[] elements = provider.getElements(fIncludesViewer
286: .getInput());
287: StructuredSelection ssel = new StructuredSelection(elements);
288: fIncludesViewer.setSelection(ssel);
289: }
290:
291: private void handleDelete() {
292: IStructuredSelection ssel = (IStructuredSelection) fIncludesViewer
293: .getSelection();
294:
295: if (ssel.isEmpty())
296: return;
297: IFeatureModel model = (IFeatureModel) getPage().getModel();
298: if (!model.isEditable()) {
299: return;
300: }
301: IFeature feature = model.getFeature();
302:
303: try {
304: IFeatureChild[] removed = new IFeatureChild[ssel.size()];
305: int i = 0;
306: for (Iterator iter = ssel.iterator(); iter.hasNext();) {
307: IFeatureChild iobj = (IFeatureChild) iter.next();
308: removed[i++] = iobj;
309: }
310: feature.removeIncludedFeatures(removed);
311: } catch (CoreException e) {
312: PDEPlugin.logException(e);
313: }
314: }
315:
316: public boolean doGlobalAction(String actionId) {
317: if (actionId.equals(ActionFactory.DELETE.getId())) {
318: BusyIndicator.showWhile(fIncludesViewer.getTable()
319: .getDisplay(), new Runnable() {
320: public void run() {
321: handleDelete();
322: }
323: });
324: return true;
325: }
326: if (actionId.equals(ActionFactory.SELECT_ALL.getId())) {
327: BusyIndicator.showWhile(fIncludesViewer.getTable()
328: .getDisplay(), new Runnable() {
329: public void run() {
330: handleSelectAll();
331: }
332: });
333: return true;
334: }
335: if (actionId.equals(ActionFactory.CUT.getId())) {
336: // delete here and let the editor transfer
337: // the selection to the clipboard
338: handleDelete();
339: return false;
340: }
341: if (actionId.equals(ActionFactory.PASTE.getId())) {
342: doPaste();
343: return true;
344: }
345: return false;
346: }
347:
348: protected void selectionChanged(IStructuredSelection selection) {
349: getPage().getPDEEditor().setSelection(selection);
350: }
351:
352: public void initialize() {
353: IFeatureModel model = (IFeatureModel) getPage().getModel();
354: refresh();
355: getTablePart().setButtonEnabled(0, model.isEditable());
356: model.addModelChangedListener(this );
357: FeatureModelManager mng = PDECore.getDefault()
358: .getFeatureModelManager();
359: mng.addFeatureModelListener(this );
360: }
361:
362: public void modelChanged(IModelChangedEvent e) {
363: if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
364: markStale();
365: return;
366: }
367: Object obj = e.getChangedObjects()[0];
368: if (obj instanceof IFeatureChild) {
369: if (e.getChangeType() == IModelChangedEvent.CHANGE) {
370: fIncludesViewer.update(obj, null);
371: } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
372: fIncludesViewer.add(e.getChangedObjects());
373: if (e.getChangedObjects().length > 0) {
374: fIncludesViewer
375: .setSelection(new StructuredSelection(e
376: .getChangedObjects()[0]));
377: }
378: } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
379: fIncludesViewer.remove(e.getChangedObjects());
380: }
381: }
382: }
383:
384: private void makeActions() {
385: IModel model = (IModel) getPage().getModel();
386: fNewAction = new Action() {
387: public void run() {
388: handleNew();
389: }
390: };
391: fNewAction.setText(PDEUIMessages.Menus_new_label);
392: fNewAction.setEnabled(model.isEditable());
393:
394: fDeleteAction = new Action() {
395: public void run() {
396: BusyIndicator.showWhile(fIncludesViewer.getTable()
397: .getDisplay(), new Runnable() {
398: public void run() {
399: handleDelete();
400: }
401: });
402: }
403: };
404: fDeleteAction.setEnabled(model.isEditable());
405: fDeleteAction.setText(PDEUIMessages.Actions_delete_label);
406: fOpenAction = new OpenReferenceAction(fIncludesViewer);
407: }
408:
409: public void modelsChanged(final IFeatureModelDelta delta) {
410: getSection().getDisplay().asyncExec(new Runnable() {
411: public void run() {
412: if (getSection().isDisposed()) {
413: return;
414: }
415: IFeatureModel[] added = delta.getAdded();
416: IFeatureModel[] removed = delta.getRemoved();
417: IFeatureModel[] changed = delta.getChanged();
418: if (hasModels(added) || hasModels(removed)
419: || hasModels(changed))
420: markStale();
421: }
422: });
423: }
424:
425: private boolean hasModels(IFeatureModel[] models) {
426: if (models == null)
427: return false;
428: IFeatureModel this Model = (IFeatureModel) getPage().getModel();
429: if (this Model == null)
430: return false;
431: for (int i = 0; i < models.length; i++) {
432: if (models[i] != this Model) {
433: return true;
434: }
435: }
436: return false;
437: }
438:
439: public void setFocus() {
440: if (fIncludesViewer != null)
441: fIncludesViewer.getTable().setFocus();
442: }
443:
444: public void refresh() {
445: IFeatureModel model = (IFeatureModel) getPage().getModel();
446: IFeature feature = model.getFeature();
447: fIncludesViewer.setInput(feature);
448: super .refresh();
449: }
450:
451: /**
452: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(Clipboard)
453: */
454: public boolean canPaste(Clipboard clipboard) {
455: Object[] objects = (Object[]) clipboard
456: .getContents(ModelDataTransfer.getInstance());
457: if (objects != null && objects.length > 0) {
458: return canPaste(null, objects);
459: }
460: return false;
461: }
462:
463: /**
464: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(Object,
465: * Object[])
466: */
467: protected boolean canPaste(Object target, Object[] objects) {
468: for (int i = 0; i < objects.length; i++) {
469: if (!(objects[i] instanceof FeatureChild))
470: return false;
471: }
472: return true;
473: }
474:
475: /**
476: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste()
477: */
478: protected void doPaste() {
479: Clipboard clipboard = getPage().getPDEEditor().getClipboard();
480: ModelDataTransfer modelTransfer = ModelDataTransfer
481: .getInstance();
482: Object[] objects = (Object[]) clipboard
483: .getContents(modelTransfer);
484: if (objects != null) {
485: doPaste(null, objects);
486: }
487: }
488:
489: /**
490: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste(Object,
491: * Object[])
492: */
493: protected void doPaste(Object target, Object[] objects) {
494: IFeatureModel model = (IFeatureModel) getPage().getModel();
495: IFeature feature = model.getFeature();
496: if (!model.isEditable()) {
497: return;
498: }
499:
500: FeatureChild[] fChildren = new FeatureChild[objects.length];
501: try {
502: for (int i = 0; i < objects.length; i++) {
503: if (objects[i] instanceof FeatureChild) {
504: FeatureChild fChild = (FeatureChild) objects[i];
505: fChild.setModel(model);
506: fChild.setParent(feature);
507: fChildren[i] = fChild;
508: }
509: }
510: feature.addIncludedFeatures(fChildren);
511: } catch (CoreException e) {
512: PDEPlugin.logException(e);
513: }
514: }
515:
516: void fireSelection() {
517: ISelection sel = fIncludesViewer.getSelection();
518: if (!sel.isEmpty()) {
519: fIncludesViewer
520: .setSelection(fIncludesViewer.getSelection());
521: } else if (fIncludesViewer.getElementAt(0) != null) {
522: fIncludesViewer.setSelection(new StructuredSelection(
523: fIncludesViewer.getElementAt(0)));
524: }
525: }
526:
527: protected boolean createCount() {
528: return true;
529: }
530:
531: }
|