001: /*******************************************************************************
002: * Copyright (c) 2005, 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.product;
011:
012: import java.util.ArrayList;
013:
014: import org.eclipse.jface.action.Action;
015: import org.eclipse.jface.action.IAction;
016: import org.eclipse.jface.action.IMenuManager;
017: import org.eclipse.jface.action.Separator;
018: import org.eclipse.jface.action.ToolBarManager;
019: import org.eclipse.jface.util.IPropertyChangeListener;
020: import org.eclipse.jface.util.PropertyChangeEvent;
021: import org.eclipse.jface.viewers.ISelection;
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.jface.wizard.WizardDialog;
027: import org.eclipse.pde.core.IModelChangedEvent;
028: import org.eclipse.pde.internal.core.FeatureModelManager;
029: import org.eclipse.pde.internal.core.PDECore;
030: import org.eclipse.pde.internal.core.ifeature.IFeature;
031: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
032: import org.eclipse.pde.internal.core.iproduct.IProduct;
033: import org.eclipse.pde.internal.core.iproduct.IProductFeature;
034: import org.eclipse.pde.internal.core.iproduct.IProductModel;
035: import org.eclipse.pde.internal.core.iproduct.IProductModelFactory;
036: import org.eclipse.pde.internal.ui.PDEPlugin;
037: import org.eclipse.pde.internal.ui.PDEUIMessages;
038: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
039: import org.eclipse.pde.internal.ui.editor.PDEFormPage;
040: import org.eclipse.pde.internal.ui.editor.TableSection;
041: import org.eclipse.pde.internal.ui.editor.actions.SortAction;
042: import org.eclipse.pde.internal.ui.editor.feature.FeatureEditor;
043: import org.eclipse.pde.internal.ui.elements.DefaultTableProvider;
044: import org.eclipse.pde.internal.ui.parts.TablePart;
045: import org.eclipse.pde.internal.ui.util.SWTUtil;
046: import org.eclipse.pde.internal.ui.wizards.FeatureSelectionDialog;
047: import org.eclipse.pde.internal.ui.wizards.feature.NewFeatureProjectWizard;
048: import org.eclipse.swt.SWT;
049: import org.eclipse.swt.events.DisposeEvent;
050: import org.eclipse.swt.events.DisposeListener;
051: import org.eclipse.swt.graphics.Cursor;
052: import org.eclipse.swt.layout.GridData;
053: import org.eclipse.swt.widgets.Composite;
054: import org.eclipse.swt.widgets.Display;
055: import org.eclipse.swt.widgets.Table;
056: import org.eclipse.swt.widgets.TableItem;
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 FeatureSection extends TableSection implements
063: IPropertyChangeListener {
064:
065: private SortAction fSortAction;
066:
067: class ContentProvider extends DefaultTableProvider {
068: public Object[] getElements(Object parent) {
069: return getProduct().getFeatures();
070: }
071: }
072:
073: private TableViewer fFeatureTable;
074:
075: public FeatureSection(PDEFormPage formPage, Composite parent) {
076: super (formPage, parent, Section.DESCRIPTION, getButtonLabels());
077: }
078:
079: private static String[] getButtonLabels() {
080: String[] labels = new String[8];
081: labels[0] = PDEUIMessages.Product_FeatureSection_add;
082: labels[1] = PDEUIMessages.Product_FeatureSection_remove;
083: labels[2] = PDEUIMessages.Product_PluginSection_removeAll;
084: labels[3] = PDEUIMessages.Product_FeatureSection_up;
085: labels[4] = PDEUIMessages.Product_FeatureSection_down;
086: labels[5] = null;
087: labels[6] = null;
088: labels[7] = PDEUIMessages.Product_FeatureSection_newFeature;
089: return labels;
090: }
091:
092: /* (non-Javadoc)
093: * @see org.eclipse.pde.internal.ui.editor.PDESection#createClient(org.eclipse.ui.forms.widgets.Section, org.eclipse.ui.forms.widgets.FormToolkit)
094: */
095: protected void createClient(Section section, FormToolkit toolkit) {
096:
097: section.setLayout(FormLayoutFactory.createClearGridLayout(
098: false, 1));
099: GridData sectionData = new GridData(GridData.FILL_BOTH);
100: sectionData.verticalSpan = 2;
101: section.setLayoutData(sectionData);
102:
103: Composite container = createClientContainer(section, 2, toolkit);
104: createViewerPartControl(container, SWT.MULTI, 2, toolkit);
105: container.setLayoutData(new GridData(GridData.FILL_BOTH));
106:
107: TablePart tablePart = getTablePart();
108: fFeatureTable = tablePart.getTableViewer();
109: fFeatureTable.setContentProvider(new ContentProvider());
110: fFeatureTable.setLabelProvider(PDEPlugin.getDefault()
111: .getLabelProvider());
112: fFeatureTable.setSorter(null);
113: GridData data = (GridData) tablePart.getControl()
114: .getLayoutData();
115: data.minimumWidth = 200;
116: fFeatureTable.setInput(PDECore.getDefault()
117: .getFeatureModelManager());
118:
119: tablePart.setButtonEnabled(0, isEditable());
120:
121: // remove buttons updated on refresh
122:
123: tablePart.setButtonEnabled(3, isEditable());
124: tablePart.setButtonEnabled(4, isEditable());
125: tablePart.setButtonEnabled(7, isEditable());
126:
127: toolkit.paintBordersFor(container);
128: section.setClient(container);
129:
130: section.setText(PDEUIMessages.Product_FeatureSection_title);
131: section
132: .setDescription(PDEUIMessages.Product_FeatureSection_desc); //
133:
134: getModel().addModelChangedListener(this );
135: createSectionToolbar(section, toolkit);
136: }
137:
138: /**
139: * @param section
140: * @param toolkit
141: */
142: private void createSectionToolbar(Section section,
143: FormToolkit toolkit) {
144: ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
145: ToolBar toolbar = toolBarManager.createControl(section);
146: final Cursor handCursor = new Cursor(Display.getCurrent(),
147: SWT.CURSOR_HAND);
148: toolbar.setCursor(handCursor);
149: // Cursor needs to be explicitly disposed
150: toolbar.addDisposeListener(new DisposeListener() {
151: public void widgetDisposed(DisposeEvent e) {
152: if ((handCursor != null)
153: && (handCursor.isDisposed() == false)) {
154: handCursor.dispose();
155: }
156: }
157: });
158: // Add sort action to the tool bar
159: fSortAction = new SortAction(fFeatureTable,
160: PDEUIMessages.Product_FeatureSection_sortAlpha, null,
161: null, this );
162: toolBarManager.add(fSortAction);
163: toolBarManager.update(true);
164:
165: section.setTextClient(toolbar);
166: }
167:
168: /* (non-Javadoc)
169: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#buttonSelected(int)
170: */
171: protected void buttonSelected(int index) {
172: switch (index) {
173: case 0:
174: handleAdd();
175: break;
176: case 1:
177: handleDelete();
178: break;
179: case 2:
180: handleRemoveAll();
181: break;
182: case 3:
183: handleUp();
184: break;
185: case 4:
186: handleDown();
187: break;
188: case 7:
189: handleNewFeature();
190: }
191: }
192:
193: private void handleNewFeature() {
194: NewFeatureProjectWizard wizard = new NewFeatureProjectWizard();
195: WizardDialog dialog = new WizardDialog(PDEPlugin
196: .getActiveWorkbenchShell(), wizard);
197: dialog.create();
198: SWTUtil.setDialogSize(dialog, 400, 500);
199: if (dialog.open() == Window.OK) {
200: addFeature(wizard.getFeatureId(), wizard
201: .getFeatureVersion());
202: }
203: }
204:
205: private void addFeature(String id, String version) {
206: IProduct product = getProduct();
207: IProductModelFactory factory = product.getModel().getFactory();
208: IProductFeature feature = factory.createFeature();
209: feature.setId(id);
210: feature.setVersion(version);
211: product.addFeatures(new IProductFeature[] { feature });
212: }
213:
214: private void handleRemoveAll() {
215: IProduct product = getProduct();
216: product.removeFeatures(product.getFeatures());
217: }
218:
219: /* (non-Javadoc)
220: * @see org.eclipse.pde.internal.ui.editor.TableSection#handleDoubleClick(org.eclipse.jface.viewers.IStructuredSelection)
221: */
222: protected void handleDoubleClick(IStructuredSelection selection) {
223: handleOpen(selection);
224: }
225:
226: /* (non-Javadoc)
227: * @see org.eclipse.ui.forms.AbstractFormPart#dispose()
228: */
229: public void dispose() {
230: IProductModel model = getModel();
231: if (model != null)
232: model.removeModelChangedListener(this );
233: super .dispose();
234: }
235:
236: /* (non-Javadoc)
237: * @see org.eclipse.pde.internal.ui.editor.PDESection#doGlobalAction(java.lang.String)
238: */
239: public boolean doGlobalAction(String actionId) {
240: if (actionId.equals(ActionFactory.DELETE.getId())) {
241: handleDelete();
242: return true;
243: }
244: if (actionId.equals(ActionFactory.CUT.getId())) {
245: handleDelete();
246: return false;
247: }
248: if (actionId.equals(ActionFactory.PASTE.getId())) {
249: doPaste();
250: return true;
251: }
252: return false;
253: }
254:
255: protected boolean canPaste(Object target, Object[] objects) {
256: for (int i = 0; i < objects.length; i++) {
257: if (objects[i] instanceof IProductFeature)
258: return true;
259: }
260: return false;
261: }
262:
263: protected void doPaste(Object target, Object[] objects) {
264: IProductFeature[] features;
265: if (objects instanceof IProductFeature[])
266: features = (IProductFeature[]) objects;
267: else {
268: features = new IProductFeature[objects.length];
269: for (int i = 0; i < objects.length; i++)
270: if (objects[i] instanceof IProductFeature)
271: features[i] = (IProductFeature) objects[i];
272: }
273: getProduct().addFeatures(features);
274: }
275:
276: private void handleDelete() {
277: IStructuredSelection ssel = (IStructuredSelection) fFeatureTable
278: .getSelection();
279: if (ssel.size() > 0) {
280: Object[] objects = ssel.toArray();
281: IProductFeature[] features = new IProductFeature[objects.length];
282: System.arraycopy(objects, 0, features, 0, objects.length);
283: getProduct().removeFeatures(features);
284: }
285: }
286:
287: /* (non-Javadoc)
288: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#fillContextMenu(org.eclipse.jface.action.IMenuManager)
289: */
290: protected void fillContextMenu(IMenuManager manager) {
291: IStructuredSelection ssel = (IStructuredSelection) fFeatureTable
292: .getSelection();
293: if (ssel == null)
294: return;
295:
296: Action openAction = new Action(
297: PDEUIMessages.Product_FeatureSection_open) {
298: public void run() {
299: handleDoubleClick((IStructuredSelection) fFeatureTable
300: .getSelection());
301: }
302: };
303: openAction.setEnabled(isEditable() && ssel.size() == 1);
304: manager.add(openAction);
305:
306: manager.add(new Separator());
307:
308: Action removeAction = new Action(
309: PDEUIMessages.Product_FeatureSection_remove) {
310: public void run() {
311: handleDelete();
312: }
313: };
314: removeAction.setEnabled(isEditable() && ssel.size() > 0);
315: manager.add(removeAction);
316:
317: Action removeAll = new Action(
318: PDEUIMessages.FeatureSection_removeAll) {
319: public void run() {
320: handleRemoveAll();
321: }
322: };
323: removeAll.setEnabled(isEditable());
324: manager.add(removeAll);
325:
326: manager.add(new Separator());
327:
328: getPage().getPDEEditor().getContributor()
329: .contextMenuAboutToShow(manager);
330: }
331:
332: private void handleOpen(IStructuredSelection selection) {
333: if (!selection.isEmpty()) {
334: IProductFeature feature = (IProductFeature) selection
335: .getFirstElement();
336: FeatureModelManager manager = PDECore.getDefault()
337: .getFeatureModelManager();
338: IFeatureModel model = manager.findFeatureModel(feature
339: .getId(), feature.getVersion());
340: FeatureEditor.openFeatureEditor(model);
341: }
342: }
343:
344: private void handleAdd() {
345: FeatureSelectionDialog dialog = new FeatureSelectionDialog(
346: PDEPlugin.getActiveWorkbenchShell(),
347: getAvailableChoices(), true);
348: if (dialog.open() == Window.OK) {
349: Object[] models = dialog.getResult();
350: for (int i = 0; i < models.length; i++) {
351: IFeature feature = ((IFeatureModel) models[i])
352: .getFeature();
353: addFeature(feature.getId(), feature.getVersion());
354: }
355: }
356: }
357:
358: private IFeatureModel[] getAvailableChoices() {
359: IFeatureModel[] models = PDECore.getDefault()
360: .getFeatureModelManager().getModels();
361: IProduct product = getProduct();
362: ArrayList list = new ArrayList();
363: for (int i = 0; i < models.length; i++) {
364: String id = models[i].getFeature().getId();
365: if (id != null && !product.containsFeature(id)) {
366: list.add(models[i]);
367: }
368: }
369: return (IFeatureModel[]) list.toArray(new IFeatureModel[list
370: .size()]);
371: }
372:
373: private IProduct getProduct() {
374: return getModel().getProduct();
375: }
376:
377: private IProductModel getModel() {
378: return (IProductModel) getPage().getPDEEditor()
379: .getAggregateModel();
380: }
381:
382: /* (non-Javadoc)
383: * @see org.eclipse.pde.internal.ui.editor.PDESection#modelChanged(org.eclipse.pde.core.IModelChangedEvent)
384: */
385: public void modelChanged(IModelChangedEvent e) {
386: Object[] objects = e.getChangedObjects();
387: // No need to call super, handling world changed event here
388: if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
389: handleModelEventWorldChanged(e);
390: return;
391: } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
392: for (int i = 0; i < objects.length; i++) {
393: if (objects[i] instanceof IProductFeature)
394: fFeatureTable.add(objects[i]);
395: }
396: } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
397:
398: Table table = fFeatureTable.getTable();
399: int index = table.getSelectionIndex();
400:
401: for (int i = 0; i < objects.length; i++) {
402: if (objects[i] instanceof IProductFeature)
403: fFeatureTable.remove(objects[i]);
404: }
405:
406: // Update Selection
407:
408: int count = table.getItemCount();
409:
410: if (count == 0) {
411: // Nothing to select
412: } else if (index < count) {
413: table.setSelection(index);
414: } else {
415: table.setSelection(count - 1);
416: }
417:
418: } else if (e.getChangeType() == IModelChangedEvent.CHANGE) {
419: fFeatureTable.refresh();
420: }
421: updateButtons(false, true);
422: }
423:
424: /**
425: * @param event
426: */
427: private void handleModelEventWorldChanged(IModelChangedEvent event) {
428: // This section can get disposed if the configuration is changed from
429: // plugins to features or vice versa. Subsequently, the configuration
430: // page is removed and readded. In this circumstance, abort the
431: // refresh
432: if (fFeatureTable.getTable().isDisposed()) {
433: return;
434: }
435: // Reload the input
436: fFeatureTable.setInput(PDECore.getDefault()
437: .getFeatureModelManager());
438: // Perform the refresh
439: refresh();
440: }
441:
442: /* (non-Javadoc)
443: * @see org.eclipse.ui.forms.AbstractFormPart#refresh()
444: */
445: public void refresh() {
446: fFeatureTable.refresh();
447: updateButtons(true, true);
448: super .refresh();
449: }
450:
451: protected void selectionChanged(IStructuredSelection selection) {
452: getPage().getPDEEditor().setSelection(selection);
453: updateButtons(true, false);
454: }
455:
456: public boolean setFormInput(Object input) {
457: if (input instanceof IProductFeature) {
458: fFeatureTable.setSelection(new StructuredSelection(input),
459: true);
460: return true;
461: }
462: return super .setFormInput(input);
463: }
464:
465: private void updateButtons(boolean updateRemove,
466: boolean updateRemoveAll) {
467: TablePart tablePart = getTablePart();
468: Table table = tablePart.getTableViewer().getTable();
469: TableItem[] tableSelection = table.getSelection();
470: boolean hasSelection = tableSelection.length > 0;
471: if (updateRemove) {
472: ISelection selection = getViewerSelection();
473: tablePart
474: .setButtonEnabled(
475: 1,
476: isEditable()
477: && !selection.isEmpty()
478: && selection instanceof IStructuredSelection
479: && ((IStructuredSelection) selection)
480: .getFirstElement() instanceof IProductFeature);
481: }
482: if (updateRemoveAll)
483: tablePart.setButtonEnabled(2, isEditable()
484: && fFeatureTable.getTable().getItemCount() > 0);
485:
486: // up/down buttons
487: boolean canMove = table.getItemCount() > 1
488: && tableSelection.length == 1
489: && !fSortAction.isChecked();
490: tablePart.setButtonEnabled(3, canMove && isEditable()
491: && hasSelection && table.getSelectionIndex() > 0);
492: tablePart
493: .setButtonEnabled(4, canMove
494: && hasSelection
495: && isEditable()
496: && table.getSelectionIndex() < table
497: .getItemCount() - 1);
498: }
499:
500: protected boolean createCount() {
501: return true;
502: }
503:
504: private void handleUp() {
505: int index = getTablePart().getTableViewer().getTable()
506: .getSelectionIndex();
507: if (index < 1)
508: return;
509: swap(index, index - 1);
510: }
511:
512: private void handleDown() {
513: Table table = getTablePart().getTableViewer().getTable();
514: int index = table.getSelectionIndex();
515: if (index == table.getItemCount() - 1)
516: return;
517: swap(index, index + 1);
518: }
519:
520: public void swap(int index1, int index2) {
521: Table table = getTablePart().getTableViewer().getTable();
522: IProductFeature feature1 = ((IProductFeature) table.getItem(
523: index1).getData());
524: IProductFeature feature2 = ((IProductFeature) table.getItem(
525: index2).getData());
526:
527: IProduct product = getProduct();
528: product.swap(feature1, feature2);
529: }
530:
531: public void propertyChange(PropertyChangeEvent event) {
532: if (fSortAction.equals(event.getSource())
533: && IAction.RESULT.equals(event.getProperty())) {
534: updateButtons(true, true);
535: }
536: }
537: }
|