001: /**
002: * <copyright></copyright> $Id: CompositeRendererImpl.java 25356 2007-04-27 04:46:44Z jeichar $
003: */package net.refractions.udig.project.internal.render.impl;
004:
005: import java.awt.AlphaComposite;
006: import java.awt.Color;
007: import java.awt.Dimension;
008: import java.awt.Graphics2D;
009: import java.awt.Rectangle;
010: import java.awt.geom.AffineTransform;
011: import java.awt.image.BufferedImage;
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.Comparator;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Set;
018: import java.util.SortedSet;
019: import java.util.TreeSet;
020: import java.util.concurrent.CopyOnWriteArraySet;
021:
022: import net.refractions.udig.project.IMap;
023: import net.refractions.udig.project.ProjectBlackboardConstants;
024: import net.refractions.udig.project.internal.ProjectPlugin;
025: import net.refractions.udig.project.internal.render.CompositeRenderContext;
026: import net.refractions.udig.project.internal.render.MultiLayerRenderer;
027: import net.refractions.udig.project.internal.render.RenderContext;
028: import net.refractions.udig.project.internal.render.RenderExecutor;
029: import net.refractions.udig.project.internal.render.RenderFactory;
030: import net.refractions.udig.project.internal.render.RenderListenerAdapter;
031: import net.refractions.udig.project.internal.render.RenderManager;
032: import net.refractions.udig.project.internal.render.Renderer;
033: import net.refractions.udig.project.internal.render.RendererCreator;
034: import net.refractions.udig.project.preferences.PreferenceConstants;
035: import net.refractions.udig.project.render.ILabelPainter;
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:
040: import org.eclipse.core.runtime.IProgressMonitor;
041: import org.eclipse.emf.common.notify.Notification;
042: import org.eclipse.emf.ecore.EObject;
043: import org.eclipse.jface.preference.IPreferenceStore;
044: import org.eclipse.jface.preference.PreferenceConverter;
045: import org.eclipse.swt.graphics.RGB;
046:
047: /**
048: * <ul>
049: * <li>Combines the output from several renderer into a single image.</li>
050: * <li>Listens to its context (CompositeContext) and creates new RenderExecutors when required.</li>
051: *
052: * @author Jesse
053: * @since 1.0.0
054: */
055: public class CompositeRendererImpl extends RendererImpl implements
056: MultiLayerRenderer {
057:
058: /**
059: * <!-- begin-user-doc --> <!-- end-user-doc -->
060: *
061: * @generated
062: */
063: public static final String copyright = "uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004, Refractions Research Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details."; //$NON-NLS-1$
064:
065: private final static Comparator<? super RenderExecutor> comparator = new Comparator<RenderExecutor>() {
066:
067: public int compare(RenderExecutor e1, RenderExecutor e2) {
068:
069: return e1.getContext().getLayer().compareTo(
070: e2.getContext().getLayer());
071:
072: }
073: };
074: private final Set<RenderExecutor> renderExecutors;
075: {
076: renderExecutors = new CopyOnWriteArraySet<RenderExecutor>();
077: }
078:
079: static final AffineTransform IDENTITY = new AffineTransform();
080:
081: /**
082: * @see net.refractions.udig.project.internal.render.MultiLayerRenderer#children()
083: */
084: public List<Renderer> children() {
085: List<Renderer> children = new ArrayList<Renderer>();
086: for (RenderExecutor victim : getRenderExecutors()) {
087: children.add(victim.getRenderer());
088: }
089: return children;
090: }
091:
092: CompositeContextListener contextListener = new CompositeContextListener() {
093:
094: private void remove(List<RenderContext> contexts) {
095: for (RenderContext context : contexts) {
096: RenderExecutor executor = findExecutor(context);
097: if (executor != null) {
098: getRenderExecutors().remove(executor);
099: executor.dispose();
100: }
101: }
102: }
103:
104: private void add(List<RenderContext> contexts) {
105: List<RenderExecutor> renderers = new ArrayList<RenderExecutor>();
106: for (RenderContext context : contexts) {
107: if (findExecutor(context) == null) {
108: Renderer renderer = getRendererCreator(context)
109: .getRenderer(context);
110: renderers.add(createRenderExecutor(renderer));
111: }
112: }
113: if (!renderers.isEmpty()) {
114: getRenderExecutors().addAll(renderers);
115: }
116: }
117:
118: public void notifyChanged(CompositeRenderContext context,
119: List<RenderContext> contexts, boolean added) {
120: if (added) {
121: add(contexts);
122: } else {
123: remove(contexts);
124: }
125: }
126: };
127:
128: /**
129: * @see net.refractions.udig.project.internal.render.impl.RendererImpl#getContext()
130: */
131: public CompositeRenderContext getContext() {
132: return (CompositeRenderContext) super .getContext();
133: }
134:
135: /**
136: * <!-- begin-user-doc --> <!-- end-user-doc -->
137: *
138: * @generated NOT
139: */
140: protected CompositeRendererImpl() {
141: super ();
142: }
143:
144: /**
145: * Called to remove the corresponding RenderExecutor from the list of RenderExecutors.
146: *
147: * @param renderer the renderer that has been removed
148: */
149: protected RenderExecutor findExecutor(IRenderContext context) {
150: for (Iterator<RenderExecutor> eIter = getRenderExecutors()
151: .iterator(); eIter.hasNext();) {
152: RenderExecutor executor = (RenderExecutor) eIter.next();
153: if (executor.getRenderer().getContext().equals(context))
154: return executor;
155: }
156: return null;
157: }
158:
159: /**
160: * @param renderer
161: */
162: @SuppressWarnings("unchecked")
163: protected RenderExecutor createRenderExecutor(Renderer renderer) {
164: final RenderExecutor executor = RenderFactory.eINSTANCE
165: .createRenderExecutor(renderer);
166: executor.eAdapters().add(new RenderListenerAdapter() {
167:
168: /**
169: * @see net.refractions.udig.project.internal.render.RenderListenerAdapter#renderDisposed(org.eclipse.emf.common.notify.Notification)
170: */
171: protected void renderDisposed(Notification msg) {
172: EObject obj = (EObject) getTarget();
173: obj.eAdapters().remove(this );
174: }
175:
176: @Override
177: protected void renderStarting() {
178: // setState(STARTING);
179: }
180:
181: /**
182: * @see net.refractions.udig.project.internal.render.RenderListenerAdapter#renderUpdate()
183: */
184: protected void renderUpdate() {
185: synchronized (CompositeRendererImpl.this ) {
186: // try {
187: // refreshImage();
188: setState(RENDERING);
189: // } catch (RenderException e) {
190: // // TODO Catch e
191: // }
192: }
193: }
194:
195: /**
196: * @see net.refractions.udig.project.internal.render.RenderListenerAdapter#renderDone()
197: */
198: protected void renderDone() {
199: setState(DONE);
200: }
201:
202: protected void renderRequest() {
203: setRenderBounds(executor.getRenderBounds());
204: setState(RENDER_REQUEST);
205: }
206: });
207: return executor;
208: }
209:
210: /**
211: * <!-- begin-user-doc --> <!-- end-user-doc -->
212: *
213: * @throws RenderException
214: * @generated NOT
215: */
216: public void refreshImage() throws RenderException {
217: synchronized (getContext()) {
218: Graphics2D g = null;
219: try {
220: getContext().clearImage();
221: BufferedImage image = getContext().getImage();
222: g = image.createGraphics();
223: IMap map = getContext().getMap();
224: Object object = map
225: .getBlackboard()
226: .get(
227: ProjectBlackboardConstants.MAP__BACKGROUND_COLOR);
228: if (object == null) {
229: IPreferenceStore store = ProjectPlugin.getPlugin()
230: .getPreferenceStore();
231: RGB background = PreferenceConverter.getColor(
232: store, PreferenceConstants.P_BACKGROUND);
233: map
234: .getBlackboard()
235: .put(
236: ProjectBlackboardConstants.MAP__BACKGROUND_COLOR,
237: new Color(background.red,
238: background.green,
239: background.blue));
240: object = map
241: .getBlackboard()
242: .get(
243: ProjectBlackboardConstants.MAP__BACKGROUND_COLOR);
244: }
245: g.setBackground((Color) object);
246: g.clearRect(0, 0, getContext().getMapDisplay()
247: .getWidth(), getContext().getMapDisplay()
248: .getHeight());
249: SortedSet<RenderExecutor> executors;
250: synchronized (renderExecutors) {
251: executors = new TreeSet<RenderExecutor>(comparator);
252: executors.addAll(getRenderExecutors());
253: }
254: RENDERERS: for (RenderExecutor executor : executors) {
255: if (!executor.getContext().isVisible())
256: continue RENDERERS;
257:
258: int executorState = executor.getRenderer()
259: .getState();
260:
261: if (executor.getState() == NEVER
262: || executor.getState() == STARTING
263: || executor.getState() == RENDER_REQUEST) {
264: // executor.render();
265: continue RENDERERS;
266: }
267: if (isFullAlphaUsed(executor)) {
268: g.setComposite(AlphaComposite.getInstance(
269: AlphaComposite.SRC_OVER, 1.0f));
270: } else {
271: g.setComposite(AlphaComposite.getInstance(
272: AlphaComposite.SRC_OVER, 0.5f));
273: }
274: g.drawRenderedImage(executor.getContext()
275: .getImage(), IDENTITY);
276: }
277: ILabelPainter cache = getContext().getLabelPainter();
278: Dimension displaySize = getContext().getMapDisplay()
279: .getDisplaySize();
280: cache.end(g, new Rectangle(displaySize));
281:
282: } catch (IllegalStateException e) {
283: stopRendering();
284: // e.printStackTrace();
285: return;
286: } finally {
287: if (g != null)
288: g.dispose();
289: }
290: }
291:
292: }
293:
294: private boolean isFullAlphaUsed(RenderExecutor executor) {
295:
296: Object object = getContext().getMap().getBlackboard().get(
297: "MYLAR"); //$NON-NLS-1$
298:
299: if (object == null || !((Boolean) object).booleanValue())
300: return true;
301:
302: if (executor.getContext() instanceof CompositeRenderContext) {
303: CompositeRenderContext context = (CompositeRenderContext) executor
304: .getContext();
305: if (context.getLayers().contains(
306: getContext().getSelectedLayer()))
307: return true;
308:
309: return false;
310: }
311:
312: if (executor.getContext().getLayer() == getContext()
313: .getSelectedLayer())
314: return true;
315:
316: return false;
317: }
318:
319: /**
320: * <!-- begin-user-doc --> <!-- end-user-doc -->
321: *
322: * @throws RenderException
323: * @generated NOT
324: */
325: public void render(Graphics2D destination, IProgressMonitor monitor)
326: throws RenderException {
327: // notify that they are starting
328: for (RenderExecutor executor : renderExecutors) {
329: executor.getRenderer().setState(STARTING);
330: }
331: for (RenderExecutor executor : renderExecutors) {
332: executor.render();
333: }
334: }
335:
336: // /**
337: // * <!-- begin-user-doc --> <!-- end-user-doc -->
338: // *
339: // * @throws RenderException
340: // * @generated NOT
341: // */
342: // public synchronized void render( IProgressMonitor monitor ) throws RenderException {
343: // if (getRenderExecutors().size() == 0)
344: // setState(DONE);
345: // for( Iterator iter = getRenderExecutors().iterator(); iter.hasNext(); ) {
346: // RenderExecutor executor = (RenderExecutor) iter.next();
347: // executor.render((Envelope) null, monitor);
348: // }
349: // }
350:
351: /**
352: * @see net.refractions.udig.project.internal.render.impl.RendererImpl#setContext(net.refractions.udig.project.render.RenderContext)
353: */
354: @SuppressWarnings("unchecked")
355: public void setContext(IRenderContext newContext) {
356: if (context != null) {
357: ((CompositeRenderContext) context)
358: .removeListener(contextListener);
359: }
360: if (newContext != null) {
361: CompositeRenderContext compositeRenderContext = (CompositeRenderContext) newContext;
362: compositeRenderContext.addListener(contextListener);
363: for (IRenderContext context : compositeRenderContext
364: .getContexts()) {
365: if (findExecutor(context) == null) {
366: Renderer renderer = getRendererCreator(context)
367: .getRenderer((RenderContext) context);
368: getRenderExecutors().add(
369: createRenderExecutor(renderer));
370: }
371: }
372: super .setContext(newContext);
373: }
374: }
375:
376: /**
377: * <!-- begin-user-doc --> <!-- end-user-doc -->
378: *
379: * @generated NOT
380: */
381: public void stopRendering() {
382: for (Iterator iter = getRenderExecutors().iterator(); iter
383: .hasNext();) {
384: ((RenderExecutor) iter.next()).stopRendering();
385: }
386: }
387:
388: /**
389: * <!-- begin-user-doc --> <!-- end-user-doc -->
390: *
391: * @uml.property name="renderExecutors"
392: * @generated NOT
393: */
394: public Collection<RenderExecutor> getRenderExecutors() {
395: return renderExecutors;
396: }
397:
398: RendererCreator rendererCreator = null;
399:
400: RendererCreator getRendererCreator(IRenderContext context) {
401: rendererCreator = ((RenderManager) context.getRenderManager())
402: .getRendererCreator();
403: rendererCreator.setContext((RenderContext) context);
404: return rendererCreator;
405: }
406:
407: /**
408: * @see net.refractions.udig.project.internal.render.impl.RendererImpl#dispose()
409: */
410: public synchronized void dispose() {
411: for (Iterator iter = getRenderExecutors().iterator(); iter
412: .hasNext();) {
413: Renderer renderer = (Renderer) iter.next();
414: renderer.dispose();
415: }
416: getRenderExecutors().clear();
417: }
418:
419: /**
420: * @see net.refractions.udig.project.internal.render.Renderer#getInfo(java.awt.Point,
421: * net.refractions.udig.project.Layer) public InfoList getInfo(Point screenLocation) throws
422: * IOException { InfoList infos = new InfoList(screenLocation); Iterator iter =
423: * getRenderExecutors().iterator(); while (iter.hasNext()) { Renderer renderer =
424: * ((RenderExecutor) iter.next()); List results = renderer.getInfo(screenLocation); if
425: * (results != null) { infos.addAll(results); } } return infos; }
426: */
427:
428: /**
429: * @throws RenderException
430: * @see net.refractions.udig.project.internal.render.Renderer#render(com.vividsolutions.jts.geom.Envelope)
431: */
432: public void render(IProgressMonitor monitor) throws RenderException {
433: if (getRenderExecutors().size() == 0)
434: setState(DONE);
435: for (Iterator iter = getRenderExecutors().iterator(); iter
436: .hasNext();) {
437: RenderExecutor executor = (RenderExecutor) iter.next();
438: executor.setRenderBounds(getRenderBounds());
439: executor.render();
440: }
441: }
442:
443: /**
444: * @see net.refractions.udig.project.render.IMultiLayerRenderer#getIChildren()
445: */
446: public List getIChildren() {
447: return children();
448: }
449:
450: /**
451: * @see net.refractions.udig.project.render.IMultiLayerRenderer#getIContext()
452: */
453: public IRenderContext getIContext() {
454: return getContext();
455: }
456:
457: } // CompositeRendererImpl
|