001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.catalog.internal.ui;
010:
011: import java.io.IOException;
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.HashMap;
015: import java.util.HashSet;
016: import java.util.List;
017: import java.util.Map;
018: import java.util.Set;
019:
020: import net.refractions.udig.catalog.IGeoResource;
021: import net.refractions.udig.catalog.IResolve;
022: import net.refractions.udig.catalog.IService;
023: import net.refractions.udig.catalog.IResolve.Status;
024: import net.refractions.udig.catalog.ui.CatalogUIPlugin;
025: import net.refractions.udig.catalog.ui.ResolveLabelProviderSimple;
026: import net.refractions.udig.catalog.ui.ResolveTitlesDecorator;
027: import net.refractions.udig.catalog.ui.internal.Messages;
028: import net.refractions.udig.catalog.ui.workflow.ResourceSelectionState;
029: import net.refractions.udig.catalog.ui.workflow.WorkflowWizardPage;
030:
031: import org.eclipse.core.runtime.IProgressMonitor;
032: import org.eclipse.core.runtime.NullProgressMonitor;
033: import org.eclipse.jface.dialogs.IPageChangedListener;
034: import org.eclipse.jface.dialogs.PageChangedEvent;
035: import org.eclipse.jface.operation.IRunnableWithProgress;
036: import org.eclipse.jface.resource.ImageDescriptor;
037: import org.eclipse.jface.viewers.CheckStateChangedEvent;
038: import org.eclipse.jface.viewers.CheckboxTreeViewer;
039: import org.eclipse.jface.viewers.DecoratingLabelProvider;
040: import org.eclipse.jface.viewers.ICheckStateListener;
041: import org.eclipse.jface.viewers.ISelectionChangedListener;
042: import org.eclipse.jface.viewers.ITreeContentProvider;
043: import org.eclipse.jface.viewers.LabelProvider;
044: import org.eclipse.jface.viewers.SelectionChangedEvent;
045: import org.eclipse.jface.viewers.Viewer;
046: import org.eclipse.jface.viewers.ViewerSorter;
047: import org.eclipse.swt.SWT;
048: import org.eclipse.swt.layout.GridData;
049: import org.eclipse.swt.layout.GridLayout;
050: import org.eclipse.swt.widgets.Button;
051: import org.eclipse.swt.widgets.Composite;
052: import org.eclipse.swt.widgets.Control;
053:
054: /**
055: * A page that allows the user to select the resources he/she wish to include in the map.
056: *
057: * @author jeichar
058: * @since 0.9.0
059: */
060: public class ResourceSelectionPage extends WorkflowWizardPage implements
061: IPageChangedListener {
062:
063: private Map<IResolve, List<IGeoResource>> geoResources = new HashMap<IResolve, List<IGeoResource>>();
064: private CheckboxTreeViewer viewer;
065:
066: /** url from workbench selection * */
067: private ResolveTitlesDecorator titleDecorator;
068: /**
069: * Indicates whether selected services should be collapse when input is changed
070: */
071: private boolean collapseCheckedInput = false;
072: private List<Object> grayedElements = new ArrayList<Object>();
073:
074: public ResourceSelectionPage(String pageName, ImageDescriptor banner) {
075: super (pageName);
076: setTitle(Messages.ResourceSelectionPage_title);
077: setMessage(Messages.ResourceSelectionPage_message);
078: // setImageDescriptor(Images.getDescriptor(ImageConstants.CHOOSE_LAYER_WIZBAN));
079: setImageDescriptor(banner);
080: }
081:
082: /**
083: * @deprecated
084: */
085: public void setResources(List<IResolve> serviceList,
086: IProgressMonitor monitor) {
087: }
088:
089: @Override
090: public void dispose() {
091: super .dispose();
092: viewer.getContentProvider().dispose();
093: viewer.getLabelProvider().dispose();
094: }
095:
096: private List<IGeoResource> getGeoResources(final IResolve resolve,
097: boolean fork) {
098: if (geoResources.get(resolve) == null || geoResources.isEmpty()) {
099: final List<IGeoResource> list = new ArrayList<IGeoResource>();
100:
101: try {
102: IRunnableWithProgress runnable = new IRunnableWithProgress() {
103:
104: @SuppressWarnings("unchecked")
105: public void run(IProgressMonitor monitor) {
106: monitor
107: .beginTask(
108: Messages.ResourceSelectionPage_searching,
109: IProgressMonitor.UNKNOWN);
110: try {
111: Collection<? extends IGeoResource> members = (Collection<? extends IGeoResource>) resolve
112: .members(monitor);
113: list.addAll(members);
114: // for (IGeoResource resource : list) {
115: // list.addAll(getGeoResources(resource, false));
116: // }
117: } catch (Exception e) {
118: // do nothing
119: }
120: monitor.done();
121: }
122:
123: };
124: if (fork) {
125: getContainer().run(false, true, runnable);
126: } else {
127: runnable.run(new NullProgressMonitor());
128: }
129: } catch (Exception e) {
130: CatalogUIPlugin.log("", e); //$NON-NLS-1$
131: }
132: geoResources.put(resolve, list);
133: }
134: return geoResources.get(resolve);
135: }
136:
137: /**
138: * @deprecated
139: */
140: public List<Object> getCheckedElements() {
141: List<Object> list = new ArrayList<Object>();
142: for (Object object : viewer.getCheckedElements()) {
143: if (object instanceof IGeoResource) {
144: IGeoResource resource = (IGeoResource) object;
145: list.add(resource);
146: }
147: }
148: return list;
149: }
150:
151: /**
152: * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
153: */
154: public void createControl(Composite parent) {
155: Composite composite = new Composite(parent, SWT.NULL);
156: composite.setLayout(new GridLayout());
157: viewer = new CheckboxTreeViewer(composite);
158:
159: // dont bother sorting its silly.
160: viewer.setSorter(new ViewerSorter() {
161: @Override
162: public void sort(Viewer viewer, Object[] elements) {
163: return;
164: }
165: });
166: viewer.getControl().setLayoutData(
167: new GridData(SWT.FILL, SWT.FILL, true, true));
168: viewer
169: .addPostSelectionChangedListener(new ISelectionChangedListener() {
170:
171: public void selectionChanged(
172: SelectionChangedEvent event) {
173: getWizard().getContainer().updateButtons();
174: }
175:
176: });
177: viewer.addCheckStateListener(new ICheckStateListener() {
178: public void checkStateChanged(CheckStateChangedEvent event) {
179: // set all children to same check state
180: Object o = event.getElement();
181: boolean checked = event.getChecked();
182: ServiceTreeProvider p = updateChildren(o, checked);
183:
184: // if checked set parent checked
185: if (checked) {
186: Object parent = p.getParent(o);
187: if (parent != null)
188: viewer.setChecked(parent, true);
189: }
190:
191: syncWithUI();
192: }
193:
194: private ServiceTreeProvider updateChildren(Object o,
195: boolean checked) {
196: ServiceTreeProvider p = (ServiceTreeProvider) viewer
197: .getContentProvider();
198: Object[] children = p.getChildren(o);
199: if (children != null && children.length > 0) {
200: for (int i = 0; i < children.length; i++) {
201: viewer.setChecked(children[i], checked);
202: updateChildren(children[i], checked);
203: }
204: }
205: return p;
206: }
207: });
208: viewer.setContentProvider(new ServiceTreeProvider());
209:
210: titleDecorator = new ResolveTitlesDecorator(
211: new ResolveLabelProviderSimple(), true);
212: LabelProvider labelProvider = new DecoratingLabelProvider(
213: titleDecorator.getSource(), titleDecorator);
214:
215: viewer.setLabelProvider(labelProvider);
216: viewer.setAutoExpandLevel(3);
217:
218: // use the state to initialize ui
219: ResourceSelectionState state = (ResourceSelectionState) getState();
220: setInput(state);
221:
222: setControl(composite);
223: }
224:
225: /**
226: * Public only for testing purposes. Treat as if it is private.
227: */
228: public CheckboxTreeViewer getViewer() {
229: return viewer;
230: }
231:
232: /**
233: * This method is mainly for testing purposes and should not be called by client code.
234: */
235: public void syncWithUI() {
236: try {
237: Map<IGeoResource, IService> map = new HashMap<IGeoResource, IService>();
238: Object[] elements = getViewer().getCheckedElements();
239:
240: for (int i = 0; i < elements.length; i++) {
241: if (elements[i] instanceof IGeoResource) {
242: IGeoResource resource = (IGeoResource) elements[i];
243: if (resource.members(null).isEmpty())
244: map.put(resource, resource.service(null));
245: }
246: }
247: ((ResourceSelectionState) getState()).setResources(map);
248: } catch (IOException e) {
249: CatalogUIPlugin.log(e.getLocalizedMessage(), e);
250: }
251: }
252:
253: @Override
254: public void shown() {
255: setInput((ResourceSelectionState) getState());
256: }
257:
258: private void setInput(ResourceSelectionState state) {
259: grayedElements.clear();
260: viewer.setInput(state.getServices()); // initialize viewer input to nothing
261: Map<IGeoResource, IService> resources = state.getResources();
262: if (resources != null) {
263: Set<IService> expanded = new HashSet<IService>();
264: for (Map.Entry<IGeoResource, IService> entry : resources
265: .entrySet()) {
266: IGeoResource resource = entry.getKey();
267: IService service = entry.getValue();
268:
269: viewer.setChecked(resource, true);
270: viewer.setChecked(service, true);
271: expanded.add(service);
272: }
273: if (collapseCheckedInput) {
274: for (IService service : expanded) {
275: viewer.setExpandedState(service, false);
276: }
277: }
278: }
279: viewer.setGrayedElements(grayedElements.toArray());
280: }
281:
282: Button findButton(Control[] children, int id) {
283: if (((Integer) getShell().getDefaultButton().getData())
284: .intValue() == id)
285: return getShell().getDefaultButton();
286:
287: for (Control child : children) {
288: if (child instanceof Button) {
289: Button button = (Button) child;
290: if (((Integer) button.getData()).intValue() == id)
291: return button;
292: }
293: if (child instanceof Composite) {
294: Composite composite = (Composite) child;
295: Button button = findButton(composite.getChildren(), id);
296: if (button != null)
297: return button;
298: }
299: }
300: return null;
301: }
302:
303: public class ServiceTreeProvider extends LabelProvider implements
304: ITreeContentProvider {
305:
306: /**
307: * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
308: */
309: public Object[] getElements(Object inputElement) {
310: return getChildren(inputElement);
311: }
312:
313: /**
314: * @see org.eclipse.jface.viewers.IContentProvider#dispose()
315: */
316: public void dispose() {
317: }
318:
319: /**
320: * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
321: * java.lang.Object, java.lang.Object)
322: */
323: public void inputChanged(Viewer viewer, Object oldInput,
324: Object newInput) {
325: }
326:
327: @SuppressWarnings("unchecked")
328: public Object[] getChildren(Object parentElement) {
329: if (parentElement instanceof Collection) {
330: Collection<IResolve> list = (Collection<IResolve>) parentElement;
331: if (list.isEmpty()) {
332: return reasons();
333: }
334:
335: return list.toArray();
336: }
337: if (parentElement instanceof IResolve) {
338: IResolve service = (IResolve) parentElement;
339: List<IGeoResource> children = getGeoResources(service,
340: true);
341: if (children.isEmpty()) {
342: if (parentElement instanceof IService) {
343: grayedElements.add(service);
344: if (service.getStatus() == Status.BROKEN) {
345: if (service.getMessage() != null) {
346: String string = Messages.ResourceSelectionPage_brokenReportError
347: + service.getMessage()
348: .getLocalizedMessage();
349: grayedElements.add(string);
350: return new String[] { string };
351: } else {
352: String string = Messages.ResourceSelectionPage_brokenUnknown;
353: grayedElements.add(string);
354: return new String[] { string };
355: }
356: }
357: if (service.getStatus() == Status.RESTRICTED_ACCESS) {
358: String string = Messages.ResourceSelectionPage_noPermission;
359: grayedElements.add(string);
360: return new String[] { string };
361: }
362: if (service.getStatus() == Status.CONNECTED) {
363: String string = Messages.ResourceSelectionPage_connectedButNoResources;
364: grayedElements.add(string);
365: return new String[] { string };
366: }
367: } else {
368: return null;
369: }
370: }
371:
372: return children.toArray();
373: }
374: return null;
375: }
376:
377: private Object[] reasons() {
378: return new String[] { Messages.ResourceSelectionPage_noServices };
379: }
380:
381: public Object getParent(Object element) {
382: if (element instanceof IGeoResource) {
383: IGeoResource resource = (IGeoResource) element;
384: try {
385: return resource.parent(null);
386: } catch (IOException e) {
387: CatalogUIPlugin.log(null, e);
388: }
389: }
390: return null;
391: }
392:
393: public boolean hasChildren(Object element) {
394: return element instanceof IResolve;
395: }
396:
397: @Override
398: public String getText(Object element) {
399: if (element instanceof IResolve) {
400: IResolve resolver = (IResolve) element;
401: return resolver.getIdentifier().toString();
402: }
403: return null;
404: }
405:
406: }
407:
408: public void pageChanged(PageChangedEvent event) {
409: }
410:
411: public boolean isCollapseCheckedInput() {
412: return collapseCheckedInput;
413: }
414:
415: public void setCollapseCheckedInput(boolean collapseCheckedInput) {
416: this.collapseCheckedInput = collapseCheckedInput;
417: }
418: }
|