001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 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.jdt.internal.ui.browsing;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.swt.widgets.Control;
016: import org.eclipse.swt.widgets.Display;
017:
018: import org.eclipse.jface.viewers.IStructuredContentProvider;
019: import org.eclipse.jface.viewers.StructuredViewer;
020: import org.eclipse.jface.viewers.TableViewer;
021:
022: import org.eclipse.jdt.core.IJavaElement;
023: import org.eclipse.jdt.core.IJavaElementDelta;
024: import org.eclipse.jdt.core.IJavaProject;
025: import org.eclipse.jdt.core.IPackageFragment;
026: import org.eclipse.jdt.core.IPackageFragmentRoot;
027: import org.eclipse.jdt.core.JavaModelException;
028:
029: /**
030: * Table content provider for the hierarchical layout in the packages view.
031: * <p>
032: * XXX: The standard Java browsing part content provider needs and calls
033: * the browsing part/view. This class currently doesn't need to do so
034: * but might be required to later.
035: * </p>
036: */
037: class PackagesViewFlatContentProvider extends LogicalPackagesProvider
038: implements IStructuredContentProvider {
039: PackagesViewFlatContentProvider(StructuredViewer viewer) {
040: super (viewer);
041: }
042:
043: /*
044: * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
045: */
046: public Object[] getChildren(Object parentElement) {
047:
048: if (parentElement instanceof IJavaElement) {
049: IJavaElement element = (IJavaElement) parentElement;
050:
051: int type = element.getElementType();
052:
053: try {
054: switch (type) {
055: case IJavaElement.JAVA_PROJECT:
056: IJavaProject project = (IJavaProject) element;
057: IPackageFragment[] children = getPackageFragments(project
058: .getPackageFragments());
059: if (isInCompoundState()) {
060: fMapToLogicalPackage.clear();
061: fMapToPackageFragments.clear();
062: return combineSamePackagesIntoLogialPackages(children);
063: } else
064: return children;
065:
066: case IJavaElement.PACKAGE_FRAGMENT_ROOT:
067: fMapToLogicalPackage.clear();
068: fMapToPackageFragments.clear();
069: IPackageFragmentRoot root = (IPackageFragmentRoot) element;
070: return root.getChildren();
071:
072: case IJavaElement.PACKAGE_FRAGMENT:
073: //no children in flat view
074: break;
075:
076: default:
077: //do nothing, empty array returned
078: }
079: } catch (JavaModelException e) {
080: return NO_CHILDREN;
081: }
082:
083: }
084: return NO_CHILDREN;
085: }
086:
087: /*
088: * Weeds out packageFragments from external jars
089: */
090: private IPackageFragment[] getPackageFragments(
091: IPackageFragment[] iPackageFragments) {
092: List list = new ArrayList();
093: for (int i = 0; i < iPackageFragments.length; i++) {
094: IPackageFragment fragment = iPackageFragments[i];
095: IJavaElement el = fragment.getParent();
096: if (el instanceof IPackageFragmentRoot) {
097: IPackageFragmentRoot root = (IPackageFragmentRoot) el;
098: if (root.isArchive() && root.isExternal())
099: continue;
100: }
101: list.add(fragment);
102: }
103: return (IPackageFragment[]) list
104: .toArray(new IPackageFragment[list.size()]);
105: }
106:
107: /*
108: * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
109: */
110: public Object[] getElements(Object inputElement) {
111: return getChildren(inputElement);
112: }
113:
114: protected void processDelta(IJavaElementDelta delta)
115: throws JavaModelException {
116:
117: int kind = delta.getKind();
118: final IJavaElement element = delta.getElement();
119:
120: if (isClassPathChange(delta)) {
121: Object input = fViewer.getInput();
122: if (input != null) {
123: if (fInputIsProject
124: && input.equals(element.getJavaProject())) {
125: postRefresh(input);
126: return;
127: } else if (!fInputIsProject && input.equals(element)) {
128: if (element.exists())
129: postRefresh(input);
130: else
131: postRemove(input);
132: return;
133: }
134: }
135: }
136:
137: if (kind == IJavaElementDelta.REMOVED) {
138: Object input = fViewer.getInput();
139: if (input != null && input.equals(element)) {
140: postRemove(input);
141: return;
142: }
143: }
144:
145: if (element instanceof IPackageFragment) {
146: final IPackageFragment frag = (IPackageFragment) element;
147:
148: if (kind == IJavaElementDelta.REMOVED) {
149: removeElement(frag);
150:
151: } else if (kind == IJavaElementDelta.ADDED) {
152: addElement(frag);
153:
154: } else if (kind == IJavaElementDelta.CHANGED) {
155: //just refresh
156: Object toBeRefreshed = element;
157:
158: IPackageFragment pkgFragment = (IPackageFragment) element;
159: LogicalPackage logicalPkg = findLogicalPackage(pkgFragment);
160: //deal with packages that have been filtered and are now visible
161: if (logicalPkg != null)
162: toBeRefreshed = findElementToRefresh(logicalPkg);
163: else
164: toBeRefreshed = findElementToRefresh(pkgFragment);
165:
166: postRefresh(toBeRefreshed);
167: }
168: //in this view there will be no children of PackageFragment to refresh
169: return;
170: }
171: processAffectedChildren(delta);
172: }
173:
174: //test to see if element to be refreshed is being filtered out
175: //and if so refresh the viewers input element (JavaProject or PackageFragmentRoot)
176: private Object findElementToRefresh(IPackageFragment fragment) {
177: if (fViewer.testFindItem(fragment) == null) {
178: if (fInputIsProject)
179: return fragment.getJavaProject();
180: else
181: return fragment.getParent();
182: }
183: return fragment;
184: }
185:
186: //test to see if element to be refreshed is being filtered out
187: //and if so refresh the viewers input element (JavaProject or PackageFragmentRoot)
188: private Object findElementToRefresh(LogicalPackage logicalPackage) {
189: if (fViewer.testFindItem(logicalPackage) == null) {
190: IPackageFragment fragment = logicalPackage.getFragments()[0];
191: return fragment.getJavaProject();
192: }
193: return logicalPackage;
194: }
195:
196: private void processAffectedChildren(IJavaElementDelta delta)
197: throws JavaModelException {
198: IJavaElementDelta[] children = delta.getAffectedChildren();
199: for (int i = 0; i < children.length; i++) {
200: IJavaElementDelta elementDelta = children[i];
201: processDelta(elementDelta);
202: }
203: }
204:
205: private void postAdd(final Object child) {
206: postRunnable(new Runnable() {
207: public void run() {
208: Control ctrl = fViewer.getControl();
209: if (ctrl != null && !ctrl.isDisposed()) {
210: ((TableViewer) fViewer).add(child);
211: }
212: }
213: });
214: }
215:
216: private void postRemove(final Object object) {
217: postRunnable(new Runnable() {
218: public void run() {
219: Control ctrl = fViewer.getControl();
220: if (ctrl != null && !ctrl.isDisposed()) {
221: ((TableViewer) fViewer).remove(object);
222: }
223: }
224: });
225: }
226:
227: private void postRunnable(final Runnable r) {
228: Control ctrl = fViewer.getControl();
229: if (ctrl != null && !ctrl.isDisposed()) {
230: // fBrowsingPart.setProcessSelectionEvents(false);
231: try {
232: Display currentDisplay = Display.getCurrent();
233: if (currentDisplay != null
234: && currentDisplay.equals(ctrl.getDisplay()))
235: ctrl.getDisplay().syncExec(r);
236: else
237: ctrl.getDisplay().asyncExec(r);
238: } finally {
239: // fBrowsingPart.setProcessSelectionEvents(true);
240: }
241: }
242: }
243:
244: private void removeElement(IPackageFragment frag) {
245: String key = getKey(frag);
246: LogicalPackage lp = (LogicalPackage) fMapToLogicalPackage
247: .get(key);
248:
249: if (lp != null) {
250: lp.remove(frag);
251: //if you need to change the LogicalPackage to a PackageFragment
252: if (lp.getFragments().length == 1) {
253: IPackageFragment fragment = lp.getFragments()[0];
254: fMapToLogicalPackage.remove(key);
255: fMapToPackageFragments.put(key, fragment);
256:
257: //@Improve: Should I replace this with a refresh of the parent?
258: postRemove(lp);
259: postAdd(fragment);
260: }
261: return;
262: } else {
263: fMapToPackageFragments.remove(key);
264: postRemove(frag);
265: }
266: }
267:
268: private void postRefresh(final Object element) {
269: postRunnable(new Runnable() {
270: public void run() {
271: Control ctrl = fViewer.getControl();
272: if (ctrl != null && !ctrl.isDisposed()) {
273: fViewer.refresh(element);
274: }
275: }
276: });
277: }
278:
279: private void addElement(IPackageFragment frag) {
280: String key = getKey(frag);
281: LogicalPackage lp = (LogicalPackage) fMapToLogicalPackage
282: .get(key);
283:
284: if (lp != null && lp.belongs(frag)) {
285: lp.add(frag);
286: return;
287: }
288:
289: IPackageFragment fragment = (IPackageFragment) fMapToPackageFragments
290: .get(key);
291: if (fragment != null) {
292: //must create a new LogicalPackage
293: if (!fragment.equals(frag)) {
294: lp = new LogicalPackage(fragment);
295: lp.add(frag);
296: fMapToLogicalPackage.put(key, lp);
297:
298: //@Improve: should I replace this with a refresh?
299: postRemove(fragment);
300: postAdd(lp);
301:
302: return;
303: }
304: }
305:
306: else {
307: fMapToPackageFragments.put(key, frag);
308: postAdd(frag);
309: }
310: }
311: }
|