1 /*
2 * $Id: List.java 3373 2008-05-12 16:21:24Z xlv $
3 *
4 * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * (the "License"); you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the License.
13 *
14 * The Original Code is 'iText, a free JAVA-PDF library'.
15 *
16 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18 * All Rights Reserved.
19 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21 *
22 * Contributor(s): all the names of the contributors are added in the source code
23 * where applicable.
24 *
25 * Alternatively, the contents of this file may be used under the terms of the
26 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27 * provisions of LGPL are applicable instead of those above. If you wish to
28 * allow use of your version of this file only under the terms of the LGPL
29 * License and not to allow others to use your version of this file under
30 * the MPL, indicate your decision by deleting the provisions above and
31 * replace them with the notice and other provisions required by the LGPL.
32 * If you do not delete the provisions above, a recipient may use your version
33 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34 *
35 * This library is free software; you can redistribute it and/or modify it
36 * under the terms of the MPL as stated above or under the terms of the GNU
37 * Library General Public License as published by the Free Software Foundation;
38 * either version 2 of the License, or any later version.
39 *
40 * This library is distributed in the hope that it will be useful, but WITHOUT
41 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43 * details.
44 *
45 * If you didn't download this code from the following link, you should check if
46 * you aren't using an obsolete version:
47 * http://www.lowagie.com/iText/
48 */
49
50 package com.lowagie.text;
51
52 import java.util.ArrayList;
53 import java.util.Iterator;
54
55 import com.lowagie.text.factories.RomanAlphabetFactory;
56
57 /**
58 * A <CODE>List</CODE> contains several <CODE>ListItem</CODE>s.
59 * <P>
60 * <B>Example 1:</B>
61 * <BLOCKQUOTE><PRE>
62 * <STRONG>List list = new List(true, 20);</STRONG>
63 * <STRONG>list.add(new ListItem("First line"));</STRONG>
64 * <STRONG>list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));</STRONG>
65 * <STRONG>list.add(new ListItem("Third line"));</STRONG>
66 * </PRE></BLOCKQUOTE>
67 *
68 * The result of this code looks like this:
69 * <OL>
70 * <LI>
71 * First line
72 * </LI>
73 * <LI>
74 * The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
75 * </LI>
76 * <LI>
77 * Third line
78 * </LI>
79 * </OL>
80 *
81 * <B>Example 2:</B>
82 * <BLOCKQUOTE><PRE>
83 * <STRONG>List overview = new List(false, 10);</STRONG>
84 * <STRONG>overview.add(new ListItem("This is an item"));</STRONG>
85 * <STRONG>overview.add("This is another item");</STRONG>
86 * </PRE></BLOCKQUOTE>
87 *
88 * The result of this code looks like this:
89 * <UL>
90 * <LI>
91 * This is an item
92 * </LI>
93 * <LI>
94 * This is another item
95 * </LI>
96 * </UL>
97 *
98 * @see Element
99 * @see ListItem
100 */
101
102 public class List implements TextElementArray {
103
104 // constants
105
106 /** a possible value for the numbered parameter */
107 public static final boolean ORDERED = true;
108 /** a possible value for the numbered parameter */
109 public static final boolean UNORDERED = false;
110 /** a possible value for the lettered parameter */
111 public static final boolean NUMERICAL = false;
112 /** a possible value for the lettered parameter */
113 public static final boolean ALPHABETICAL = true;
114 /** a possible value for the lettered parameter */
115 public static final boolean UPPERCASE = false;
116 /** a possible value for the lettered parameter */
117 public static final boolean LOWERCASE = true;
118
119 // member variables
120
121 /** This is the <CODE>ArrayList</CODE> containing the different <CODE>ListItem</CODE>s. */
122 protected ArrayList list = new ArrayList();
123
124 /** Indicates if the list has to be numbered. */
125 protected boolean numbered = false;
126 /** Indicates if the listsymbols are numerical or alphabetical. */
127 protected boolean lettered = false;
128 /** Indicates if the listsymbols are lowercase or uppercase. */
129 protected boolean lowercase = false;
130 /** Indicates if the indentation has to be set automatically. */
131 protected boolean autoindent = false;
132 /** Indicates if the indentation of all the items has to be aligned. */
133 protected boolean alignindent = false;
134
135 /** This variable indicates the first number of a numbered list. */
136 protected int first = 1;
137 /** This is the listsymbol of a list that is not numbered. */
138 protected Chunk symbol = new Chunk("- ");
139 /**
140 * In case you are using numbered/lettered lists, this String is added before the number/letter.
141 * @since iText 2.1.1
142 */
143 protected String preSymbol = "";
144 /**
145 * In case you are using numbered/lettered lists, this String is added after the number/letter.
146 * @since iText 2.1.1
147 */
148 protected String postSymbol = ". ";
149
150 /** The indentation of this list on the left side. */
151 protected float indentationLeft = 0;
152 /** The indentation of this list on the right side. */
153 protected float indentationRight = 0;
154 /** The indentation of the listitems. */
155 protected float symbolIndent = 0;
156
157 // constructors
158
159 /** Constructs a <CODE>List</CODE>. */
160 public List() {
161 this(false, false);
162 }
163
164 /**
165 * Constructs a <CODE>List</CODE> with a specific symbol indentation.
166 * @param symbolIndent the symbol indentation
167 * @since iText 2.0.8
168 */
169 public List(float symbolIndent) {
170 this.symbolIndent = symbolIndent;
171 }
172
173 /**
174 * Constructs a <CODE>List</CODE>.
175 * @param numbered a boolean
176 */
177 public List(boolean numbered) {
178 this(numbered, false);
179 }
180
181 /**
182 * Constructs a <CODE>List</CODE>.
183 * @param numbered a boolean
184 * @param lettered has the list to be 'numbered' with letters
185 */
186 public List(boolean numbered, boolean lettered) {
187 this.numbered = numbered;
188 this.lettered = lettered;
189 this.autoindent = true;
190 this.alignindent = true;
191 }
192
193 /**
194 * Constructs a <CODE>List</CODE>.
195 * <P>
196 * Remark: the parameter <VAR>symbolIndent</VAR> is important for instance when
197 * generating PDF-documents; it indicates the indentation of the listsymbol.
198 * It is not important for HTML-documents.
199 *
200 * @param numbered a boolean
201 * @param symbolIndent the indentation that has to be used for the listsymbol
202 */
203 public List(boolean numbered, float symbolIndent) {
204 this(numbered, false, symbolIndent);
205 }
206
207 /**
208 * Creates a list
209 * @param numbered has the list to be numbered?
210 * @param lettered has the list to be 'numbered' with letters
211 * @param symbolIndent the indentation of the symbol
212 */
213 public List(boolean numbered, boolean lettered, float symbolIndent) {
214 this.numbered = numbered;
215 this.lettered = lettered;
216 this.symbolIndent = symbolIndent;
217 }
218
219 // implementation of the Element-methods
220
221 /**
222 * Processes the element by adding it (or the different parts) to an
223 * <CODE>ElementListener</CODE>.
224 *
225 * @param listener an <CODE>ElementListener</CODE>
226 * @return <CODE>true</CODE> if the element was processed successfully
227 */
228 public boolean process(ElementListener listener) {
229 try {
230 for (Iterator i = list.iterator(); i.hasNext(); ) {
231 listener.add((Element) i.next());
232 }
233 return true;
234 }
235 catch(DocumentException de) {
236 return false;
237 }
238 }
239
240 /**
241 * Gets the type of the text element.
242 *
243 * @return a type
244 */
245 public int type() {
246 return Element.LIST;
247 }
248
249 /**
250 * Gets all the chunks in this element.
251 *
252 * @return an <CODE>ArrayList</CODE>
253 */
254 public ArrayList getChunks() {
255 ArrayList tmp = new ArrayList();
256 for (Iterator i = list.iterator(); i.hasNext(); ) {
257 tmp.addAll(((Element) i.next()).getChunks());
258 }
259 return tmp;
260 }
261
262 // methods to set the membervariables
263
264 /**
265 * Adds an <CODE>Object</CODE> to the <CODE>List</CODE>.
266 *
267 * @param o the object to add.
268 * @return true if adding the object succeeded
269 */
270 public boolean add(Object o) {
271 if (o instanceof ListItem) {
272 ListItem item = (ListItem) o;
273 if (numbered || lettered) {
274 Chunk chunk = new Chunk(preSymbol, symbol.getFont());
275 int index = first + list.size();
276 if ( lettered )
277 chunk.append(RomanAlphabetFactory.getString(index, lowercase));
278 else
279 chunk.append(String.valueOf(index));
280 chunk.append(postSymbol);
281 item.setListSymbol(chunk);
282 }
283 else {
284 item.setListSymbol(symbol);
285 }
286 item.setIndentationLeft(symbolIndent, autoindent);
287 item.setIndentationRight(0);
288 return list.add(item);
289 }
290 else if (o instanceof List) {
291 List nested = (List) o;
292 nested.setIndentationLeft(nested.getIndentationLeft() + symbolIndent);
293 first--;
294 return list.add(nested);
295 }
296 else if (o instanceof String) {
297 return this.add(new ListItem((String) o));
298 }
299 return false;
300 }
301
302 // extra methods
303
304 /** Makes sure all the items in the list have the same indentation. */
305 public void normalizeIndentation() {
306 float max = 0;
307 Element o;
308 for (Iterator i = list.iterator(); i.hasNext(); ) {
309 o = (Element)i.next();
310 if (o instanceof ListItem) {
311 max = Math.max(max, ((ListItem)o).getIndentationLeft());
312 }
313 }
314 for (Iterator i = list.iterator(); i.hasNext(); ) {
315 o = (Element)i.next();
316 if (o instanceof ListItem) {
317 ((ListItem)o).setIndentationLeft(max);
318 }
319 }
320 }
321
322 // setters
323
324 /**
325 * @param numbered the numbered to set
326 */
327 public void setNumbered(boolean numbered) {
328 this.numbered = numbered;
329 }
330
331 /**
332 * @param lettered the lettered to set
333 */
334 public void setLettered(boolean lettered) {
335 this.lettered = lettered;
336 }
337
338 /**
339 * @param uppercase the uppercase to set
340 */
341 public void setLowercase(boolean uppercase) {
342 this.lowercase = uppercase;
343 }
344
345 /**
346 * @param autoindent the autoindent to set
347 */
348 public void setAutoindent(boolean autoindent) {
349 this.autoindent = autoindent;
350 }
351 /**
352 * @param alignindent the alignindent to set
353 */
354 public void setAlignindent(boolean alignindent) {
355 this.alignindent = alignindent;
356 }
357
358 /**
359 * Sets the number that has to come first in the list.
360 *
361 * @param first a number
362 */
363 public void setFirst(int first) {
364 this.first = first;
365 }
366
367 /**
368 * Sets the listsymbol.
369 *
370 * @param symbol a <CODE>Chunk</CODE>
371 */
372 public void setListSymbol(Chunk symbol) {
373 this.symbol = symbol;
374 }
375
376 /**
377 * Sets the listsymbol.
378 * <P>
379 * This is a shortcut for <CODE>setListSymbol(Chunk symbol)</CODE>.
380 *
381 * @param symbol a <CODE>String</CODE>
382 */
383 public void setListSymbol(String symbol) {
384 this.symbol = new Chunk(symbol);
385 }
386
387 /**
388 * Sets the indentation of this paragraph on the left side.
389 *
390 * @param indentation the new indentation
391 */
392 public void setIndentationLeft(float indentation) {
393 this.indentationLeft = indentation;
394 }
395
396 /**
397 * Sets the indentation of this paragraph on the right side.
398 *
399 * @param indentation the new indentation
400 */
401 public void setIndentationRight(float indentation) {
402 this.indentationRight = indentation;
403 }
404
405 /**
406 * @param symbolIndent the symbolIndent to set
407 */
408 public void setSymbolIndent(float symbolIndent) {
409 this.symbolIndent = symbolIndent;
410 }
411
412 // methods to retrieve information
413
414 /**
415 * Gets all the items in the list.
416 *
417 * @return an <CODE>ArrayList</CODE> containing <CODE>ListItem</CODE>s.
418 */
419 public ArrayList getItems() {
420 return list;
421 }
422
423 /**
424 * Gets the size of the list.
425 *
426 * @return a <CODE>size</CODE>
427 */
428 public int size() {
429 return list.size();
430 }
431
432 /**
433 * Returns <CODE>true</CODE> if the list is empty.
434 *
435 * @return <CODE>true</CODE> if the list is empty
436 */
437 public boolean isEmpty() {
438 return list.isEmpty();
439 }
440
441 /**
442 * Gets the leading of the first listitem.
443 *
444 * @return a <CODE>leading</CODE>
445 */
446 public float getTotalLeading() {
447 if (list.size() < 1) {
448 return -1;
449 }
450 ListItem item = (ListItem) list.get(0);
451 return item.getTotalLeading();
452 }
453
454 // getters
455
456 /**
457 * Checks if the list is numbered.
458 * @return <CODE>true</CODE> if the list is numbered, <CODE>false</CODE> otherwise.
459 */
460
461 public boolean isNumbered() {
462 return numbered;
463 }
464
465 /**
466 * Checks if the list is lettered.
467 * @return <CODE>true</CODE> if the list is lettered, <CODE>false</CODE> otherwise.
468 */
469 public boolean isLettered() {
470 return lettered;
471 }
472
473 /**
474 * Checks if the list lettering is lowercase.
475 * @return <CODE>true</CODE> if it is lowercase, <CODE>false</CODE> otherwise.
476 */
477 public boolean isLowercase() {
478 return lowercase;
479 }
480
481 /**
482 * Checks if the indentation of list items is done automatically.
483 * @return the autoindent
484 */
485 public boolean isAutoindent() {
486 return autoindent;
487 }
488
489 /**
490 * Checks if all the listitems should be aligned.
491 * @return the alignindent
492 */
493 public boolean isAlignindent() {
494 return alignindent;
495 }
496
497 /**
498 * Gets the first number .
499 * @return a number
500 */
501 public int getFirst() {
502 return first;
503 }
504
505 /**
506 * Gets the Chunk containing the symbol.
507 * @return a Chunk with a symbol
508 */
509 public Chunk getSymbol() {
510 return symbol;
511 }
512
513 /**
514 * Gets the indentation of this paragraph on the left side.
515 * @return the indentation
516 */
517 public float getIndentationLeft() {
518 return indentationLeft;
519 }
520
521 /**
522 * Gets the indentation of this paragraph on the right side.
523 * @return the indentation
524 */
525 public float getIndentationRight() {
526 return indentationRight;
527 }
528
529 /**
530 * Gets the symbol indentation.
531 * @return the symbol indentation
532 */
533 public float getSymbolIndent() {
534 return symbolIndent;
535 }
536 /**
537 * @see com.lowagie.text.Element#isContent()
538 * @since iText 2.0.8
539 */
540 public boolean isContent() {
541 return true;
542 }
543
544 /**
545 * @see com.lowagie.text.Element#isNestable()
546 * @since iText 2.0.8
547 */
548 public boolean isNestable() {
549 return true;
550 }
551
552 /**
553 * Returns the String that is after a number or letter in the list symbol.
554 * @return the String that is after a number or letter in the list symbol
555 * @since iText 2.1.1
556 */
557 public String getPostSymbol() {
558 return postSymbol;
559 }
560
561 /**
562 * Sets the String that has to be added after a number or letter in the list symbol.
563 * @since iText 2.1.1
564 * @param postSymbol the String that has to be added after a number or letter in the list symbol.
565 */
566 public void setPostSymbol(String postSymbol) {
567 this.postSymbol = postSymbol;
568 }
569
570 /**
571 * Returns the String that is before a number or letter in the list symbol.
572 * @return the String that is before a number or letter in the list symbol
573 * @since iText 2.1.1
574 */
575 public String getPreSymbol() {
576 return preSymbol;
577 }
578
579 /**
580 * Sets the String that has to be added before a number or letter in the list symbol.
581 * @since iText 2.1.1
582 * @param preSymbol the String that has to be added before a number or letter in the list symbol.
583 */
584 public void setPreSymbol(String preSymbol) {
585 this.preSymbol = preSymbol;
586 }
587
588 }