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.plugin;
011:
012: import java.io.BufferedInputStream;
013: import java.io.ByteArrayInputStream;
014: import java.io.InputStream;
015: import java.util.ArrayList;
016: import java.util.HashSet;
017: import java.util.Iterator;
018: import java.util.Vector;
019:
020: import org.eclipse.core.runtime.CoreException;
021: import org.eclipse.jface.action.Action;
022: import org.eclipse.jface.action.IAction;
023: import org.eclipse.jface.action.IMenuManager;
024: import org.eclipse.jface.action.Separator;
025: import org.eclipse.jface.action.ToolBarManager;
026: import org.eclipse.jface.util.IPropertyChangeListener;
027: import org.eclipse.jface.util.PropertyChangeEvent;
028: import org.eclipse.jface.viewers.ISelection;
029: import org.eclipse.jface.viewers.IStructuredSelection;
030: import org.eclipse.jface.viewers.StructuredSelection;
031: import org.eclipse.jface.viewers.TableViewer;
032: import org.eclipse.jface.viewers.ViewerDropAdapter;
033: import org.eclipse.jface.window.Window;
034: import org.eclipse.pde.core.IModel;
035: import org.eclipse.pde.core.IModelChangedEvent;
036: import org.eclipse.pde.core.IModelChangedListener;
037: import org.eclipse.pde.core.plugin.IPlugin;
038: import org.eclipse.pde.core.plugin.IPluginBase;
039: import org.eclipse.pde.core.plugin.IPluginImport;
040: import org.eclipse.pde.core.plugin.IPluginModel;
041: import org.eclipse.pde.core.plugin.IPluginModelBase;
042: import org.eclipse.pde.core.plugin.IPluginModelFactory;
043: import org.eclipse.pde.core.plugin.PluginRegistry;
044: import org.eclipse.pde.internal.core.IPluginModelListener;
045: import org.eclipse.pde.internal.core.PDECore;
046: import org.eclipse.pde.internal.core.PluginModelDelta;
047: import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
048: import org.eclipse.pde.internal.core.bundle.BundlePluginModelBase;
049: import org.eclipse.pde.internal.core.plugin.AbstractPluginModelBase;
050: import org.eclipse.pde.internal.core.plugin.ExternalPluginModel;
051: import org.eclipse.pde.internal.core.plugin.ImportObject;
052: import org.eclipse.pde.internal.core.plugin.PluginBase;
053: import org.eclipse.pde.internal.core.text.plugin.PluginBaseNode;
054: import org.eclipse.pde.internal.core.text.plugin.PluginDocumentNodeFactory;
055: import org.eclipse.pde.internal.ui.PDEPlugin;
056: import org.eclipse.pde.internal.ui.PDEUIMessages;
057: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
058: import org.eclipse.pde.internal.ui.editor.TableSection;
059: import org.eclipse.pde.internal.ui.editor.actions.SortAction;
060: import org.eclipse.pde.internal.ui.elements.DefaultTableProvider;
061: import org.eclipse.pde.internal.ui.parts.TablePart;
062: import org.eclipse.pde.internal.ui.search.PluginSearchActionGroup;
063: import org.eclipse.pde.internal.ui.search.dependencies.UnusedDependenciesAction;
064: import org.eclipse.pde.internal.ui.util.SWTUtil;
065: import org.eclipse.pde.internal.ui.wizards.PluginSelectionDialog;
066: import org.eclipse.swt.SWT;
067: import org.eclipse.swt.events.DisposeEvent;
068: import org.eclipse.swt.events.DisposeListener;
069: import org.eclipse.swt.graphics.Cursor;
070: import org.eclipse.swt.layout.GridData;
071: import org.eclipse.swt.widgets.Composite;
072: import org.eclipse.swt.widgets.Control;
073: import org.eclipse.swt.widgets.Display;
074: import org.eclipse.swt.widgets.Table;
075: import org.eclipse.swt.widgets.TableItem;
076: import org.eclipse.swt.widgets.ToolBar;
077: import org.eclipse.ui.actions.ActionContext;
078: import org.eclipse.ui.actions.ActionFactory;
079: import org.eclipse.ui.forms.widgets.FormToolkit;
080: import org.eclipse.ui.forms.widgets.Section;
081:
082: public class RequiresSection extends TableSection implements
083: IModelChangedListener, IPluginModelListener,
084: IPropertyChangeListener {
085:
086: private static final int ADD_INDEX = 0;
087: private static final int REMOVE_INDEX = 1;
088: private static final int UP_INDEX = 2;
089: private static final int DOWN_INDEX = 3;
090: private static final int PROPERTIES_INDEX = 4;
091:
092: private TableViewer fImportViewer;
093: private Vector fImports;
094: private Action fOpenAction;
095: private Action fAddAction;
096: private Action fRemoveAction;
097: private Action fPropertiesAction;
098: private Action fSortAction;
099:
100: private int fImportInsertIndex;
101:
102: class ImportContentProvider extends DefaultTableProvider {
103: public Object[] getElements(Object parent) {
104: if (fImports == null)
105: createImportObjects();
106: return fImports.toArray();
107: }
108: }
109:
110: public RequiresSection(DependenciesPage page, Composite parent,
111: String[] labels) {
112: super (page, parent, Section.DESCRIPTION, labels);
113: getSection().setText(PDEUIMessages.RequiresSection_title);
114: boolean fragment = ((IPluginModelBase) getPage().getModel())
115: .isFragmentModel();
116: if (fragment)
117: getSection().setDescription(
118: PDEUIMessages.RequiresSection_fDesc);
119: else
120: getSection().setDescription(
121: PDEUIMessages.RequiresSection_desc);
122: getTablePart().setEditable(false);
123: resetImportInsertIndex();
124: }
125:
126: public void createClient(Section section, FormToolkit toolkit) {
127: Composite container = createClientContainer(section, 2, toolkit);
128: createViewerPartControl(container, SWT.MULTI, 2, toolkit);
129: TablePart tablePart = getTablePart();
130: fImportViewer = tablePart.getTableViewer();
131:
132: fImportViewer.setContentProvider(new ImportContentProvider());
133: fImportViewer.setLabelProvider(PDEPlugin.getDefault()
134: .getLabelProvider());
135: toolkit.paintBordersFor(container);
136: makeActions();
137: section.setClient(container);
138: GridData gd = new GridData(GridData.FILL_BOTH);
139: gd.minimumWidth = 250;
140: gd.grabExcessVerticalSpace = true;
141: section.setLayout(FormLayoutFactory.createClearGridLayout(
142: false, 1));
143: section.setLayoutData(gd);
144: section.setText(PDEUIMessages.RequiresSection_title);
145: createSectionToolbar(section, toolkit);
146: initialize();
147: }
148:
149: private void createSectionToolbar(Section section,
150: FormToolkit toolkit) {
151: ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
152: ToolBar toolbar = toolBarManager.createControl(section);
153: final Cursor handCursor = new Cursor(Display.getCurrent(),
154: SWT.CURSOR_HAND);
155: toolbar.setCursor(handCursor);
156: // Cursor needs to be explicitly disposed
157: toolbar.addDisposeListener(new DisposeListener() {
158: public void widgetDisposed(DisposeEvent e) {
159: if ((handCursor != null)
160: && (handCursor.isDisposed() == false)) {
161: handCursor.dispose();
162: }
163: }
164: });
165:
166: // Add sort action to the tool bar
167: fSortAction = new SortAction(fImportViewer,
168: PDEUIMessages.RequiresSection_sortAlpha, null, null,
169: this );
170: toolBarManager.add(fSortAction);
171:
172: toolBarManager.update(true);
173:
174: section.setTextClient(toolbar);
175: }
176:
177: protected void selectionChanged(IStructuredSelection sel) {
178: getPage().getPDEEditor().setSelection(sel);
179: updateButtons();
180: }
181:
182: private void updateButtons() {
183: Table table = getTablePart().getTableViewer().getTable();
184: TableItem[] selection = table.getSelection();
185: boolean hasSelection = selection.length > 0;
186: TablePart tablePart = getTablePart();
187: tablePart.setButtonEnabled(ADD_INDEX, isEditable());
188: updateUpDownButtons();
189: if (isBundle())
190: tablePart.setButtonEnabled(PROPERTIES_INDEX,
191: selection.length == 1);
192: tablePart.setButtonEnabled(REMOVE_INDEX, isEditable()
193: && hasSelection);
194: }
195:
196: private void updateUpDownButtons() {
197: TablePart tablePart = getTablePart();
198: if (fSortAction.isChecked()) {
199: tablePart.setButtonEnabled(UP_INDEX, false);
200: tablePart.setButtonEnabled(DOWN_INDEX, false);
201: return;
202: }
203: Table table = getTablePart().getTableViewer().getTable();
204: TableItem[] selection = table.getSelection();
205: boolean hasSelection = selection.length > 0;
206: boolean canMove = table.getItemCount() > 1
207: && selection.length == 1;
208:
209: tablePart.setButtonEnabled(UP_INDEX, canMove && isEditable()
210: && hasSelection && table.getSelectionIndex() > 0);
211: tablePart
212: .setButtonEnabled(DOWN_INDEX, canMove
213: && hasSelection
214: && isEditable()
215: && table.getSelectionIndex() < table
216: .getItemCount() - 1);
217: }
218:
219: protected void handleDoubleClick(IStructuredSelection sel) {
220: handleOpen(sel);
221: }
222:
223: protected void buttonSelected(int index) {
224: switch (index) {
225: case ADD_INDEX:
226: handleAdd();
227: break;
228: case REMOVE_INDEX:
229: handleRemove();
230: break;
231: case UP_INDEX:
232: handleUp();
233: break;
234: case DOWN_INDEX:
235: handleDown();
236: break;
237: case PROPERTIES_INDEX:
238: handleOpenProperties();
239: break;
240: }
241: }
242:
243: private void handleOpenProperties() {
244: Object changeObject = ((IStructuredSelection) fImportViewer
245: .getSelection()).getFirstElement();
246: IPluginImport importObject = ((ImportObject) changeObject)
247: .getImport();
248:
249: DependencyPropertiesDialog dialog = new DependencyPropertiesDialog(
250: isEditable(), importObject);
251: dialog.create();
252: SWTUtil.setDialogSize(dialog, 400, -1);
253: dialog.setTitle(importObject.getId());
254: if (dialog.open() == Window.OK && isEditable()) {
255: try {
256: importObject.setOptional(dialog.isOptional());
257: importObject.setReexported(dialog.isReexported());
258: importObject.setVersion(dialog.getVersion());
259: } catch (CoreException e) {
260: PDEPlugin.logException(e);
261: }
262: }
263: }
264:
265: public void dispose() {
266: IPluginModelBase model = (IPluginModelBase) getPage()
267: .getModel();
268: if (model != null)
269: model.removeModelChangedListener(this );
270: PDECore.getDefault().getModelManager()
271: .removePluginModelListener(this );
272: super .dispose();
273: }
274:
275: /* (non-Javadoc)
276: * @see org.eclipse.pde.internal.ui.editor.PDESection#doGlobalAction(java.lang.String)
277: */
278: public boolean doGlobalAction(String actionId) {
279:
280: if (!isEditable()) {
281: return false;
282: }
283:
284: if (actionId.equals(ActionFactory.DELETE.getId())) {
285: handleRemove();
286: return true;
287: }
288: if (actionId.equals(ActionFactory.CUT.getId())) {
289: // delete here and let the editor transfer
290: // the selection to the clipboard
291: handleRemove();
292: return false;
293: }
294: if (actionId.equals(ActionFactory.PASTE.getId())) {
295: doPaste();
296: return true;
297: }
298: return false;
299: }
300:
301: /* (non-Javadoc)
302: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canPaste(java.lang.Object, java.lang.Object[])
303: */
304: protected boolean canPaste(Object targetObject,
305: Object[] sourceObjects) {
306: HashSet existingImportsSet = null;
307: // Only import objects that are not already existing imports can be
308: // pasted
309: for (int i = 0; i < sourceObjects.length; i++) {
310: // Only import objects allowed
311: if ((sourceObjects[i] instanceof ImportObject) == false) {
312: return false;
313: }
314: // Get the current import objects and store them for searching
315: // purposes
316: if (existingImportsSet == null) {
317: existingImportsSet = PluginSelectionDialog
318: .getExistingImports(getModel(), false);
319: }
320: // Only import object that do not exist are allowed
321: ImportObject importObject = (ImportObject) sourceObjects[i];
322: if (existingImportsSet.contains(importObject.getImport()
323: .getId())) {
324: return false;
325: }
326: }
327: return true;
328: }
329:
330: /* (non-Javadoc)
331: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doPaste(java.lang.Object, java.lang.Object[])
332: */
333: protected void doPaste(Object targetObject, Object[] sourceObjects) {
334: // Get the model
335: IPluginModelBase model = getModel();
336: IPluginBase pluginBase = model.getPluginBase();
337: try {
338: // Paste all source objects
339: for (int i = 0; i < sourceObjects.length; i++) {
340: Object sourceObject = sourceObjects[i];
341: if (sourceObject instanceof ImportObject) {
342: // Import object
343: ImportObject importObject = (ImportObject) sourceObject;
344: // Adjust all the source object transient field values to
345: // acceptable values
346: // TODO: MP: CCP: Remove unnecessary reconnected Plugin attributes
347: // This may not be necessary. The model object is discarded when
348: // the import object wrapping the plugin import object is converted
349: // into a require bundle object
350: importObject.reconnect(model);
351: // Add the import object to the plugin
352: pluginBase.add(importObject.getImport());
353: }
354: }
355: } catch (CoreException e) {
356: PDEPlugin.logException(e);
357: }
358: }
359:
360: /**
361: * @return
362: */
363: private IPluginModelBase getModel() {
364: return (IPluginModelBase) getPage().getModel();
365: }
366:
367: public boolean setFormInput(Object object) {
368: if (object instanceof IPluginImport) {
369: ImportObject iobj = new ImportObject((IPluginImport) object);
370: fImportViewer.setSelection(new StructuredSelection(iobj),
371: true);
372: return true;
373: }
374: return false;
375: }
376:
377: protected void fillContextMenu(IMenuManager manager) {
378: ISelection selection = fImportViewer.getSelection();
379: manager.add(fAddAction);
380: if (!selection.isEmpty()) {
381: manager.add(fOpenAction);
382: }
383: manager.add(new Separator());
384: getPage().contextMenuAboutToShow(manager);
385:
386: if (!selection.isEmpty())
387: manager.add(fRemoveAction);
388: getPage().getPDEEditor().getContributor()
389: .contextMenuAboutToShow(manager);
390: manager.add(new Separator());
391:
392: PluginSearchActionGroup actionGroup = new PluginSearchActionGroup();
393: actionGroup.setContext(new ActionContext(selection));
394: actionGroup.fillContextMenu(manager);
395: if (((IModel) getPage().getModel()).getUnderlyingResource() != null) {
396: manager.add(new UnusedDependenciesAction(
397: (IPluginModelBase) getPage().getModel(), false));
398: }
399: if (fPropertiesAction != null
400: && !fImportViewer.getSelection().isEmpty()) {
401: manager.add(new Separator());
402: manager.add(fPropertiesAction);
403: }
404: }
405:
406: private void handleOpen(ISelection sel) {
407: if (sel instanceof IStructuredSelection) {
408: IStructuredSelection ssel = (IStructuredSelection) sel;
409: if (ssel.size() == 1) {
410: Object obj = ssel.getFirstElement();
411: if (obj instanceof ImportObject) {
412: IPlugin plugin = ((ImportObject) obj).getPlugin();
413: if (plugin != null)
414: ManifestEditor.open(plugin, false);
415: }
416: }
417: }
418: }
419:
420: private void handleRemove() {
421: IStructuredSelection ssel = (IStructuredSelection) fImportViewer
422: .getSelection();
423: IPluginModelBase model = (IPluginModelBase) getPage()
424: .getModel();
425: IPluginBase pluginBase = model.getPluginBase();
426: IPluginImport[] imports = new IPluginImport[ssel.size()];
427: int i = 0;
428: for (Iterator iter = ssel.iterator(); iter.hasNext(); i++)
429: imports[i] = ((ImportObject) iter.next()).getImport();
430:
431: try {
432: removeImports(pluginBase, imports);
433: } catch (CoreException e) {
434: PDEPlugin.logException(e);
435: }
436: updateButtons();
437: }
438:
439: private void removeImports(IPluginBase base, IPluginImport[] imports)
440: throws CoreException {
441: if (base instanceof BundlePluginBase)
442: ((BundlePluginBase) base).remove(imports);
443: else if (base instanceof PluginBase)
444: ((PluginBase) base).remove(imports);
445: else if (base instanceof PluginBaseNode)
446: ((PluginBaseNode) base).remove(imports);
447: }
448:
449: private void handleAdd() {
450: IPluginModelBase model = (IPluginModelBase) getPage()
451: .getModel();
452: PluginSelectionDialog dialog = new PluginSelectionDialog(
453: PDEPlugin.getActiveWorkbenchShell(),
454: getAvailablePlugins(model), true);
455: dialog.create();
456: if (dialog.open() == Window.OK) {
457: Object[] models = dialog.getResult();
458: IPluginImport[] imports = new IPluginImport[models.length];
459: try {
460: for (int i = 0; i < models.length; i++) {
461: IPluginModel candidate = (IPluginModel) models[i];
462: String pluginId = candidate.getPlugin().getId();
463: IPluginImport importNode = createImport(model
464: .getPluginFactory(), pluginId);
465: imports[i] = importNode;
466: }
467: addImports(model.getPluginBase(), imports);
468: } catch (CoreException e) {
469: }
470: }
471: }
472:
473: private IPluginImport createImport(IPluginModelFactory factory,
474: String id) {
475: if (factory instanceof AbstractPluginModelBase)
476: return ((AbstractPluginModelBase) factory).createImport(id);
477: else if (factory instanceof BundlePluginModelBase)
478: return ((BundlePluginModelBase) factory).createImport(id);
479: else if (factory instanceof PluginDocumentNodeFactory)
480: return ((PluginDocumentNodeFactory) factory)
481: .createImport(id);
482: return null;
483: }
484:
485: private void addImports(IPluginBase base, IPluginImport[] imports)
486: throws CoreException {
487: if (base instanceof BundlePluginBase)
488: ((BundlePluginBase) base).add(imports);
489: else if (base instanceof PluginBase)
490: ((PluginBase) base).add(imports);
491: else if (base instanceof PluginBaseNode)
492: ((PluginBaseNode) base).add(imports);
493: }
494:
495: private void handleUp() {
496: int index = getTablePart().getTableViewer().getTable()
497: .getSelectionIndex();
498: if (index < 1)
499: return;
500: swap(index, index - 1);
501: }
502:
503: private void handleDown() {
504: Table table = getTablePart().getTableViewer().getTable();
505: int index = table.getSelectionIndex();
506: if (index == table.getItemCount() - 1)
507: return;
508: swap(index, index + 1);
509: }
510:
511: public void swap(int index1, int index2) {
512: Table table = getTablePart().getTableViewer().getTable();
513: IPluginImport dep1 = ((ImportObject) table.getItem(index1)
514: .getData()).getImport();
515: IPluginImport dep2 = ((ImportObject) table.getItem(index2)
516: .getData()).getImport();
517:
518: try {
519: IPluginModelBase model = (IPluginModelBase) getPage()
520: .getModel();
521: IPluginBase pluginBase = model.getPluginBase();
522: pluginBase.swap(dep1, dep2);
523: } catch (CoreException e) {
524: PDEPlugin.logException(e);
525: }
526: }
527:
528: private IPluginModelBase[] getAvailablePlugins(
529: IPluginModelBase model) {
530: IPluginModelBase[] plugins = PluginRegistry
531: .getActiveModels(false);
532: HashSet existingImports = PluginSelectionDialog
533: .getExistingImports(model, false);
534: ArrayList result = new ArrayList();
535: for (int i = 0; i < plugins.length; i++) {
536: if (!existingImports.contains(plugins[i].getPluginBase()
537: .getId())) {
538: result.add(plugins[i]);
539: }
540: }
541:
542: if (!existingImports.contains("system.bundle")) //$NON-NLS-1$
543: addSystemBundle(result);
544: return (IPluginModelBase[]) result
545: .toArray(new IPluginModelBase[result.size()]);
546: }
547:
548: private void addSystemBundle(java.util.List list) {
549: try {
550: ExternalPluginModel model = new ExternalPluginModel();
551:
552: // Need Install Location to load model. Giving it org.eclipse.osgi's install location
553: IPluginModelBase osgi = PluginRegistry
554: .findModel("org.eclipse.osgi"); //$NON-NLS-1$
555: if (osgi == null)
556: return;
557: model.setInstallLocation(osgi.getInstallLocation());
558:
559: // Load model from a String representing the contents of an equivalent plugin.xml file
560: String pluginInfo = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><plugin id=\"system.bundle\" name=\"System Bundle\"></plugin>"; //$NON-NLS-1$
561: InputStream is = new BufferedInputStream(
562: new ByteArrayInputStream(pluginInfo.getBytes()));
563: model.load(is, false);
564:
565: list.add(model);
566:
567: } catch (CoreException e) {
568: }
569: }
570:
571: public void initialize() {
572: IPluginModelBase model = (IPluginModelBase) getPage()
573: .getModel();
574: if (model == null)
575: return;
576: fImportViewer.setInput(model.getPluginBase());
577: updateButtons();
578: model.addModelChangedListener(this );
579: PDECore.getDefault().getModelManager().addPluginModelListener(
580: this );
581: fAddAction.setEnabled(model.isEditable());
582: fRemoveAction.setEnabled(model.isEditable());
583: }
584:
585: private void makeActions() {
586: fAddAction = new Action(PDEUIMessages.RequiresSection_add) {
587: public void run() {
588: handleAdd();
589: }
590: };
591: fOpenAction = new Action(PDEUIMessages.RequiresSection_open) {
592: public void run() {
593: handleOpen(fImportViewer.getSelection());
594: }
595: };
596: fRemoveAction = new Action(PDEUIMessages.RequiresSection_delete) {
597: public void run() {
598: handleRemove();
599: }
600: };
601: if (isBundle()) {
602: fPropertiesAction = new Action(
603: PDEUIMessages.RequiresSection_properties) {
604: public void run() {
605: handleOpenProperties();
606: }
607: };
608: }
609: }
610:
611: public void refresh() {
612: fImports = null;
613: fImportViewer.refresh();
614: super .refresh();
615: }
616:
617: public void modelChanged(IModelChangedEvent event) {
618: if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
619: markStale();
620: return;
621: }
622: if (event.getChangedProperty() == IPluginBase.P_IMPORT_ORDER) {
623: refresh();
624: updateButtons();
625: return;
626: }
627:
628: Object[] changedObjects = event.getChangedObjects();
629: if (changedObjects[0] instanceof IPluginImport) {
630: int index = 0;
631: for (int i = 0; i < changedObjects.length; i++) {
632: Object changeObject = changedObjects[i];
633: IPluginImport iimport = (IPluginImport) changeObject;
634: if (event.getChangeType() == IModelChangedEvent.INSERT) {
635: ImportObject iobj = new ImportObject(iimport);
636: if (fImports == null) {
637: // createImportObjects method will find new addition
638: createImportObjects();
639: } else {
640: int insertIndex = getImportInsertIndex();
641: if (insertIndex < 0) {
642: // Add Button
643: fImports.add(iobj);
644: } else {
645: // DND
646: fImports.add(insertIndex, iobj);
647: }
648: }
649: } else {
650: ImportObject iobj = findImportObject(iimport);
651: if (iobj != null) {
652: if (event.getChangeType() == IModelChangedEvent.REMOVE) {
653: if (fImports == null)
654: // createImportObjects method will not include the removed import
655: createImportObjects();
656: else
657: fImports.remove(iobj);
658: Table table = fImportViewer.getTable();
659: index = table.getSelectionIndex();
660: fImportViewer.remove(iobj);
661: } else {
662: fImportViewer.update(iobj, null);
663: }
664: }
665: }
666: }
667: if (event.getChangeType() == IModelChangedEvent.INSERT) {
668: if (changedObjects.length > 0) {
669: // Refresh the viewer
670: fImportViewer.refresh();
671: // Get the last import added to the viewer
672: IPluginImport lastImport = (IPluginImport) changedObjects[changedObjects.length - 1];
673: // Find the corresponding bundle object for the plug-in import
674: ImportObject lastImportObject = findImportObject(lastImport);
675: if (lastImportObject != null) {
676: fImportViewer
677: .setSelection(new StructuredSelection(
678: lastImportObject));
679: }
680: fImportViewer.getTable().setFocus();
681: }
682: } else if (event.getChangeType() == IModelChangedEvent.REMOVE) {
683: Table table = fImportViewer.getTable();
684: table.setSelection(index < table.getItemCount() ? index
685: : table.getItemCount() - 1);
686: }
687: } else {
688: fImportViewer.update(((IStructuredSelection) fImportViewer
689: .getSelection()).toArray(), null);
690: }
691: }
692:
693: public void modelsChanged(PluginModelDelta delta) {
694: fImports = null;
695: final Control control = fImportViewer.getControl();
696: if (!control.isDisposed()) {
697: control.getDisplay().asyncExec(new Runnable() {
698: public void run() {
699: if (!control.isDisposed())
700: fImportViewer.refresh();
701: }
702: });
703: }
704: }
705:
706: private ImportObject findImportObject(IPluginImport iimport) {
707: if (fImports == null)
708: return null;
709: for (int i = 0; i < fImports.size(); i++) {
710: ImportObject iobj = (ImportObject) fImports.get(i);
711: if (iobj.getImport().equals(iimport))
712: return iobj;
713: }
714: return null;
715: }
716:
717: private void createImportObjects() {
718: fImports = new Vector();
719: IPluginModelBase model = (IPluginModelBase) getPage()
720: .getModel();
721: IPluginImport[] iimports = model.getPluginBase().getImports();
722: for (int i = 0; i < iimports.length; i++) {
723: IPluginImport iimport = iimports[i];
724: fImports.add(new ImportObject(iimport));
725: }
726: }
727:
728: public void setFocus() {
729: if (fImportViewer != null)
730: fImportViewer.getTable().setFocus();
731: }
732:
733: private boolean isBundle() {
734: return getPage().getPDEEditor().getContextManager()
735: .findContext(BundleInputContext.CONTEXT_ID) != null;
736: }
737:
738: protected boolean createCount() {
739: return true;
740: }
741:
742: public void propertyChange(PropertyChangeEvent event) {
743: if (fSortAction.equals(event.getSource())
744: && IAction.RESULT.equals(event.getProperty())) {
745: updateUpDownButtons();
746: }
747: }
748:
749: /* (non-Javadoc)
750: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#isDragAndDropEnabled()
751: */
752: protected boolean isDragAndDropEnabled() {
753: return true;
754: }
755:
756: /* (non-Javadoc)
757: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canDragMove(java.lang.Object[])
758: */
759: public boolean canDragMove(Object[] sourceObjects) {
760: if (validateDragMoveSanity(sourceObjects) == false) {
761: return false;
762: } else if (isTreeViewerSorted()) {
763: return false;
764: }
765: return true;
766: }
767:
768: /**
769: * @param sourceObjects
770: * @return
771: */
772: private boolean validateDragMoveSanity(Object[] sourceObjects) {
773: // Validate source
774: if (sourceObjects == null) {
775: // No objects
776: return false;
777: } else if (sourceObjects.length != 1) {
778: // Multiple selection not supported
779: return false;
780: } else if ((sourceObjects[0] instanceof ImportObject) == false) {
781: // Must be the right type
782: return false;
783: }
784: return true;
785: }
786:
787: /**
788: * @param targetObject
789: * @param sourceObjects
790: * @return
791: */
792: private boolean validateDropMoveSanity(Object targetObject,
793: Object[] sourceObjects) {
794: // Validate target object
795: if ((targetObject instanceof ImportObject) == false) {
796: return false;
797: }
798: // Validate source objects
799: if (validateDragMoveSanity(sourceObjects) == false) {
800: return false;
801: }
802: return true;
803: }
804:
805: /**
806: * @param sourceImportObject
807: * @param targetImportObject
808: * @return
809: */
810: private boolean validateDropMoveModel(
811: ImportObject sourceImportObject,
812: ImportObject targetImportObject) {
813: // Objects have to be from the same model
814: IPluginModelBase sourceModel = sourceImportObject.getImport()
815: .getPluginModel();
816: IPluginModelBase targetModel = targetImportObject.getImport()
817: .getPluginModel();
818: if (sourceModel.equals(targetModel) == false) {
819: return false;
820: } else if ((getModel().getPluginBase() instanceof BundlePluginBase) == false) {
821: return false;
822: }
823: return true;
824: }
825:
826: /* (non-Javadoc)
827: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#canDropMove(java.lang.Object, java.lang.Object[], int)
828: */
829: public boolean canDropMove(Object targetObject,
830: Object[] sourceObjects, int targetLocation) {
831: // Sanity check
832: if (validateDropMoveSanity(targetObject, sourceObjects) == false) {
833: return false;
834: }
835: // Multiple selection not supported
836: ImportObject sourceImportObject = (ImportObject) sourceObjects[0];
837: ImportObject targetImportObject = (ImportObject) targetObject;
838: IPluginImport sourcePluginImport = sourceImportObject
839: .getImport();
840: IPluginImport targetPluginImport = targetImportObject
841: .getImport();
842: // Validate model
843: if (validateDropMoveModel(sourceImportObject,
844: targetImportObject) == false) {
845: return false;
846: }
847: // Get the bundle plug-in base
848: BundlePluginBase bundlePluginBase = (BundlePluginBase) getModel()
849: .getPluginBase();
850: // Validate move
851: if (targetLocation == ViewerDropAdapter.LOCATION_BEFORE) {
852: // Get the previous import of the target
853: IPluginImport previousImport = bundlePluginBase
854: .getPreviousImport(targetPluginImport);
855: // Ensure the previous element is not the source
856: if (sourcePluginImport.equals(previousImport)) {
857: return false;
858: }
859: return true;
860: } else if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
861: // Get the next import of the target
862: IPluginImport nextImport = bundlePluginBase
863: .getNextImport(targetPluginImport);
864: // Ensure the next import is not the source
865: if (sourcePluginImport.equals(nextImport)) {
866: return false;
867: }
868: return true;
869: } else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
870: // Not supported
871: return false;
872: }
873: return false;
874: }
875:
876: /* (non-Javadoc)
877: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#doDropMove(java.lang.Object, java.lang.Object[], int)
878: */
879: public void doDropMove(Object targetObject, Object[] sourceObjects,
880: int targetLocation) {
881: // Sanity check
882: if (validateDropMoveSanity(targetObject, sourceObjects) == false) {
883: Display.getDefault().beep();
884: return;
885: }
886: // Multiple selection not supported
887: ImportObject sourceImportObject = (ImportObject) sourceObjects[0];
888: ImportObject targetImportObject = (ImportObject) targetObject;
889: IPluginImport sourcePluginImport = sourceImportObject
890: .getImport();
891: IPluginImport targetPluginImport = targetImportObject
892: .getImport();
893: // Validate move
894: if ((targetLocation == ViewerDropAdapter.LOCATION_BEFORE)
895: || (targetLocation == ViewerDropAdapter.LOCATION_AFTER)) {
896: // Do move
897: doDropMove(sourceImportObject, sourcePluginImport,
898: targetPluginImport, targetLocation);
899: } else if (targetLocation == ViewerDropAdapter.LOCATION_ON) {
900: // Not supported
901: }
902: }
903:
904: /**
905: * @param sourceImportObject
906: * @param sourcePluginImport
907: * @param targetPluginImport
908: * @param targetLocation
909: */
910: private void doDropMove(ImportObject sourceImportObject,
911: IPluginImport sourcePluginImport,
912: IPluginImport targetPluginImport, int targetLocation) {
913: // Remove the original source object
914: // Normally we remove the original source object after inserting the
915: // serialized source object; however, the imports are removed via ID
916: // and having both objects with the same ID co-existing will confound
917: // the remove operation
918: doDragRemove();
919: // Get the bundle plug-in base
920: BundlePluginBase bundlePluginBase = (BundlePluginBase) getModel()
921: .getPluginBase();
922: // Get the index of the target
923: int index = bundlePluginBase.getIndexOf(targetPluginImport);
924: // Ensure the target index was found
925: if (index == -1) {
926: return;
927: }
928: // Determine the location index
929: int targetIndex = index;
930: if (targetLocation == ViewerDropAdapter.LOCATION_AFTER) {
931: targetIndex++;
932: }
933: // Adjust all the source object transient field values to
934: // acceptable values
935: sourceImportObject.reconnect(getModel());
936: // Store index so that the import can be inserted properly into
937: // the table viewer
938: setImportInsertIndex(targetIndex);
939: // Add source as sibling of target
940: bundlePluginBase.add(sourcePluginImport, targetIndex);
941: // Reset the index
942: resetImportInsertIndex();
943: }
944:
945: /**
946: *
947: */
948: private void resetImportInsertIndex() {
949: fImportInsertIndex = -1;
950: }
951:
952: /**
953: * @param index
954: */
955: private void setImportInsertIndex(int index) {
956: fImportInsertIndex = index;
957: }
958:
959: /**
960: * @return
961: */
962: private int getImportInsertIndex() {
963: return fImportInsertIndex;
964: }
965:
966: /**
967: *
968: */
969: private void doDragRemove() {
970: // Get the bundle plug-in base
971: BundlePluginBase bundlePluginBase = (BundlePluginBase) getModel()
972: .getPluginBase();
973: // Retrieve the original non-serialized source objects dragged initially
974: Object[] sourceObjects = getDragSourceObjects();
975: // Validate source objects
976: if (validateDragMoveSanity(sourceObjects) == false) {
977: return;
978: }
979: IPluginImport sourcePluginImport = ((ImportObject) sourceObjects[0])
980: .getImport();
981: try {
982: bundlePluginBase.remove(sourcePluginImport);
983: } catch (CoreException e) {
984: PDEPlugin.logException(e);
985: }
986: }
987:
988: /**
989: * @return
990: */
991: private boolean isTreeViewerSorted() {
992: if (fSortAction == null) {
993: return false;
994: }
995: return fSortAction.isChecked();
996: }
997:
998: }
|