KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > area > PageViewport


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: PageViewport.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.area;
21
22 import java.awt.Rectangle JavaDoc;
23 import java.awt.geom.Rectangle2D JavaDoc;
24 import java.io.ObjectOutputStream JavaDoc;
25 import java.io.ObjectInputStream JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36 import org.apache.fop.fo.Constants;
37 import org.apache.fop.fo.extensions.ExtensionAttachment;
38 import org.apache.fop.fo.pagination.SimplePageMaster;
39
40 /**
41  * Page viewport that specifies the viewport area and holds the page contents.
42  * This is the top level object for a page and remains valid for the life
43  * of the document and the area tree.
44  * This object may be used as a key to reference a page.
45  * This is the level that creates the page.
46  * The page (reference area) is then rendered inside the page object
47  */

48 public class PageViewport extends AreaTreeObject implements Resolvable, Cloneable JavaDoc {
49
50     private Page page;
51     private Rectangle2D JavaDoc viewArea;
52     private String JavaDoc simplePageMasterName;
53     
54     /**
55      * Unique key to identify the page. pageNumberString and pageIndex are both no option
56      * for this.
57      */

58     private String JavaDoc pageKey;
59     
60     private int pageNumber = -1;
61     private String JavaDoc pageNumberString = null;
62     private int pageIndex = -1; //-1 = undetermined
63
private boolean blank;
64     
65     private transient PageSequence pageSequence;
66
67     // list of id references and the rectangle on the page
68
//private Map idReferences = null;
69

70     // this keeps a list of currently unresolved areas or extensions
71
// once an idref is resolved it is removed
72
// when this is empty the page can be rendered
73
private Map JavaDoc unresolvedIDRefs = new java.util.HashMap JavaDoc();
74
75     private Map JavaDoc pendingResolved = null;
76
77     // hashmap of markers for this page
78
// start and end are added by the fo that contains the markers
79
private Map JavaDoc markerFirstStart = null;
80     private Map JavaDoc markerLastStart = null;
81     private Map JavaDoc markerFirstAny = null;
82     private Map JavaDoc markerLastEnd = null;
83     private Map JavaDoc markerLastAny = null;
84     
85     //Arbitrary attachments to the page from extensions that need to pass information
86
//down to the renderers.
87
private List JavaDoc extensionAttachments = null;
88
89     /**
90      * logging instance
91      */

92     protected static Log log = LogFactory.getLog(PageViewport.class);
93
94     /**
95      * Create a page viewport.
96      * @param spm SimplePageMaster indicating the page and region dimensions
97      * @param pageNumber the page number
98      * @param pageStr String representation of the page number
99      * @param blank true if this is a blank page
100      */

101     public PageViewport(SimplePageMaster spm, int pageNumber, String JavaDoc pageStr, boolean blank) {
102         this.simplePageMasterName = spm.getMasterName();
103         this.extensionAttachments = spm.getExtensionAttachments();
104         this.blank = blank;
105         int pageWidth = spm.getPageWidth().getValue();
106         int pageHeight = spm.getPageHeight().getValue();
107         this.pageNumber = pageNumber;
108         this.pageNumberString = pageStr;
109         this.viewArea = new Rectangle JavaDoc(0, 0, pageWidth, pageHeight);
110         this.page = new Page(spm);
111         createSpan(false);
112     }
113
114     /**
115      * Copy constructor.
116      * @param original the original PageViewport to copy from
117      */

118     public PageViewport(PageViewport original) {
119         if (original.extensionAttachments != null) {
120             this.extensionAttachments = new java.util.ArrayList JavaDoc(original.extensionAttachments);
121         }
122         this.pageNumber = original.pageNumber;
123         this.pageNumberString = original.pageNumberString;
124         this.page = (Page)original.page.clone();
125         this.viewArea = (Rectangle2D JavaDoc)original.viewArea.clone();
126         this.simplePageMasterName = original.simplePageMasterName;
127         this.blank = original.blank;
128     }
129
130     /**
131      * Constructor used by the area tree parser.
132      * @param viewArea the view area
133      * @param pageNumber the page number
134      * @param pageStr String representation of the page number
135      * @param simplePageMasterName name of the original simple-page-master that generated this page
136      * @param blank true if this is a blank page
137      */

138     public PageViewport(Rectangle2D JavaDoc viewArea, int pageNumber, String JavaDoc pageStr,
139             String JavaDoc simplePageMasterName, boolean blank) {
140         this.viewArea = viewArea;
141         this.pageNumber = pageNumber;
142         this.pageNumberString = pageStr;
143         this.simplePageMasterName = simplePageMasterName;
144         this.blank = blank;
145     }
146     
147     /**
148      * Sets the page sequence this page belongs to
149      * @param seq the page sequence
150      */

151     public void setPageSequence(PageSequence seq) {
152         this.pageSequence = seq;
153     }
154     
155     /** @return the page sequence this page belongs to */
156     public PageSequence getPageSequence() {
157         return this.pageSequence;
158     }
159     
160     /**
161      * Get the view area rectangle of this viewport.
162      * @return the rectangle for this viewport
163      */

164     public Rectangle2D JavaDoc getViewArea() {
165         return viewArea;
166     }
167
168     /**
169      * Get the page reference area with the contents.
170      * @return the page reference area
171      */

172     public Page getPage() {
173         return page;
174     }
175     
176     /**
177      * Sets the page object for this PageViewport.
178      * @param page the page
179      */

180     public void setPage(Page page) {
181         this.page = page;
182     }
183
184     /**
185      * Get the page number of this page.
186      * @return the integer value that represents this page
187      */

188     public int getPageNumber() {
189         return pageNumber;
190     }
191
192     /**
193      * Get the page number of this page.
194      * @return the string that represents this page
195      */

196     public String JavaDoc getPageNumberString() {
197         return pageNumberString;
198     }
199
200     /**
201      * Sets the page index of the page in this rendering run.
202      * (This is not the same as the page number!)
203      * @param index the page index (zero-based), -1 if it is undetermined
204      */

205     public void setPageIndex(int index) {
206         this.pageIndex = index;
207     }
208     
209     /**
210      * @return the overall page index of the page in this rendering run (zero-based,
211      * -1 if it is undetermined).
212      */

213     public int getPageIndex() {
214         return this.pageIndex;
215     }
216     
217     /**
218      * Sets the unique key for this PageViewport that will be used to reference this page.
219      * @param key the unique key.
220      */

221     public void setKey(String JavaDoc key) {
222         this.pageKey = key;
223     }
224     
225     /**
226      * Get the key for this page viewport.
227      * This is used so that a serializable key can be used to
228      * lookup the page or some other reference.
229      *
230      * @return a unique page viewport key for this area tree
231      */

232     public String JavaDoc getKey() {
233         if (this.pageKey == null) {
234             throw new IllegalStateException JavaDoc("No page key set on the PageViewport: " + toString());
235         }
236         return this.pageKey;
237     }
238
239     /**
240      * Add an idref to this page.
241      * All idrefs found for child areas of this PageViewport are added
242      * to unresolvedIDRefs, for subsequent resolution by AreaTreeHandler
243      * calls to this object's resolveIDRef().
244      *
245      * @param idref the idref
246      * @param res the child element of this page that needs this
247      * idref resolved
248      */

249     public void addUnresolvedIDRef(String JavaDoc idref, Resolvable res) {
250         if (unresolvedIDRefs == null) {
251             unresolvedIDRefs = new HashMap JavaDoc();
252         }
253         List JavaDoc list = (List JavaDoc)unresolvedIDRefs.get(idref);
254         if (list == null) {
255             list = new ArrayList JavaDoc();
256             unresolvedIDRefs.put(idref, list);
257         }
258         list.add(res);
259     }
260
261     /**
262      * Check if this page has been fully resolved.
263      * @return true if the page is resolved and can be rendered
264      */

265     public boolean isResolved() {
266         return unresolvedIDRefs == null
267             || unresolvedIDRefs.size() == 0;
268     }
269
270     /**
271      * Get the unresolved idrefs for this page.
272      * @return String array of idref's that still have not been resolved
273      */

274     public String JavaDoc[] getIDRefs() {
275         return (unresolvedIDRefs == null) ? null
276             : (String JavaDoc[]) unresolvedIDRefs.keySet().toArray(new String JavaDoc[] {});
277     }
278
279     /**
280      * @see org.apache.fop.area.Resolvable#resolveIDRef(String, List)
281      */

282     public void resolveIDRef(String JavaDoc id, List JavaDoc pages) {
283         if (page == null) {
284             if (pendingResolved == null) {
285                 pendingResolved = new HashMap JavaDoc();
286             }
287             pendingResolved.put(id, pages);
288         } else {
289             if (unresolvedIDRefs != null) {
290                 List JavaDoc todo = (List JavaDoc)unresolvedIDRefs.get(id);
291                 if (todo != null) {
292                     for (int count = 0; count < todo.size(); count++) {
293                         Resolvable res = (Resolvable)todo.get(count);
294                         res.resolveIDRef(id, pages);
295                     }
296                 }
297             }
298         }
299         if (unresolvedIDRefs != null && pages != null) {
300             unresolvedIDRefs.remove(id);
301             if (unresolvedIDRefs.isEmpty()) {
302                 unresolvedIDRefs = null;
303             }
304         }
305     }
306
307     /**
308      * Add the markers for this page.
309      * Only the required markers are kept.
310      * For "first-starting-within-page" it adds the markers
311      * that are starting only if the marker class name is not
312      * already added.
313      * For "first-including-carryover" it adds any starting marker
314      * if the marker class name is not already added.
315      * For "last-starting-within-page" it adds all marks that
316      * are starting, replacing earlier markers.
317      * For "last-ending-within-page" it adds all markers that
318      * are ending, replacing earlier markers.
319      *
320      * Should this logic be placed in the Page layout manager.
321      *
322      * @param marks the map of markers to add
323      * @param starting if the area being added is starting or ending
324      * @param isfirst if the area being added has is-first trait
325      * @param islast if the area being added has is-last trait
326      */

327     public void addMarkers(Map JavaDoc marks, boolean starting,
328             boolean isfirst, boolean islast) {
329
330         if (marks == null) {
331             return;
332         }
333         if (log.isDebugEnabled()) {
334             log.debug("--" + marks.keySet() + ": "
335                     + (starting ? "starting" : "ending")
336                     + (isfirst ? ", first" : "")
337                     + (islast ? ", last" : ""));
338         }
339         
340         // at the start of the area, register is-first and any areas
341
if (starting) {
342             if (isfirst) {
343                 if (markerFirstStart == null) {
344                     markerFirstStart = new HashMap JavaDoc();
345                 }
346                 if (markerFirstAny == null) {
347                     markerFirstAny = new HashMap JavaDoc();
348                 }
349                 // first on page: only put in new values, leave current
350
for (Iterator JavaDoc iter = marks.keySet().iterator(); iter.hasNext();) {
351                     Object JavaDoc key = iter.next();
352                     if (!markerFirstStart.containsKey(key)) {
353                         markerFirstStart.put(key, marks.get(key));
354                         if (log.isTraceEnabled()) {
355                             log.trace("page " + pageNumberString + ": "
356                                     + "Adding marker " + key + " to FirstStart");
357                         }
358                     }
359                     if (!markerFirstAny.containsKey(key)) {
360                         markerFirstAny.put(key, marks.get(key));
361                         if (log.isTraceEnabled()) {
362                             log.trace("page " + pageNumberString + ": "
363                                     + "Adding marker " + key + " to FirstAny");
364                         }
365                     }
366                 }
367                 if (markerLastStart == null) {
368                     markerLastStart = new HashMap JavaDoc();
369                 }
370                 // last on page: replace all
371
markerLastStart.putAll(marks);
372                 if (log.isTraceEnabled()) {
373                     log.trace("page " + pageNumberString + ": "
374                             + "Adding all markers to LastStart");
375                 }
376             } else {
377                 if (markerFirstAny == null) {
378                     markerFirstAny = new HashMap JavaDoc();
379                 }
380                 // first on page: only put in new values, leave current
381
for (Iterator JavaDoc iter = marks.keySet().iterator(); iter.hasNext();) {
382                     Object JavaDoc key = iter.next();
383                     if (!markerFirstAny.containsKey(key)) {
384                         markerFirstAny.put(key, marks.get(key));
385                         if (log.isTraceEnabled()) {
386                             log.trace("page " + pageNumberString + ": "
387                                     + "Adding marker " + key + " to FirstAny");
388                         }
389                     }
390                 }
391             }
392         } else {
393             // at the end of the area, register is-last and any areas
394
if (islast) {
395                 if (markerLastEnd == null) {
396                     markerLastEnd = new HashMap JavaDoc();
397                 }
398                 // last on page: replace all
399
markerLastEnd.putAll(marks);
400                 if (log.isTraceEnabled()) {
401                     log.trace("page " + pageNumberString + ": "
402                             + "Adding all markers to LastEnd");
403                 }
404             }
405             if (markerLastAny == null) {
406                 markerLastAny = new HashMap JavaDoc();
407             }
408             // last on page: replace all
409
markerLastAny.putAll(marks);
410             if (log.isTraceEnabled()) {
411                 log.trace("page " + pageNumberString + ": "
412                         + "Adding all markers to LastAny");
413             }
414         }
415     }
416
417     /**
418      * Get a marker from this page.
419      * This will retrieve a marker with the class name
420      * and position.
421      *
422      * @param name The class name of the marker to retrieve
423      * @param pos the position to retrieve
424      * @return Object the marker found or null
425      */

426     public Object JavaDoc getMarker(String JavaDoc name, int pos) {
427         Object JavaDoc mark = null;
428         String JavaDoc posName = null;
429         switch (pos) {
430             case Constants.EN_FSWP:
431                 if (markerFirstStart != null) {
432                     mark = markerFirstStart.get(name);
433                     posName = "FSWP";
434                 }
435                 if (mark == null && markerFirstAny != null) {
436                     mark = markerFirstAny.get(name);
437                     posName = "FirstAny after " + posName;
438                 }
439             break;
440             case Constants.EN_FIC:
441                 if (markerFirstAny != null) {
442                     mark = markerFirstAny.get(name);
443                     posName = "FIC";
444                 }
445             break;
446             case Constants.EN_LSWP:
447                 if (markerLastStart != null) {
448                     mark = markerLastStart.get(name);
449                     posName = "LSWP";
450                 }
451                 if (mark == null && markerLastAny != null) {
452                     mark = markerLastAny.get(name);
453                     posName = "LastAny after " + posName;
454                 }
455             break;
456             case Constants.EN_LEWP:
457                 if (markerLastEnd != null) {
458                     mark = markerLastEnd.get(name);
459                     posName = "LEWP";
460                 }
461                 if (mark == null && markerLastAny != null) {
462                     mark = markerLastAny.get(name);
463                     posName = "LastAny after " + posName;
464                 }
465             break;
466             default:
467                 throw new RuntimeException JavaDoc();
468         }
469         if (log.isTraceEnabled()) {
470             log.trace("page " + pageNumberString + ": " + "Retrieving marker " + name
471                     + " at position " + posName);
472         }
473         return mark;
474     }
475
476     /** Dumps the current marker data to the logger. */
477     public void dumpMarkers() {
478         if (log.isTraceEnabled()) {
479             log.trace("FirstAny: " + this.markerFirstAny);
480             log.trace("FirstStart: " + this.markerFirstStart);
481             log.trace("LastAny: " + this.markerLastAny);
482             log.trace("LastEnd: " + this.markerLastEnd);
483             log.trace("LastStart: " + this.markerLastStart);
484         }
485     }
486     
487     /**
488      * Save the page contents to an object stream.
489      * The map of unresolved references are set on the page so that
490      * the resolvers can be properly serialized and reloaded.
491      * @param out the object output stream to write the contents
492      * @throws Exception if there is a problem saving the page
493      */

494     public void savePage(ObjectOutputStream JavaDoc out) throws Exception JavaDoc {
495         // set the unresolved references so they are serialized
496
page.setUnresolvedReferences(unresolvedIDRefs);
497         out.writeObject(page);
498         page = null;
499     }
500
501     /**
502      * Load the page contents from an object stream.
503      * This loads the page contents from the stream and
504      * if there are any unresolved references that were resolved
505      * while saved they will be resolved on the page contents.
506      * @param in the object input stream to read the page from
507      * @throws Exception if there is an error loading the page
508      */

509     public void loadPage(ObjectInputStream JavaDoc in) throws Exception JavaDoc {
510         page = (Page) in.readObject();
511         unresolvedIDRefs = page.getUnresolvedReferences();
512         if (unresolvedIDRefs != null && pendingResolved != null) {
513             for (Iterator JavaDoc iter = pendingResolved.keySet().iterator();
514                          iter.hasNext();) {
515                 String JavaDoc id = (String JavaDoc) iter.next();
516                 resolveIDRef(id, (List JavaDoc)pendingResolved.get(id));
517             }
518             pendingResolved = null;
519         }
520     }
521
522     /**
523      * Clone this page.
524      * Used by the page master to create a copy of an original page.
525      * @return a copy of this page and associated viewports
526      */

527     public Object JavaDoc clone() {
528         return new PageViewport(this);
529     }
530
531     /**
532      * Clear the page contents to save memory.
533      * This object is kept for the life of the area tree since
534      * it holds id and marker information and is used as a key.
535      */

536     public void clear() {
537         page = null;
538     }
539
540     /**
541      * @see java.lang.Object#toString()
542      */

543     public String JavaDoc toString() {
544         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(64);
545         sb.append("PageViewport: page=");
546         sb.append(getPageNumberString());
547         return sb.toString();
548     }
549     
550     /** @return the name of the simple-page-master that created this page */
551     public String JavaDoc getSimplePageMasterName() {
552         return this.simplePageMasterName;
553     }
554     
555     /**
556      * Adds a new ExtensionAttachment instance to this page.
557      * @param attachment the ExtensionAttachment
558      */

559     public void addExtensionAttachment(ExtensionAttachment attachment) {
560         if (this.extensionAttachments == null) {
561             this.extensionAttachments = new java.util.ArrayList JavaDoc();
562         }
563         extensionAttachments.add(attachment);
564     }
565     
566     /** @return the list of extension attachments for this page */
567     public List JavaDoc getExtensionAttachments() {
568         if (this.extensionAttachments == null) {
569             return Collections.EMPTY_LIST;
570         } else {
571             return this.extensionAttachments;
572         }
573     }
574     
575     /** @return True if this is a blank page. */
576     public boolean isBlank() {
577         return this.blank;
578     }
579     
580     /**
581      * Convenience method to get BodyRegion of this PageViewport
582      * @return BodyRegion object
583      */

584     public BodyRegion getBodyRegion() {
585         return (BodyRegion) getPage().getRegionViewport(
586                 Constants.FO_REGION_BODY).getRegionReference();
587     }
588
589     /**
590      * Convenience method to create a new Span for this
591      * this PageViewport.
592      *
593      * @param spanAll whether this is a single-column span
594      * @return Span object created
595      */

596     public Span createSpan(boolean spanAll) {
597         return getBodyRegion().getMainReference().createSpan(spanAll);
598     }
599
600     /**
601      * Convenience method to get the span-reference-area currently
602      * being processed
603      *
604      * @return span currently being processed.
605      */

606     public Span getCurrentSpan() {
607         return getBodyRegion().getMainReference().getCurrentSpan();
608     }
609     
610     /**
611      * Convenience method to get the normal-flow-reference-area
612      * currently being processed
613      *
614      * @return span currently being processed.
615      */

616     public NormalFlow getCurrentFlow() {
617         return getCurrentSpan().getCurrentFlow();
618     }
619     
620     /**
621      * Convenience method to increment the Span to the
622      * next NormalFlow to be processed, and to return that flow.
623      *
624      * @return the next NormalFlow in the Span.
625      */

626     public NormalFlow moveToNextFlow() {
627         return getCurrentSpan().moveToNextFlow();
628     }
629     
630     /**
631      * Convenience method to return a given region-reference-area,
632      * keyed by the Constants class identifier for the corresponding
633      * formatting object (ie. Constants.FO_REGION_BODY, FO_REGION_START,
634      * etc.)
635      *
636      * @param id the Constants class identifier for the region.
637      * @return the corresponding region-reference-area for this page.
638      */

639     public RegionReference getRegionReference(int id) {
640         return getPage().getRegionViewport(id).getRegionReference();
641     }
642 }
643
Popular Tags