001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.printing.model.impl;
016:
017: import java.awt.Color;
018: import java.awt.Graphics2D;
019: import java.awt.geom.Rectangle2D;
020: import java.awt.image.BufferedImage;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.SortedSet;
024: import java.util.TreeSet;
025:
026: import net.refractions.udig.printing.model.AbstractBoxPrinter;
027: import net.refractions.udig.printing.model.PrintingModelPlugin;
028: import net.refractions.udig.printing.model.internal.Messages;
029: import net.refractions.udig.project.ILayer;
030: import net.refractions.udig.project.IMap;
031: import net.refractions.udig.project.IMapCompositionListener;
032: import net.refractions.udig.project.IMapListener;
033: import net.refractions.udig.project.IProject;
034: import net.refractions.udig.project.MapCompositionEvent;
035: import net.refractions.udig.project.MapEvent;
036: import net.refractions.udig.project.internal.Map;
037: import net.refractions.udig.project.internal.render.CompositeRenderContext;
038: import net.refractions.udig.project.internal.render.RenderContext;
039: import net.refractions.udig.project.internal.render.RenderFactory;
040: import net.refractions.udig.project.internal.render.RenderManager;
041: import net.refractions.udig.project.internal.render.Renderer;
042: import net.refractions.udig.project.internal.render.RendererCreator;
043: import net.refractions.udig.project.internal.render.ViewportModel;
044: import net.refractions.udig.project.internal.render.impl.RenderContextImpl;
045: import net.refractions.udig.project.internal.render.impl.RendererCreatorImpl;
046: import net.refractions.udig.project.render.IViewportModel;
047: import net.refractions.udig.project.render.IViewportModelListener;
048: import net.refractions.udig.project.render.RenderException;
049: import net.refractions.udig.project.render.ViewportModelEvent;
050: import net.refractions.udig.project.render.displayAdapter.IMapDisplay;
051: import net.refractions.udig.project.render.displayAdapter.MapDisplayEvent;
052: import net.refractions.udig.project.ui.ApplicationGIS;
053:
054: import org.eclipse.core.runtime.IAdaptable;
055: import org.eclipse.core.runtime.IProgressMonitor;
056: import org.eclipse.draw2d.geometry.Dimension;
057: import org.eclipse.emf.common.util.URI;
058: import org.eclipse.emf.ecore.util.EcoreUtil;
059: import org.eclipse.jface.util.PropertyChangeEvent;
060: import org.eclipse.ui.IMemento;
061: import org.opengis.referencing.crs.CoordinateReferenceSystem;
062:
063: import com.vividsolutions.jts.geom.Envelope;
064:
065: /**
066: * Box Printer for MapBox objects.
067: *
068: * @author Jesse
069: * @since 1.1.0
070: */
071: public class MapBoxPrinter extends AbstractBoxPrinter implements
072: IAdaptable {
073: Map map;
074:
075: IMapCompositionListener layerListener = new IMapCompositionListener() {
076:
077: public void changed(MapCompositionEvent event) {
078: getBox()
079: .notifyPropertyChange(
080: new PropertyChangeEvent(
081: MapBoxPrinter.this ,
082: "layers", event.getOldValue(), event.getNewValue())); //$NON-NLS-1$
083: }
084:
085: };
086:
087: IViewportModelListener viewportListener = new IViewportModelListener() {
088:
089: public void changed(ViewportModelEvent event) {
090: getBox()
091: .notifyPropertyChange(
092: new PropertyChangeEvent(
093: MapBoxPrinter.this ,
094: "viewport", event.getOldValue(), event.getNewValue())); //$NON-NLS-1$
095: }
096: };
097:
098: IMapListener mapListener = new IMapListener() {
099:
100: public void changed(MapEvent event) {
101: switch (event.getType()) {
102: case VIEWPORT_MODEL:
103: if (event.getNewValue() != null) {
104: ((ViewportModel) event.getNewValue())
105: .addViewportModelListener(viewportListener);
106: }
107: if (event.getOldValue() != null) {
108: ((ViewportModel) event.getOldValue())
109: .removeViewportModelListener(viewportListener);
110: }
111: break;
112:
113: default:
114: break;
115: }
116: }
117:
118: };
119:
120: public Map getMap() {
121: return map;
122: }
123:
124: @SuppressWarnings("unchecked")
125: public void setMap(IMap map2) {
126: Map oldMap = map;
127: if (oldMap != null) {
128: oldMap.removeMapCompositionListener(layerListener);
129: oldMap.getViewportModel().removeViewportModelListener(
130: viewportListener);
131: oldMap.removeMapListener(mapListener);
132: }
133: this .map = (Map) map2;
134: if (map != null) {
135: map.addMapCompositionListener(layerListener);
136: map.getViewportModel().addViewportModelListener(
137: viewportListener);
138: map.addMapListener(mapListener);
139: }
140: }
141:
142: public void draw(Graphics2D graphics, IProgressMonitor monitor) {
143: try {
144: drawInternal(graphics, monitor);
145: } catch (RenderException e) {
146: PrintingModelPlugin.log(null, e);
147: }
148: }
149:
150: private void drawInternal(Graphics2D graphics,
151: IProgressMonitor monitor) throws RenderException {
152: if (map == null) {
153: drawErrorMessage(graphics,
154: Messages.MapBoxPrinter_no_map_set);
155: return;
156: }
157:
158: Map map = (Map) EcoreUtil.copy(this .map);
159: final Dimension size = getBox().getSize();
160: PrintingModelPlugin
161: .trace("MapBoxImpl.draw() beginning rendering of map '" + map.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
162:
163: RenderManager manager = RenderFactory.eINSTANCE
164: .createRenderManagerViewer();
165:
166: RenderContext tools = new RenderContextImpl();
167: tools.setMapInternal(map);
168: tools.setRenderManagerInternal(manager);
169:
170: PrintingModelPlugin
171: .trace("Firing size changed event. Changing to size: " + size.width + " by " + size.height); //$NON-NLS-1$ //$NON-NLS-2$
172:
173: manager.setMapInternal(map);
174: manager.setMapDisplay(new IMapDisplay() {
175: public java.awt.Dimension getDisplaySize() {
176: return new java.awt.Dimension(size.width, size.height);
177: }
178:
179: public int getWidth() {
180: return size.width;
181: }
182:
183: public int getHeight() {
184: return size.height;
185: }
186:
187: public int getDPI() {
188: // XXX What should this be Richard?
189: return 72;
190: }
191: });
192:
193: ViewportModel model = RenderFactory.eINSTANCE
194: .createViewportModel();
195:
196: manager.setViewportModelInternal(model);
197:
198: model.setCRS(map.getViewportModel().getCRS());
199: model.zoomToBox(map.getViewportModel().getBounds());
200:
201: PrintingModelPlugin
202: .trace("Using bounds: " + map.getViewportModel().getBounds()); //$NON-NLS-1$
203:
204: model.setMapInternal(map);
205:
206: model.sizeChanged(new MapDisplayEvent(null,
207: new java.awt.Dimension(0, 0), new java.awt.Dimension(
208: size.width, size.height)));
209:
210: RendererCreator decisive = new RendererCreatorImpl();
211: decisive.setContext(tools);
212:
213: decisive.getLayers().addAll(this .map.getLayersInternal());
214:
215: SortedSet<RenderContext> sortedContexts = new TreeSet<RenderContext>(
216: decisive.getConfiguration());
217:
218: Iterator iter = sortedContexts.iterator();
219: while (iter.hasNext()) {
220: RenderContext context = (RenderContext) iter.next();
221: if (context instanceof CompositeRenderContext) {
222: CompositeRenderContext compositeContext = (CompositeRenderContext) context;
223: List<ILayer> layers = compositeContext.getLayers();
224: boolean visible = false;
225: for (ILayer layer : layers) {
226: visible = layer.isVisible();
227: }
228: if (!visible)
229: continue;
230: } else if (!context.getLayer().isVisible())
231: continue;
232: Renderer renderer = decisive.getRenderer(context);
233: PrintingModelPlugin
234: .trace("Issuing render call to " + renderer.getName()); //$NON-NLS-1$
235: renderer.render(graphics, monitor);
236: }
237: }
238:
239: BufferedImage preview;
240: State current;
241:
242: public void createPreview(Graphics2D graphics,
243: final IProgressMonitor monitor) {
244: Dimension size = getBox().getSize();
245: preview = new BufferedImage(size.width, size.height,
246: BufferedImage.TYPE_INT_ARGB);
247: final Graphics2D g = preview.createGraphics();
248:
249: try {
250: drawInternal(g, monitor);
251: } catch (Exception e) {
252: PrintingModelPlugin.log("", e); //$NON-NLS-1$
253: String message = "Error rendering Map: " + e.getMessage(); //$NON-NLS-1$
254: drawErrorMessage(g, message);
255: }
256: g.dispose();
257: if (map != null)
258: current = new State(map.getViewportModel(), getBox()
259: .getSize());
260: graphics.drawImage(preview, 0, 0, size.width, size.height, 0,
261: 0, preview.getWidth(), preview.getHeight(), null);
262: }
263:
264: private void drawErrorMessage(Graphics2D g, String message) {
265: Dimension size = getBox().getSize();
266: g.setColor(Color.YELLOW);
267: Rectangle2D bounds = g.getFontMetrics().getStringBounds(
268: message, g);
269: g.fillRect((int) (size.width / 2 - bounds.getWidth() / 2) - 2,
270: (int) (size.height / 2 - bounds.getHeight() / 2) + 2,
271: (int) bounds.getWidth() + 4,
272: (int) bounds.getHeight() + 4);
273: g.setColor(Color.BLACK);
274: g.drawString(message,
275: (int) (size.width / 2 - bounds.getWidth() / 2),
276: (int) (size.height / 2 + bounds.getHeight() / 2));
277: }
278:
279: static class State {
280: private double aspectRatio;
281:
282: public State(IViewportModel viewportModel, Dimension size) {
283: bounds = viewportModel.getBounds();
284: crs = viewportModel.getCRS();
285: this .aspectRatio = (double) size.height
286: / (double) size.width;
287: }
288:
289: Envelope bounds;
290: CoordinateReferenceSystem crs;
291: }
292:
293: public boolean isNewPreviewNeeded() {
294: final Dimension size = getBox().getSize();
295: double aspectRatio = (double) size.height / (double) size.width;
296: return preview == null
297: || current == null
298: || !current.bounds.equals(map.getViewportModel()
299: .getBounds())
300: || current.crs != map.getViewportModel().getCRS()
301: || Math.abs(current.aspectRatio - aspectRatio) > 0.00001;
302: }
303:
304: public void save(IMemento memento) {
305: System.out.println(map.getID());
306: memento.putString("mapId", map.getID().toString()); //$NON-NLS-1$
307: memento.putString(
308: "projectId", map.getProject().getID().toString()); //$NON-NLS-1$
309: }
310:
311: public void load(IMemento value) {
312: URI mapId = URI.createURI(value.getString("mapId")); //$NON-NLS-1$
313: URI projectId = URI.createURI(value.getString("projectId")); //$NON-NLS-1$
314:
315: List<? extends IProject> projects = ApplicationGIS
316: .getProjects();
317:
318: for (IProject project : projects) {
319: if (project.getID().equals(projectId)) {
320: List<IMap> maps = project.getElements(IMap.class);
321: for (IMap map : maps) {
322: if (map.getID().equals(mapId)) {
323: setMap(map);
324: break;
325: }
326: }
327: }
328: }
329: }
330:
331: public String getExtensionPointID() {
332: return "net.refractions.udig.printing.ui.standardBoxes"; //$NON-NLS-1$
333: }
334:
335: @SuppressWarnings("unchecked")
336: public Object getAdapter(Class adapter) {
337: if (adapter.isAssignableFrom(Map.class)) {
338: return this.map;
339: }
340: return null;
341: }
342:
343: }
|