1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.foRenderer;
13
14 import java.io.IOException;
15 import java.util.HashMap;
16 import java.util.LinkedList;
17 import java.util.List;
18 import java.util.Queue;
19
20 import javax.xml.transform.Source;
21 import javax.xml.transform.TransformerException;
22 import javax.xml.transform.dom.DOMSource;
23
24 import org.apache.fop.apps.FOPException;
25 import org.eclipse.draw2d.Border;
26 import org.eclipse.draw2d.ColorConstants;
27 import org.eclipse.draw2d.FlowLayout;
28 import org.eclipse.draw2d.IFigure;
29 import org.eclipse.draw2d.geometry.Dimension;
30 import org.eclipse.draw2d.geometry.Point;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33
34 import sk.baka.ikslibs.DOMUtils;
35 import sk.baka.ikslibs.Namespaces;
36 import sk.baka.ikslibs.ids.IDManager;
37 import sk.baka.ikslibs.modify.IChangeCollector;
38 import sk.baka.ikslibs.splitted.SplittedDocHolder;
39 import sk.baka.xml.gene.ExportUtils;
40 import sk.uniba.euromath.document.XMLAccess;
41 import sk.uniba.euromath.editor.EditorException;
42 import sk.uniba.euromath.editor.IInputPreprocessor;
43 import sk.uniba.euromath.editor.IRenderer;
44 import sk.uniba.euromath.editor.RendererInfo;
45 import sk.uniba.euromath.editor.figures.EMFigure;
46 import sk.uniba.euromath.editor.figures.IEMFigure;
47 import sk.uniba.euromath.foRenderer.figures.LineRuleBorder;
48 import sk.uniba.euromath.foRenderer.figures.PageFigure;
49 import sk.uniba.euromath.foRenderer.fop.AbstractFOPLauncher;
50 import sk.uniba.euromath.gene.RendererContext;
51
52 /***
53 * Renderer for FO XML documents. Rendering is done by processing document by
54 * FOP andrendering FOP areas by {@link Draw2dRenderer} to draw2d figures.
55 */
56 public class FORenderer implements IRenderer {
57
58 /***
59 * Root node from transformed document(Source).
60 */
61 private Element rootElement;
62
63 private AbstractFOPLauncher launcher;
64
65 /***
66 * The renderer info.
67 */
68 private final RendererInfo info;
69
70 /***
71 * Root figure.
72 */
73 private IEMFigure pageDesktopFigure;
74
75 /***
76 * Renderer context instance.
77 */
78 private RendererContext rendererContext;
79
80 /***
81 * Map for holdnig ids of mark elements and for mapping them to parent
82 * figures to position them.
83 */
84 private HashMap<String, IFigure> externalIdFigureMap;
85
86 /***
87 * Map for mapping ids of mark elements to dimension of contents.
88 */
89 private HashMap<String, Dimension> externalIdDimensionMap;
90
91 /***
92 * Constructor
93 */
94 public FORenderer(final RendererInfo info) throws FOPException {
95 super();
96 rootElement = null;
97 this.info = info;
98 launcher = createLauncher();
99 }
100
101 /***
102 * Creates launcher.
103 *
104 * @return
105 */
106 protected AbstractFOPLauncher createLauncher() throws FOPException {
107 AbstractFOPLauncher result = new AbstractFOPLauncher(this);
108
109
110 return result;
111 }
112
113 /***
114 * Makes a copy of source, handles mark elements and renders source by
115 * FOP. Accepts only DOMSource.
116 */
117 public void init(Source transformedDoc, RendererContext context)
118 throws EditorException {
119 try {
120
121 this.rendererContext = context;
122
123
124 final DOMSource copyOfTransformedDoc = (DOMSource) transformedDoc;
125 if (copyOfTransformedDoc.getNode() == null)
126 throw new NullPointerException("null node");
127
128 rootElement = DOMUtils
129 .getRootElement(copyOfTransformedDoc);
130
131 handleMarkElements();
132
133 pageDesktopFigure = createPageDesktopFigure();
134
135 Draw2dRenderer bld = (Draw2dRenderer) launcher
136 .getRenderer();
137
138 launcher.setInput(copyOfTransformedDoc);
139 launcher.run();
140 List<PageFigure> pages = bld.getPages();
141 for (PageFigure figure : pages) {
142 pageDesktopFigure.add(figure);
143 }
144
145 } catch (FOPException e) {
146 throw new EditorException("FO renderer fails to init.",
147 e);
148 } catch (TransformerException e) {
149 throw new EditorException("FO renderer fails to init.",
150 e);
151 }
152 }
153
154
155
156
157
158
159 public void reinit(IChangeCollector changes) throws EditorException {
160 try {
161
162 launcher.reinit(this);
163
164 DOMSource copyOfTransformedDoc = (DOMSource) changes
165 .getSource();
166 rootElement = DOMUtils
167 .getRootElement(copyOfTransformedDoc);
168
169 handleMarkElements();
170
171 pageDesktopFigure = createPageDesktopFigure();
172
173 Draw2dRenderer bld = (Draw2dRenderer) launcher
174 .getRenderer();
175
176 try {
177 bld.startRenderer(null);
178 } catch (IOException e) {
179 throw new EditorException(e);
180 }
181
182 launcher.setInput(copyOfTransformedDoc);
183 launcher.run();
184 List<PageFigure> pages = bld.getPages();
185 for (PageFigure figure : pages) {
186 pageDesktopFigure.add(figure);
187 }
188
189 } catch (FOPException e) {
190 throw new EditorException("FO renderer fails to init.",
191 e);
192 } catch (TransformerException e) {
193 throw new EditorException("FO renderer fails to init.",
194 e);
195 }
196 }
197
198 /***
199 * Replaces mark elements with <fo:instream-foreign-object>
200 *
201 * @param transformedDoc
202 * @throws EditorException
203 */
204 private void handleMarkElements() throws EditorException {
205 externalIdFigureMap = new HashMap<String, IFigure>();
206 externalIdDimensionMap = new HashMap<String, Dimension>();
207
208 Queue<Node> queue = new LinkedList<Node>();
209 queue.addAll(DOMUtils.nodeListToList(rootElement
210 .getChildNodes()));
211 Node node;
212 while (!queue.isEmpty()) {
213 node = queue.poll();
214
215 final String id = FOPreprocessor.getGenerefElementId(node);
216 if (id != null) {
217
218 Dimension dimension = rendererContext
219 .getCanvasSize(id);
220 externalIdDimensionMap.put(id, dimension);
221 externalIdFigureMap.put(id, null);
222
223 Node parent = (Element) node.getParentNode();
224
225 parent.removeChild(node);
226
227
228 if (((Element) parent).getLocalName().contains(
229 "instream-foreign-object")) {
230 Node grandParent = parent
231 .getParentNode();
232 grandParent.removeChild(parent);
233 parent = grandParent;
234 }
235
236
237 Element e = parent
238 .getOwnerDocument()
239 .createElementNS(
240 Namespaces.XSL_FO_NAMESPACE,
241 "fo:block-container");
242 e.setAttributeNS(null, "width", Integer
243 .toString(dimension.width)
244 + "pt");
245 e.setAttributeNS(null, "height", Integer
246 .toString(dimension.height)
247 + "pt");
248 e.setAttributeNS(null, "id", id);
249 parent.appendChild(e);
250 parent = e;
251 e = parent.getOwnerDocument().createElementNS(
252 Namespaces.XSL_FO_NAMESPACE,
253 "fo:block");
254 parent.appendChild(e);
255
256
257 } else {
258 queue.addAll(DOMUtils.nodeListToList(node
259 .getChildNodes()));
260 }
261 }
262 }
263
264 /***
265 * Creates root figure - pageDesktopFigure.
266 *
267 * @return root figure
268 */
269 private IEMFigure createPageDesktopFigure() {
270 EMFigure result = new EMFigure(IDManager.getIDNull(rootElement,
271 ExportUtils.GENE_ID_ATTRIBUTE_QNAME),
272 rootElement, true);
273
274
275 Border border = new LineRuleBorder();
276 result.setBorder(border);
277 result.setBackgroundColor(ColorConstants.buttonDarker);
278
279 FlowLayout layout = new FlowLayout(false);
280
281
282
283 layout.setMajorAlignment(FlowLayout.ALIGN_CENTER);
284 layout.setMinorAlignment(FlowLayout.ALIGN_CENTER);
285 layout.setMajorSpacing(10);
286 layout.setMinorSpacing(10);
287 result.setLayoutManager(layout);
288
289 result.setOpaque(true);
290 return result;
291
292 }
293
294 /***
295 * Returns XMLAccess instance.
296 *
297 * @return XMLAccess
298 */
299 private XMLAccess getXMLAccess() {
300 if (rendererContext == null)
301 throw new IllegalStateException(
302 "Cannot getXMLAccess because RendererContext is null, probably renderer is before initialization.");
303 return rendererContext.xmlAccess;
304 }
305
306
307
308
309
310
311
312 public Point getPlacement(String id) {
313 IFigure figure = externalIdFigureMap.get(id);
314 Point result = figure.getClientArea().getTopLeft();
315 return result;
316 }
317
318
319
320
321
322
323 public Dimension getCanvasSize() throws EditorException {
324
325 return this.pageDesktopFigure.getBounds().getSize();
326 }
327
328
329
330
331
332
333 public IEMFigure getFigure(Object o) {
334 if (!(o instanceof Node))
335 throw new IllegalArgumentException(
336 "Object must bu instance of node.");
337 return null;
338 }
339
340
341
342
343
344
345 public IEMFigure getRootFigure() {
346 return pageDesktopFigure;
347 }
348
349
350
351
352
353
354 public void render(org.eclipse.draw2d.Graphics g)
355 throws EditorException {
356 pageDesktopFigure.paint(g);
357 }
358
359
360
361
362
363
364 public Object offerObject() {
365 throw new UnsupportedOperationException(
366 "FO renderer, offerObject.");
367 }
368
369
370
371
372
373
374 public RendererInfo getInfo() {
375 return info;
376 }
377
378
379
380
381
382
383 public IInputPreprocessor createPreprocessor() {
384 return new FOPreprocessor();
385 }
386
387 /***
388 * Returns map for holdnig ids of mark elements and for mapping them to
389 * parent figures to position them.
390 */
391 public HashMap<String, IFigure> getExternalIdFigureMap() {
392 return externalIdFigureMap;
393 }
394
395 /***
396 * Getter for RendererContext.
397 */
398 public RendererContext getRendererContext() {
399 return rendererContext;
400 }
401
402 /***
403 * Returns map for mapping ids of mark elements to dimension of
404 * contents.
405 */
406 public HashMap<String, Dimension> getExternalIdDimensionMap() {
407 return externalIdDimensionMap;
408 }
409 }