001: /**
002: * <copyright></copyright> $Id: RenderManagerDynamic.java 22605 2006-11-06 17:55:57Z jeichar $
003: */package net.refractions.udig.project.ui.internal;
004:
005: import static net.refractions.udig.project.ui.internal.Trace.RENDER;
006:
007: import java.awt.Color;
008: import java.awt.Graphics2D;
009: import java.awt.Rectangle;
010: import java.awt.image.BufferedImage;
011: import java.util.ArrayList;
012: import java.util.Collection;
013: import java.util.HashSet;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Set;
017:
018: import net.refractions.udig.project.ILayer;
019: import net.refractions.udig.project.internal.ContextModelListenerAdapter;
020: import net.refractions.udig.project.internal.Layer;
021: import net.refractions.udig.project.internal.Map;
022: import net.refractions.udig.project.internal.ProjectPackage;
023: import net.refractions.udig.project.internal.render.CompositeRenderContext;
024: import net.refractions.udig.project.internal.render.ExecutorVisitor;
025: import net.refractions.udig.project.internal.render.MultiLayerRenderer;
026: import net.refractions.udig.project.internal.render.RenderContext;
027: import net.refractions.udig.project.internal.render.RenderExecutor;
028: import net.refractions.udig.project.internal.render.RenderFactory;
029: import net.refractions.udig.project.internal.render.RenderPackage;
030: import net.refractions.udig.project.internal.render.SelectionLayer;
031: import net.refractions.udig.project.internal.render.impl.CompositeRenderContextImpl;
032: import net.refractions.udig.project.internal.render.impl.CompositeRendererImpl;
033: import net.refractions.udig.project.internal.render.impl.RenderExecutorComposite;
034: import net.refractions.udig.project.internal.render.impl.RenderExecutorMultiLayer;
035: import net.refractions.udig.project.internal.render.impl.RenderManagerImpl;
036: import net.refractions.udig.project.render.IRenderContext;
037: import net.refractions.udig.project.render.IRenderer;
038: import net.refractions.udig.project.render.RenderException;
039: import net.refractions.udig.project.render.displayAdapter.IMapDisplay;
040: import net.refractions.udig.project.ui.render.displayAdapter.ViewportPane;
041: import net.refractions.udig.ui.PlatformGIS;
042:
043: import org.eclipse.core.runtime.ISafeRunnable;
044: import org.eclipse.emf.common.notify.Adapter;
045: import org.eclipse.emf.common.notify.Notification;
046: import org.eclipse.emf.common.notify.NotificationChain;
047: import org.eclipse.emf.ecore.EObject;
048: import org.eclipse.emf.ecore.impl.ENotificationImpl;
049: import org.eclipse.swt.widgets.Display;
050: import org.geotools.geometry.jts.ReferencedEnvelope;
051:
052: import com.vividsolutions.jts.geom.Envelope;
053:
054: /**
055: * An implementation of IRenderManager that is reacts to events such as viewport model changes.
056: *
057: * @generated
058: */
059: public class RenderManagerDynamic extends RenderManagerImpl {
060:
061: ContextModelListenerAdapter contextModelAdapter = RenderManagerAdapters
062: .createContextModelListener(this );
063:
064: Adapter viewportListener = RenderManagerAdapters
065: .createViewportListener(this );
066:
067: private Adapter viewportModelChangeListener = RenderManagerAdapters
068: .createViewportModelChangeListener(this , viewportListener,
069: contextModelAdapter);
070:
071: /**
072: * <!-- begin-user-doc --> <!-- end-user-doc -->
073: *
074: * @generated NOT
075: */
076: @SuppressWarnings("unchecked")
077: public RenderManagerDynamic() {
078: super ();
079: eAdapters().add(viewportModelChangeListener);
080: }
081:
082: /**
083: * @see net.refractions.udig.project.render.impl.RenderManagerImpl#refresh(net.refractions.udig.project.Layer)
084: */
085: public void refresh(final ILayer layer, final Envelope bounds) {
086: if (Display.getCurrent() != null) {
087: PlatformGIS.run(new ISafeRunnable() {
088:
089: public void handleException(Throwable exception) {
090: ProjectUIPlugin.log("", exception); //$NON-NLS-1$
091: }
092:
093: public void run() throws Exception {
094: doInternalRefresh(layer, bounds);
095: }
096:
097: });
098: } else {
099: doInternalRefresh(layer, bounds);
100: }
101: }
102:
103: private void doInternalRefresh(final ILayer layer,
104: final Envelope bounds) {
105: checkState();
106: if (getMapDisplay() == null || getRenderExecutor() == null)
107: return;
108:
109: getRendererCreator().reset();
110: validateRendererConfiguration();
111:
112: final SelectionLayer selectionLayer = getRendererCreator()
113: .findSelectionLayer(layer);
114:
115: getRenderExecutor().visit(new ExecutorVisitor() {
116: public void visit(RenderExecutor executor) {
117: if (executor.getContext().getLayer() == layer
118: || selectionLayer == executor.getContext()
119: .getLayer()) {
120: executor.getRenderer().setRenderBounds(bounds);
121: executor.getRenderer().setState(
122: IRenderer.RENDER_REQUEST);
123: }
124: }
125:
126: public void visit(RenderExecutorMultiLayer executor) {
127: if (executor.getContext().getLayers().contains(layer)
128: || executor.getContext().getLayers().contains(
129: selectionLayer))
130: executor.getRenderer().setState(
131: IRenderer.RENDER_REQUEST);
132: }
133:
134: public void visit(RenderExecutorComposite executor) {
135: List<RenderExecutor> executors = new ArrayList<RenderExecutor>(
136: executor.getRenderer().getRenderExecutors());
137: for (RenderExecutor child : executors)
138: child.visit(this );
139: }
140: });
141: }
142:
143: /**
144: * @see net.refractions.udig.project.render.impl.RenderManagerImpl#refreshSelection(com.vividsolutions.jts.geom.Envelope)
145: */
146: public void refreshSelection(final ILayer layer,
147: final Envelope bounds) {
148: if (Display.getCurrent() != null) {
149: PlatformGIS.run(new ISafeRunnable() {
150:
151: public void handleException(Throwable exception) {
152: ProjectUIPlugin.log("", exception); //$NON-NLS-1$
153: }
154:
155: public void run() throws Exception {
156: doInternalRefreshSelection(layer, bounds);
157: }
158:
159: });
160: } else {
161: doInternalRefreshSelection(layer, bounds);
162: }
163: }
164:
165: private void doInternalRefreshSelection(final ILayer layer,
166: final Envelope bounds) {
167:
168: checkState();
169: if (getMapDisplay() == null || getRenderExecutor() == null)
170: return;
171:
172: final Layer selectionLayer = getRendererCreator()
173: .findSelectionLayer(layer);
174:
175: if (selectionLayer == null)
176: return;
177:
178: getRendererCreator().reset();
179: validateRendererConfiguration();
180:
181: getRenderExecutor().visit(new ExecutorVisitor() {
182: public void visit(RenderExecutor executor) {
183: IRenderContext context = executor.getContext();
184: if (selectionLayer == context.getLayer()) {
185: executor.getRenderer().setRenderBounds(bounds);
186: if (bounds != null) {
187: Rectangle bounds2 = context.toShape(
188: new ReferencedEnvelope(bounds,
189: getViewportModelInternal()
190: .getCRS())).getBounds();
191: context.clearImage(bounds2);
192: } else {
193: context.clearImage();
194: }
195: executor.getRenderer().setState(
196: IRenderer.RENDER_REQUEST);
197: }
198: }
199:
200: public void visit(RenderExecutorMultiLayer executor) {
201: CompositeRenderContext contexts = executor.getContext();
202: for (IRenderContext context : contexts.getContexts()) {
203: if (context.getLayer() == selectionLayer) {
204: executor.getRenderer().setState(
205: IRenderer.RENDER_REQUEST);
206: return;
207: }
208: }
209: }
210:
211: public void visit(RenderExecutorComposite executor) {
212: for (RenderExecutor child : executor.getRenderer()
213: .getRenderExecutors())
214: child.visit(this );
215: }
216: });
217: }
218:
219: /**
220: * @see net.refractions.udig.project.render.IRenderManager#clearSelection(ILayer)
221: */
222: public void clearSelection(ILayer layer) {
223: checkState();
224: if (getMapDisplay() == null || getRenderExecutor() == null)
225: return;
226: final Layer selectionLayer = getRendererCreator()
227: .findSelectionLayer(layer);
228:
229: if (selectionLayer == null)
230: return;
231:
232: try {
233: CompositeRendererImpl compositeRendererImpl = (CompositeRendererImpl) getRenderExecutor()
234: .getRenderer();
235: compositeRendererImpl.refreshImage();
236: compositeRendererImpl.setState(IRenderer.DONE);
237:
238: } catch (RenderException e) {
239: ProjectUIPlugin.log("", e); //$NON-NLS-1$
240: }
241: }
242:
243: /**
244: * <!-- begin-user-doc --> <!-- end-user-doc -->
245: *
246: * @generated NOT
247: */
248: @SuppressWarnings("unchecked")
249: public void refresh(final Envelope bounds) {
250: if (Display.getCurrent() != null) {
251: PlatformGIS.run(new ISafeRunnable() {
252:
253: public void handleException(Throwable exception) {
254: ProjectUIPlugin.log("", exception); //$NON-NLS-1$
255: }
256:
257: public void run() throws Exception {
258: doInternalRefresh(bounds);
259: }
260:
261: });
262: } else {
263: doInternalRefresh(bounds);
264: }
265: }
266:
267: @SuppressWarnings("unchecked")
268: private void doInternalRefresh(Envelope bounds) {
269: checkState();
270: getViewportModelInternal().setInitialized(true);
271: if (getMapDisplay() == null) {
272: return;
273: }
274: if (getMapDisplay().getWidth() < 1
275: || getMapDisplay().getHeight() < 1)
276: return;
277:
278: getRendererCreator().reset();
279: validateRendererConfiguration();
280:
281: if (!getMapInternal().getContextModel().eAdapters().contains(
282: contextModelAdapter))
283: getMapInternal().getContextModel().eAdapters().add(
284: contextModelAdapter);
285:
286: try {
287: getRenderExecutor().setRenderBounds(bounds);
288: getRenderExecutor().render();
289: } catch (RenderException e) {
290: // Won't happen
291: }
292: }
293:
294: void initRenderCreator(RenderContext context) {
295: checkState();
296: List<Layer> layers = getMapInternal().getLayersInternal();
297: // make sure renderer creator is initialized.
298: getRendererCreator().setContext(context);
299: ENotificationImpl notification = new ENotificationImpl(this ,
300: Notification.ADD_MANY,
301: ProjectPackage.CONTEXT_MODEL__LAYERS, null, layers);
302: getRendererCreator().changed(notification);
303:
304: }
305:
306: /**
307: * <!-- begin-user-doc --> <!-- end-user-doc -->
308: *
309: * @generated NOT
310: */
311: @SuppressWarnings("unchecked")
312: public void dispose() {
313: configuration = null;
314: Set<EObject> set = new HashSet<EObject>();
315: set.add(getMapInternal());
316: Iterator<EObject> iter = getMapInternal().eAllContents();
317: while (iter.hasNext()) {
318: EObject obj = iter.next();
319: removeAdapters(obj);
320: }
321: removeAdapters(getRenderExecutor());
322: ((ViewportPane) mapDisplay).setRenderManager(null);
323: super .dispose();
324: }
325:
326: /**
327: * @param obj
328: */
329: private void removeAdapters(EObject obj) {
330: obj.eAdapters().remove(this .viewportListener);
331: obj.eAdapters().remove(this .viewportModelChangeListener);
332: obj.eAdapters().remove(this .contextModelAdapter);
333: obj.eAdapters().remove(this .renderExecutorListener);
334: obj.eAdapters().remove(this .selectionListener);
335: }
336:
337: /**
338: * <!-- begin-user-doc --> <!-- end-user-doc -->
339: *
340: * @generated
341: */
342: public void setDisplayGen(IMapDisplay newDisplay) {
343: IMapDisplay oldDisplay = mapDisplay;
344: mapDisplay = newDisplay;
345: if (eNotificationRequired())
346: eNotify(new ENotificationImpl(this , Notification.SET,
347: RenderPackage.RENDER_MANAGER__MAP_DISPLAY,
348: oldDisplay, mapDisplay));
349: }
350:
351: /**
352: * TODO summary sentence for setViewport ...
353: *
354: * @see net.refractions.udig.project.render.RenderManager#setDisplay(net.refractions.udig.project.render.displayAdapter.IMapDisplay)
355: * @param value
356: */
357: public void setDisplay(IMapDisplay value) {
358: checkState();
359: ((ViewportPane) value).setRenderManager(this );
360: setDisplayGen(value);
361: }
362:
363: Adapter renderExecutorListener = RenderManagerAdapters
364: .getRenderExecutorListener(this );
365:
366: /**
367: * @see net.refractions.udig.project.render.impl.RenderManagerImpl#setRenderExecutor(net.refractions.udig.project.render.RenderExecutor)
368: */
369: @SuppressWarnings("unchecked")
370: public void setRenderExecutor(RenderExecutor newRenderExecutor) {
371: checkState();
372: if (renderExecutor != null) {
373: renderExecutor.eAdapters().remove(renderExecutorListener);
374: }
375: if (newRenderExecutor != null
376: && !newRenderExecutor.eAdapters().contains(
377: renderExecutorListener)) {
378: newRenderExecutor.eAdapters().add(renderExecutorListener);
379: }
380: super .setRenderExecutor(newRenderExecutor);
381: }
382:
383: Adapter selectionListener = RenderManagerAdapters
384: .createLayerListener(this );
385:
386: /**
387: * @see net.refractions.udig.project.render.impl.RenderManagerImpl#basicSetMap(net.refractions.udig.project.Map,
388: * org.eclipse.emf.common.notify.NotificationChain)
389: */
390: @SuppressWarnings("unchecked")
391: public NotificationChain basicSetMapInternal(Map newMap,
392: NotificationChain msgs) {
393: if (getMapInternal() != null) {
394: getMapInternal().eAdapters().remove(selectionListener);
395: getMapInternal().removeDeepAdapter(selectionListener);
396: }
397: if (newMap != null) {
398: newMap.eAdapters().add(selectionListener);
399: newMap.addDeepAdapter(selectionListener);
400: }
401: return super .basicSetMapInternal(newMap, msgs);
402: }
403:
404: public volatile Collection<RenderContext> configuration = null;
405:
406: /**
407: * Ensures that the current configuration of renderer is a valid choice. For example the each of
408: * the layers in the map has a renderer that can render it.
409: */
410: public void validateRendererConfiguration() {
411: checkState();
412: Collection<RenderContext> configuration;
413: synchronized (this ) {
414: if (this .configuration == null) {
415: configuration = null;
416: } else {
417: configuration = new ArrayList<RenderContext>(
418: this .configuration);
419: }
420: }
421: Collection<RenderContext> configuration2;
422: if (configuration != null) {
423: configuration2 = getRendererCreator().getConfiguration();
424: List<RenderContext> removeList = new ArrayList<RenderContext>();
425: List<RenderContext> addList = new ArrayList<RenderContext>();
426: for (IRenderContext context : configuration) {
427: if (!configuration2.contains(context))
428: removeList.add((RenderContext) context);
429: }
430: for (RenderContext context : configuration2) {
431: if (configuration.contains(context))
432: continue;
433:
434: addList.add(context);
435: }
436: CompositeRenderContext compositecontext = (CompositeRenderContext) getRenderExecutor()
437: .getContext();
438: compositecontext.removeContexts(removeList);
439: if (!addList.isEmpty())
440: compositecontext.removeContexts(addList);
441: compositecontext.addContexts(addList);
442:
443: } else {
444: initRenderExecutor();
445: configuration2 = getRendererCreator().getConfiguration();
446:
447: CompositeRenderContext compositecontext = (CompositeRenderContext) getRenderExecutor()
448: .getContext();
449: // need this because this is taking place in a non-synchronized block so it is possible for
450: // this code to be executed twice. I want the second run to be accurate.
451: // might need to be thought about more.
452: compositecontext.clear();
453: compositecontext.addContexts(configuration2);
454: }
455: synchronized (this ) {
456: this .configuration = configuration2;
457: }
458: logRendererTypes();
459:
460: }
461:
462: /**
463: *
464: */
465: private void initRenderExecutor() {
466: checkState();
467: MultiLayerRenderer renderExecutor = RenderFactory.eINSTANCE
468: .createCompositeRenderer();
469: CompositeRenderContext context = new CompositeRenderContextImpl() {
470: @Override
471: public synchronized BufferedImage getImage(int width,
472: int height) {
473: if (image == null || image.getWidth() < width
474: || image.getHeight() < height) {
475: image = new BufferedImage(width, height,
476: BufferedImage.TYPE_3BYTE_BGR);
477: Graphics2D g = image.createGraphics();
478: g.setBackground(Color.WHITE);
479: g.clearRect(0, 0, width, height);
480: g.dispose();
481: }
482:
483: return image;
484: }
485:
486: @Override
487: public synchronized void clearImage(Rectangle paintArea) {
488: if (image == null)
489: return;
490: Graphics2D g = image.createGraphics();
491: g.setBackground(Color.WHITE);
492: g.clearRect(paintArea.x, paintArea.y, paintArea.width,
493: paintArea.height);
494: g.dispose();
495: //// FIXME Arbonaut Oy , Vitali Diatchkov
496: // System.out.println("synchronized CompositeRenderContext.clearImage()");
497: }
498:
499: };
500: context.setMapInternal(getMapInternal());
501: context.setRenderManagerInternal(this );
502: renderExecutor.setContext(context);
503:
504: initRenderCreator(context);
505:
506: renderExecutor.setName(Messages.RenderManagerDynamic_allLayers);
507: setRenderExecutor(RenderFactory.eINSTANCE
508: .createRenderExecutor(renderExecutor));
509: }
510:
511: private void logRendererTypes() {
512: if (ProjectUIPlugin.isDebugging(RENDER)) {
513:
514: final StringBuffer log = new StringBuffer(
515: "Current Renderers:"); //$NON-NLS-1$
516: getRenderExecutor().visit(new ExecutorVisitor() {
517: public void visit(RenderExecutor executor) {
518: log
519: .append("\n\t" + executor.getClass().getSimpleName() + ":" + //$NON-NLS-1$ //$NON-NLS-2$
520: executor.getRenderer().getClass()
521: .getSimpleName()
522: + "-" + //$NON-NLS-1$
523: executor.getContext().getLayer()
524: .getName());
525: }
526:
527: public void visit(RenderExecutorComposite executor) {
528: log
529: .append("\n\t" + executor.getRenderer().getClass().getSimpleName()); //$NON-NLS-1$
530: for (RenderExecutor child : executor.getRenderer()
531: .getRenderExecutors())
532: child.visit(this );
533: }
534:
535: public void visit(RenderExecutorMultiLayer executor) {
536: log
537: .append("\n\t" + executor.getRenderer().getClass().getSimpleName()); //$NON-NLS-1$
538: }
539: });
540: System.out.println(log);
541: }
542: }
543:
544: /**
545: * <!-- begin-user-doc --> <!-- end-user-doc -->
546: *
547: * @generated
548: */
549: public RenderExecutor getRenderExecutor() {
550: checkState();
551: if (renderExecutor == null) {
552: initRenderExecutor();
553: }
554:
555: return renderExecutor;
556: }
557: } // RenderManagerImpl
|