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.build;
011:
012: import org.eclipse.core.resources.IFile;
013: import org.eclipse.core.resources.IProject;
014: import org.eclipse.core.resources.IResource;
015: import org.eclipse.core.runtime.Assert;
016: import org.eclipse.core.runtime.CoreException;
017: import org.eclipse.core.runtime.IStatus;
018: import org.eclipse.core.runtime.Status;
019: import org.eclipse.jface.action.Action;
020: import org.eclipse.jface.action.IMenuManager;
021: import org.eclipse.jface.action.Separator;
022: import org.eclipse.jface.viewers.ISelection;
023: import org.eclipse.jface.viewers.IStructuredContentProvider;
024: import org.eclipse.jface.viewers.IStructuredSelection;
025: import org.eclipse.jface.viewers.ITableLabelProvider;
026: import org.eclipse.jface.viewers.LabelProvider;
027: import org.eclipse.jface.viewers.StructuredSelection;
028: import org.eclipse.jface.viewers.TableViewer;
029: import org.eclipse.jface.viewers.Viewer;
030: import org.eclipse.jface.viewers.ViewerFilter;
031: import org.eclipse.jface.window.Window;
032: import org.eclipse.pde.core.IModelChangedEvent;
033: import org.eclipse.pde.core.IModelChangedListener;
034: import org.eclipse.pde.core.build.IBuild;
035: import org.eclipse.pde.core.build.IBuildEntry;
036: import org.eclipse.pde.core.build.IBuildModel;
037: import org.eclipse.pde.core.plugin.IPluginModelBase;
038: import org.eclipse.pde.core.plugin.PluginRegistry;
039: import org.eclipse.pde.internal.build.IBuildPropertiesConstants;
040: import org.eclipse.pde.internal.core.natures.PDE;
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.PDEFormPage;
045: import org.eclipse.pde.internal.ui.editor.TableSection;
046: import org.eclipse.pde.internal.ui.editor.context.InputContext;
047: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
048: import org.eclipse.pde.internal.ui.parts.EditableTablePart;
049: import org.eclipse.swt.SWT;
050: import org.eclipse.swt.graphics.Image;
051: import org.eclipse.swt.layout.GridData;
052: import org.eclipse.swt.widgets.Composite;
053: import org.eclipse.swt.widgets.Table;
054: import org.eclipse.ui.ISharedImages;
055: import org.eclipse.ui.PlatformUI;
056: import org.eclipse.ui.actions.ActionFactory;
057: import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
058: import org.eclipse.ui.dialogs.ISelectionStatusValidator;
059: import org.eclipse.ui.forms.widgets.ExpandableComposite;
060: import org.eclipse.ui.forms.widgets.FormToolkit;
061: import org.eclipse.ui.forms.widgets.Section;
062: import org.eclipse.ui.model.WorkbenchContentProvider;
063: import org.eclipse.ui.model.WorkbenchLabelProvider;
064: import org.eclipse.ui.views.navigator.ResourceComparator;
065:
066: public class BuildClasspathSection extends TableSection implements
067: IModelChangedListener {
068:
069: private TableViewer fTableViewer;
070: private boolean fEnabled = true;
071:
072: /**
073: * Implementation of a <code>ISelectionValidator</code> to validate the
074: * type of an element.
075: * Empty selections are not accepted.
076: */
077: class ElementSelectionValidator implements
078: ISelectionStatusValidator {
079:
080: private Class[] fAcceptedTypes;
081: private boolean fAllowMultipleSelection;
082:
083: /**
084: * @param acceptedTypes The types accepted by the validator
085: * @param allowMultipleSelection If set to <code>true</code>, the validator
086: * allows multiple selection.
087: */
088: public ElementSelectionValidator(Class[] acceptedTypes,
089: boolean allowMultipleSelection) {
090: Assert.isNotNull(acceptedTypes);
091: fAcceptedTypes = acceptedTypes;
092: fAllowMultipleSelection = allowMultipleSelection;
093: }
094:
095: /*
096: * @see org.eclipse.ui.dialogs.ISelectionValidator#isValid(java.lang.Object)
097: */
098: public IStatus validate(Object[] elements) {
099: if (isValid(elements)) {
100: return new Status(IStatus.OK, PDEPlugin.getPluginId(),
101: IStatus.OK, "", //$NON-NLS-1$
102: null);
103: }
104: return new Status(IStatus.ERROR, PDEPlugin.getPluginId(),
105: IStatus.ERROR, "", //$NON-NLS-1$
106: null);
107: }
108:
109: private boolean isOfAcceptedType(Object o) {
110: for (int i = 0; i < fAcceptedTypes.length; i++) {
111: if (fAcceptedTypes[i].isInstance(o)) {
112: return true;
113: }
114: }
115: return false;
116: }
117:
118: private boolean isValid(Object[] selection) {
119: if (selection.length == 0) {
120: return false;
121: }
122:
123: if (!fAllowMultipleSelection && selection.length != 1) {
124: return false;
125: }
126:
127: for (int i = 0; i < selection.length; i++) {
128: Object o = selection[i];
129: if (!isOfAcceptedType(o)) {
130: return false;
131: }
132: }
133: return true;
134: }
135: }
136:
137: class TableContentProvider extends DefaultContentProvider implements
138: IStructuredContentProvider {
139: public Object[] getElements(Object parent) {
140: if (parent instanceof IBuildModel) {
141: IBuild build = ((IBuildModel) parent).getBuild();
142: IBuildEntry entry = build
143: .getEntry(IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
144: if (entry != null) {
145: return entry.getTokens();
146: }
147: }
148: return new Object[0];
149: }
150: }
151:
152: class TableLabelProvider extends LabelProvider implements
153: ITableLabelProvider {
154: public String getColumnText(Object obj, int index) {
155: return obj.toString();
156: }
157:
158: public Image getColumnImage(Object obj, int index) {
159: ISharedImages sharedImages = PlatformUI.getWorkbench()
160: .getSharedImages();
161: return sharedImages.getImage(ISharedImages.IMG_OBJ_FILE);
162: }
163: }
164:
165: public BuildClasspathSection(PDEFormPage page, Composite parent) {
166: super (page, parent, Section.DESCRIPTION
167: | ExpandableComposite.TWISTIE, new String[] {
168: PDEUIMessages.BuildEditor_ClasspathSection_add,
169: PDEUIMessages.BuildEditor_ClasspathSection_remove,
170: null, null });
171: getSection().setText(
172: PDEUIMessages.BuildEditor_ClasspathSection_title);
173: getSection().setDescription(
174: PDEUIMessages.BuildEditor_ClasspathSection_desc);
175: initialize();
176:
177: }
178:
179: private IBuildModel getBuildModel() {
180: InputContext context = getPage().getPDEEditor()
181: .getContextManager().findContext(
182: BuildInputContext.CONTEXT_ID);
183: if (context == null)
184: return null;
185: return (IBuildModel) context.getModel();
186: }
187:
188: public void initialize() {
189: getBuildModel().addModelChangedListener(this );
190: IBuildEntry entry = getBuildModel().getBuild().getEntry(
191: IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
192: getSection().setExpanded(
193: entry != null && entry.getTokens().length > 0);
194: }
195:
196: public void createClient(Section section, FormToolkit toolkit) {
197: Composite container = createClientContainer(section, 2, toolkit);
198: createViewerPartControl(container, SWT.FULL_SELECTION, 2,
199: toolkit);
200:
201: EditableTablePart tablePart = getTablePart();
202: tablePart.setEditable(true);
203: fTableViewer = tablePart.getTableViewer();
204:
205: fTableViewer.setContentProvider(new TableContentProvider());
206: fTableViewer.setLabelProvider(new TableLabelProvider());
207: fTableViewer.setInput(getBuildModel());
208:
209: toolkit.paintBordersFor(container);
210: enableSection(true);
211: section.setLayout(FormLayoutFactory.createClearGridLayout(
212: false, 1));
213: GridData data = new GridData(GridData.FILL_HORIZONTAL);
214: section.setLayoutData(data);
215: data.horizontalSpan = 2;
216: section.setClient(container);
217: }
218:
219: protected void fillContextMenu(IMenuManager manager) {
220: ISelection selection = fTableViewer.getSelection();
221:
222: // add NEW action
223: Action action = new Action(
224: PDEUIMessages.BuildEditor_ClasspathSection_add) {
225: public void run() {
226: handleNew();
227: }
228: };
229: action.setEnabled(fEnabled);
230: manager.add(action);
231:
232: manager.add(new Separator());
233:
234: // add DELETE action
235: action = new Action(
236: PDEUIMessages.BuildEditor_ClasspathSection_remove) {
237: public void run() {
238: handleDelete();
239: }
240: };
241: action.setEnabled(!selection.isEmpty() && fEnabled);
242: manager.add(action);
243:
244: getPage().getPDEEditor().getContributor()
245: .contextMenuAboutToShow(manager, false);
246: }
247:
248: public void dispose() {
249: IBuildModel model = getBuildModel();
250: if (model != null)
251: model.removeModelChangedListener(this );
252: super .dispose();
253: }
254:
255: public void refresh() {
256: fTableViewer.refresh();
257: }
258:
259: public boolean doGlobalAction(String actionId) {
260: if (actionId.equals(ActionFactory.DELETE.getId())) {
261: if (fEnabled) {
262: handleDelete();
263: }
264: return true;
265: }
266: return false;
267: }
268:
269: public void enableSection(boolean enable) {
270: fEnabled = enable;
271: EditableTablePart tablePart = getTablePart();
272: tablePart.setButtonEnabled(1, enable
273: && !fTableViewer.getSelection().isEmpty());
274: tablePart.setButtonEnabled(0, enable);
275: }
276:
277: protected void selectionChanged(IStructuredSelection selection) {
278: getPage().getPDEEditor().setSelection(selection);
279: getTablePart().setButtonEnabled(1,
280: selection != null && selection.size() > 0 && fEnabled);
281: }
282:
283: private void handleDelete() {
284: Object selection = ((IStructuredSelection) fTableViewer
285: .getSelection()).getFirstElement();
286: if (selection != null && selection instanceof String) {
287: IBuild build = getBuildModel().getBuild();
288: IBuildEntry entry = build
289: .getEntry(IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
290: if (entry != null) {
291: try {
292: entry.removeToken(selection.toString());
293:
294: String[] tokens = entry.getTokens();
295: if (tokens.length == 0)
296: build.remove(entry);
297:
298: } catch (CoreException e) {
299: PDEPlugin.logException(e);
300: }
301: }
302: }
303: }
304:
305: private void initializeDialogSettings(
306: ElementTreeSelectionDialog dialog) {
307: Class[] acceptedClasses = new Class[] { IFile.class };
308: dialog.setValidator(new ElementSelectionValidator(
309: acceptedClasses, true));
310: dialog
311: .setTitle(PDEUIMessages.BuildEditor_ClasspathSection_jarsTitle);
312: dialog
313: .setMessage(PDEUIMessages.BuildEditor_ClasspathSection_jarsDesc);
314: dialog.addFilter(new JARFileFilter());
315: dialog.addFilter(new ViewerFilter() {
316: public boolean select(Viewer viewer, Object parentElement,
317: Object element) {
318: if (element instanceof IProject) {
319: try {
320: return ((IProject) element)
321: .hasNature(PDE.PLUGIN_NATURE);
322: } catch (CoreException e) {
323: }
324: return false;
325: } else if (element instanceof IResource) {
326: IBuildModel model = getBuildModel();
327: IBuildEntry entry = model
328: .getBuild()
329: .getEntry(
330: IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
331: if (entry != null)
332: return !entry
333: .contains(getRelativePathTokenName((IResource) element));
334: }
335: return true;
336: }
337: });
338: dialog.setInput(PDEPlugin.getWorkspace().getRoot());
339: dialog.setComparator(new ResourceComparator(
340: ResourceComparator.NAME));
341: dialog.setInitialSelection(getBuildModel()
342: .getUnderlyingResource().getProject());
343:
344: }
345:
346: private void handleNew() {
347: ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
348: getSection().getShell(), new WorkbenchLabelProvider(),
349: new WorkbenchContentProvider());
350:
351: initializeDialogSettings(dialog);
352: if (dialog.open() == Window.OK) {
353: Object[] elements = dialog.getResult();
354: for (int i = 0; i < elements.length; i++) {
355: IResource elem = (IResource) elements[i];
356: String tokenName = getRelativePathTokenName(elem);
357: if (tokenName == null)
358: continue;
359: addClasspathToken(tokenName);
360: }
361: }
362: }
363:
364: private void addClasspathToken(String tokenName) {
365: IBuildModel model = getBuildModel();
366: IBuildEntry entry = model.getBuild().getEntry(
367: IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
368: try {
369: if (entry == null) {
370: entry = model
371: .getFactory()
372: .createEntry(
373: IBuildPropertiesConstants.PROPERTY_JAR_EXTRA_CLASSPATH);
374: model.getBuild().add(entry);
375: }
376: if (!entry.contains(tokenName))
377: entry.addToken(tokenName);
378: } catch (CoreException e) {
379: PDEPlugin.logException(e);
380: }
381: }
382:
383: private String getRelativePathTokenName(IResource elem) {
384: IProject this Project = getBuildModel().getUnderlyingResource()
385: .getProject();
386: IProject elemProject = elem.getProject();
387: String projectRelative = elem.getProjectRelativePath()
388: .toString();
389: if (this Project == elemProject)
390: return projectRelative;
391:
392: IPluginModelBase model = PluginRegistry.findModel(elemProject);
393: if (model != null)
394: return "platform:/plugin/" + model.getPluginBase().getId() + '/' + projectRelative; //$NON-NLS-1$
395: return null;
396: }
397:
398: protected void buttonSelected(int index) {
399: switch (index) {
400: case 0:
401: handleNew();
402: break;
403: case 1:
404: handleDelete();
405: break;
406: default:
407: break;
408: }
409: }
410:
411: public void modelChanged(IModelChangedEvent event) {
412: if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED)
413: markStale();
414: else if (event.getChangeType() == IModelChangedEvent.CHANGE) {
415: Object changeObject = event.getChangedObjects()[0];
416:
417: if (changeObject instanceof IBuildEntry
418: && ((IBuildEntry) changeObject).getName().equals(
419: IBuildEntry.JARS_EXTRA_CLASSPATH)) {
420: Table table = fTableViewer.getTable();
421: int index = table.getSelectionIndex();
422: fTableViewer.refresh();
423: int count = table.getItemCount();
424: if (index == -1 || index >= count
425: || event.getOldValue() == null)
426: index = count - 1;
427: if (count == 0)
428: fTableViewer.setSelection(null);
429: else
430: fTableViewer.setSelection(new StructuredSelection(
431: table.getItem(index).getData()));
432: table.setFocus();
433: }
434: }
435: }
436: }
|