KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > biff > XFRecord


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20
21 package jxl.biff;
22
23 import java.text.DateFormat JavaDoc;
24 import java.text.SimpleDateFormat JavaDoc;
25 import java.text.NumberFormat JavaDoc;
26 import java.text.DecimalFormat JavaDoc;
27 import java.text.DecimalFormatSymbols JavaDoc;
28
29 import common.Assert;
30 import common.Logger;
31
32 import jxl.WorkbookSettings;
33 import jxl.format.CellFormat;
34 import jxl.format.Format;
35 import jxl.format.Font;
36 import jxl.format.Alignment;
37 import jxl.format.VerticalAlignment;
38 import jxl.format.BorderLineStyle;
39 import jxl.format.Border;
40 import jxl.format.Colour;
41 import jxl.format.Pattern;
42 import jxl.format.Orientation;
43 import jxl.read.biff.Record;
44
45 /**
46  * Holds an extended formatting record
47  */

48 public class XFRecord extends WritableRecordData implements CellFormat
49 {
50   /**
51    * The logger
52    */

53   private static Logger logger = Logger.getLogger(XFRecord.class);
54
55   /**
56    * The index to the format record
57    */

58   public int formatIndex;
59
60   /**
61    * The index of the parent format
62    */

63   private int parentFormat;
64
65   /**
66    * The format type
67    */

68   private XFType xfFormatType;
69
70   /**
71    * Indicates whether this is a date formatting record
72    */

73   private boolean date;
74
75   /**
76    * Indicates whether this is a number formatting record
77    */

78   private boolean number;
79
80   /**
81    * The date format for this record. Deduced when the record is
82    * read in from a spreadsheet
83    */

84   private DateFormat JavaDoc dateFormat;
85
86   /**
87    * The number format for this record. Deduced when the record is read in
88    * from a spreadsheet
89    */

90   private NumberFormat JavaDoc numberFormat;
91
92   /**
93    * The used attribute. Needs to be preserved in order to get accurate
94    * rationalization
95    */

96   private byte usedAttributes;
97   /**
98    * The index to the font record used by this XF record
99    */

100   private int fontIndex;
101   /**
102    * Flag to indicate whether this XF record represents a locked cell
103    */

104   private boolean locked;
105   /**
106    * Flag to indicate whether this XF record is hidden
107    */

108   private boolean hidden;
109   /**
110    * The alignment for this cell (left, right, centre)
111    */

112   private Alignment align;
113   /**
114    * The vertical alignment for the cell (top, bottom, centre)
115    */

116   private VerticalAlignment valign;
117   /**
118    * The orientation of the cell
119    */

120   private Orientation orientation;
121   /**
122    * Flag to indicates whether the data (normally text) in the cell will be
123    * wrapped around to fit in the cell width
124    */

125   private boolean wrap;
126
127   /**
128    * Indentation of the cell text
129    */

130   private int indentation;
131
132   /**
133    * Flag to indicate that this format is shrink to fit
134    */

135   private boolean shrinkToFit;
136
137   /**
138    * The border indicator for the left of this cell
139    */

140   private BorderLineStyle leftBorder;
141   /**
142    * The border indicator for the right of the cell
143    */

144   private BorderLineStyle rightBorder;
145   /**
146    * The border indicator for the top of the cell
147    */

148   private BorderLineStyle topBorder;
149   /**
150    * The border indicator for the bottom of the cell
151    */

152   private BorderLineStyle bottomBorder;
153
154   /**
155    * The border colour for the left of the cell
156    */

157   private Colour leftBorderColour;
158   /**
159    * The border colour for the right of the cell
160    */

161   private Colour rightBorderColour;
162   /**
163    * The border colour for the top of the cell
164    */

165   private Colour topBorderColour;
166   /**
167    * The border colour for the bottom of the cell
168    */

169   private Colour bottomBorderColour;
170
171   /**
172    * The background colour
173    */

174   private Colour backgroundColour;
175   /**
176    * The background pattern
177    */

178   private Pattern pattern;
179   /**
180    * The options mask which is used to store the processed cell options (such
181    * as alignment, borders etc)
182    */

183   private int options;
184   /**
185    * The index of this XF record within the workbook
186    */

187   private int xfIndex;
188   /**
189    * The font object for this XF record
190    */

191   private FontRecord font;
192   /**
193    * The format object for this XF record. This is used when creating
194    * a writable record
195    */

196   private DisplayFormat format;
197   /**
198    * Flag to indicate whether this XF record has been initialized
199    */

200   private boolean initialized;
201
202   /**
203    * Indicates whether this cell was constructed by an API or read
204    * from an existing Excel file
205    */

206   private boolean read;
207
208   /**
209    * The excel format for this record. This is used to display the actual
210    * excel format string back to the user (eg. when generating certain
211    * types of XML document) as opposed to the java equivalent
212    */

213   private Format JavaDoc excelFormat;
214
215   /**
216    * Flag to indicate whether the format information has been initialized.
217    * This is false if the xf record has been read in, but true if it
218    * has been written
219    */

220   private boolean formatInfoInitialized;
221
222   /**
223    * Flag to indicate whether this cell was copied. If it was copied, then
224    * it can be set to uninitialized, allowing us to change certain format
225    * information
226    */

227   private boolean copied;
228
229   /**
230    * A handle to the formatting records. The purpose of this is
231    * to read the formatting information back, for the purposes of
232    * output eg. to some form of XML
233    */

234   private FormattingRecords formattingRecords;
235
236   /**
237    * The list of built in date format values
238    */

239   private static final int[] dateFormats = new int[]
240     {0xe,
241      0xf,
242      0x10,
243      0x11,
244      0x12,
245      0x13,
246      0x14,
247      0x15,
248      0x16,
249      0x2d,
250      0x2e,
251      0x2f};
252
253   /**
254    * The list of java date format equivalents
255    */

256   private static final DateFormat JavaDoc[] javaDateFormats = new DateFormat JavaDoc[]
257     {new SimpleDateFormat JavaDoc("dd/MM/yyyy"),
258      new SimpleDateFormat JavaDoc("d-MMM-yy"),
259      new SimpleDateFormat JavaDoc("d-MMM"),
260      new SimpleDateFormat JavaDoc("MMM-yy"),
261      new SimpleDateFormat JavaDoc("h:mm a"),
262      new SimpleDateFormat JavaDoc("h:mm:ss a"),
263      new SimpleDateFormat JavaDoc("H:mm"),
264      new SimpleDateFormat JavaDoc("H:mm:ss"),
265      new SimpleDateFormat JavaDoc("M/d/yy H:mm"),
266      new SimpleDateFormat JavaDoc("mm:ss"),
267      new SimpleDateFormat JavaDoc("H:mm:ss"),
268      new SimpleDateFormat JavaDoc("mm:ss.S")};
269
270   /**
271    * The list of built in number format values
272    */

273   private static int[] numberFormats = new int[]
274     {0x1,
275      0x2,
276      0x3,
277      0x4,
278      0x5,
279      0x6,
280      0x7,
281      0x8,
282      0x9,
283      0xa,
284      0xb,
285      0x25,
286      0x26,
287      0x27,
288      0x28,
289      0x29,
290      0x2a,
291      0x2b,
292      0x2c,
293      0x30};
294
295   /**
296    * The list of java number format equivalents
297    */

298   private static NumberFormat JavaDoc[] javaNumberFormats = new NumberFormat JavaDoc[]
299     {new DecimalFormat JavaDoc("0"),
300      new DecimalFormat JavaDoc("0.00"),
301      new DecimalFormat JavaDoc("#,##0"),
302      new DecimalFormat JavaDoc("#,##0.00"),
303      new DecimalFormat JavaDoc("$#,##0;($#,##0)"),
304      new DecimalFormat JavaDoc("$#,##0;($#,##0)"),
305      new DecimalFormat JavaDoc("$#,##0.00;($#,##0.00)"),
306      new DecimalFormat JavaDoc("$#,##0.00;($#,##0.00)"),
307      new DecimalFormat JavaDoc("0%"),
308      new DecimalFormat JavaDoc("0.00%"),
309      new DecimalFormat JavaDoc("0.00E00"),
310      new DecimalFormat JavaDoc("#,##0;(#,##0)"),
311      new DecimalFormat JavaDoc("#,##0;(#,##0)"),
312      new DecimalFormat JavaDoc("#,##0.00;(#,##0.00)"),
313      new DecimalFormat JavaDoc("#,##0.00;(#,##0.00)"),
314      new DecimalFormat JavaDoc("#,##0;(#,##0)"),
315      new DecimalFormat JavaDoc("$#,##0;($#,##0)"),
316      new DecimalFormat JavaDoc("#,##0.00;(#,##0.00)"),
317      new DecimalFormat JavaDoc("$#,##0.00;($#,##0.00)"),
318      new DecimalFormat JavaDoc("##0.0E0")};
319
320   // Type to distinguish between biff7 and biff8
321
private static class BiffType {};
322
323   public static final BiffType biff8 = new BiffType();
324   public static final BiffType biff7 = new BiffType();
325
326   /**
327    * The biff type
328    */

329   private BiffType biffType;
330
331   // Type to distinguish between cell and style records
332
private static class XFType
333   {
334   }
335   protected static final XFType cell = new XFType();
336   protected static final XFType style = new XFType();
337
338   /**
339    * Constructs this object from the raw data
340    *
341    * @param t the raw data
342    * @param bt the biff type
343    */

344   public XFRecord(Record t, WorkbookSettings ws, BiffType bt)
345   {
346     super(t);
347
348     biffType = bt;
349
350     byte[] data = getRecord().getData();
351
352     fontIndex = IntegerHelper.getInt(data[0], data[1]);
353     formatIndex = IntegerHelper.getInt(data[2], data[3]);
354     date = false;
355     number = false;
356
357
358     // Compare against the date formats
359
for (int i = 0; i < dateFormats.length && date == false; i++)
360     {
361       if (formatIndex == dateFormats[i])
362       {
363         date = true;
364         dateFormat = javaDateFormats[i];
365       }
366     }
367
368     // Compare against the number formats
369
for (int i = 0; i < numberFormats.length && number == false; i++)
370     {
371       if (formatIndex == numberFormats[i])
372       {
373         number = true;
374         DecimalFormat JavaDoc df = (DecimalFormat JavaDoc) javaNumberFormats[i].clone();
375         DecimalFormatSymbols JavaDoc symbols =
376           new DecimalFormatSymbols JavaDoc(ws.getLocale());
377         df.setDecimalFormatSymbols(symbols);
378         numberFormat = df;
379         //numberFormat = javaNumberFormats[i];
380
}
381     }
382
383     // Initialize the parent format and the type
384
int cellAttributes = IntegerHelper.getInt(data[4], data[5]);
385     parentFormat = (cellAttributes & 0xfff0) >> 4;
386
387     int formatType = cellAttributes & 0x4;
388     xfFormatType = formatType == 0 ? cell : style;
389     locked = ((cellAttributes & 0x1) != 0);
390     hidden = ((cellAttributes & 0x2) != 0);
391
392     if (xfFormatType == cell &&
393         (parentFormat & 0xfff) == 0xfff)
394     {
395       // Something is screwy with the parent format - set to zero
396
parentFormat = 0;
397       logger.warn("Invalid parent format found - ignoring");
398     }
399
400     initialized = false;
401     read = true;
402     formatInfoInitialized = false;
403     copied = false;
404   }
405
406   /**
407    * A constructor used when creating a writable record
408    *
409    * @param fnt the font
410    * @param form the format
411    */

412   public XFRecord(FontRecord fnt, DisplayFormat form)
413   {
414     super(Type.XF);
415
416     initialized = false;
417     locked = true;
418     hidden = false;
419     align = Alignment.GENERAL;
420     valign = VerticalAlignment.BOTTOM;
421     orientation = Orientation.HORIZONTAL;
422     wrap = false;
423     leftBorder = BorderLineStyle.NONE;
424     rightBorder = BorderLineStyle.NONE;
425     topBorder = BorderLineStyle.NONE;
426     bottomBorder = BorderLineStyle.NONE;
427     leftBorderColour = Colour.AUTOMATIC;
428     rightBorderColour = Colour.AUTOMATIC;
429     topBorderColour = Colour.AUTOMATIC;
430     bottomBorderColour = Colour.AUTOMATIC;
431     pattern = Pattern.NONE;
432     backgroundColour = Colour.DEFAULT_BACKGROUND;
433     indentation = 0;
434     shrinkToFit = false;
435
436     // This will be set by the initialize method and the subclass respectively
437
parentFormat = 0;
438     xfFormatType = null;
439
440     font = fnt;
441     format = form;
442     biffType = biff8;
443     read = false;
444     copied = false;
445     formatInfoInitialized = true;
446
447     Assert.verify(font != null);
448     Assert.verify(format != null);
449   }
450
451   /**
452    * Copy constructor. Used for copying writable formats, typically
453    * when duplicating formats to handle merged cells
454    *
455    * @param fmt XFRecord
456    */

457   protected XFRecord(XFRecord fmt)
458   {
459     super(Type.XF);
460
461     initialized = false;
462     locked = fmt.locked;
463     hidden = fmt.hidden;
464     align = fmt.align;
465     valign = fmt.valign;
466     orientation = fmt.orientation;
467     wrap = fmt.wrap;
468     leftBorder = fmt.leftBorder;
469     rightBorder = fmt.rightBorder;
470     topBorder = fmt.topBorder;
471     bottomBorder = fmt.bottomBorder;
472     leftBorderColour = fmt.leftBorderColour;
473     rightBorderColour = fmt.rightBorderColour;
474     topBorderColour = fmt.topBorderColour;
475     bottomBorderColour = fmt.bottomBorderColour;
476     pattern = fmt.pattern;
477     xfFormatType = fmt.xfFormatType;
478     indentation = fmt.indentation;
479     shrinkToFit = fmt.shrinkToFit;
480     parentFormat = fmt.parentFormat;
481     backgroundColour = fmt.backgroundColour;
482
483     // Shallow copy is sufficient for these purposes
484
font = fmt.font;
485     format = fmt.format;
486
487     fontIndex = fmt.fontIndex;
488     formatIndex = fmt.formatIndex;
489
490     formatInfoInitialized = fmt.formatInfoInitialized;
491
492     biffType = biff8;
493     read = false;
494     copied = true;
495   }
496
497   /**
498    * A public copy constructor which can be used for copy formats between
499    * different sheets. Unlike the the other copy constructor, this
500    * version does a deep copy
501    *
502    * @param cellFormat the format to copy
503    */

504   protected XFRecord(CellFormat cellFormat)
505   {
506     super(Type.XF);
507
508     Assert.verify(cellFormat != null);
509     Assert.verify(cellFormat instanceof XFRecord);
510     XFRecord fmt = (XFRecord) cellFormat;
511
512     if (!fmt.formatInfoInitialized)
513     {
514       fmt.initializeFormatInformation();
515     }
516
517     locked = fmt.locked;
518     hidden = fmt.hidden;
519     align = fmt.align;
520     valign = fmt.valign;
521     orientation = fmt.orientation;
522     wrap = fmt.wrap;
523     leftBorder = fmt.leftBorder;
524     rightBorder = fmt.rightBorder;
525     topBorder = fmt.topBorder;
526     bottomBorder = fmt.bottomBorder;
527     leftBorderColour = fmt.leftBorderColour;
528     rightBorderColour = fmt.rightBorderColour;
529     topBorderColour = fmt.topBorderColour;
530     bottomBorderColour = fmt.bottomBorderColour;
531     pattern = fmt.pattern;
532     xfFormatType = fmt.xfFormatType;
533     parentFormat = fmt.parentFormat;
534     indentation = fmt.indentation;
535     shrinkToFit = fmt.shrinkToFit;
536     backgroundColour = fmt.backgroundColour;
537
538     // Deep copy of the font
539
font = new FontRecord(fmt.getFont());
540
541     // Copy the format
542
if (fmt.getFormat() == null)
543     {
544       // format is writable
545
if (fmt.format.isBuiltIn())
546       {
547         format = fmt.format;
548       }
549       else
550       {
551         // Format is not built in, so do a deep copy
552
format = new FormatRecord((FormatRecord) fmt.format);
553       }
554     }
555     else if (fmt.getFormat() instanceof BuiltInFormat)
556     {
557       // read excel format is built in
558
excelFormat = (BuiltInFormat) fmt.excelFormat;
559       format = (BuiltInFormat) fmt.excelFormat;
560     }
561     else
562     {
563       // read excel format is user defined
564
Assert.verify(fmt.formatInfoInitialized);
565
566       // in this case FormattingRecords should initialize the excelFormat
567
// field with an instance of FormatRecord
568
Assert.verify(fmt.excelFormat instanceof FormatRecord);
569
570       // Format is not built in, so do a deep copy
571
FormatRecord fr = new FormatRecord((FormatRecord) fmt.excelFormat);
572
573       // Set both format fields to be the same object, since
574
// FormatRecord implements all the necessary interfaces
575
excelFormat = fr;
576       format = fr;
577     }
578
579     biffType = biff8;
580
581     // The format info should be all OK by virtue of the deep copy
582
formatInfoInitialized = true;
583     
584
585     // This format was not read in
586
read = false;
587
588     // Treat this as a new cell record, so set the copied flag to false
589
copied = false;
590
591     // The font or format indexes need to be set, so set initialized to false
592
initialized = false;
593   }
594
595   /**
596    * Gets the java date format for this format record
597    *
598    * @return returns the date format
599    */

600   public DateFormat JavaDoc getDateFormat()
601   {
602     return dateFormat;
603   }
604
605   /**
606    * Gets the java number format for this format record
607    *
608    * @return returns the number format
609    */

610   public NumberFormat JavaDoc getNumberFormat()
611   {
612     return numberFormat;
613   }
614
615   /**
616    * Gets the lookup number of the format record
617    *
618    * @return returns the lookup number of the format record
619    */

620   public int getFormatRecord()
621   {
622     return formatIndex;
623   }
624
625   /**
626    * Sees if this format is a date format
627    *
628    * @return TRUE if this refers to a built in date format
629    */

630   public boolean isDate()
631   {
632     return date;
633   }
634
635   /**
636    * Sees if this format is a number format
637    *
638    * @return TRUE if this refers to a built in date format
639    */

640   public boolean isNumber()
641   {
642     return number;
643   }
644
645   /**
646    * Converts the various fields into binary data. If this object has
647    * been read from an Excel file rather than being requested by a user (ie.
648    * if the read flag is TRUE) then
649    * no processing takes place and the raw data is simply returned.
650    *
651    * @return the raw data for writing
652    */

653   public byte[] getData()
654   {
655     // Format rationalization process means that we always want to
656
// regenerate the format info - even if the spreadsheet was
657
// read in
658
if (!formatInfoInitialized)
659     {
660       initializeFormatInformation();
661     }
662
663     byte[] data = new byte[20];
664
665     IntegerHelper.getTwoBytes(fontIndex, data, 0);
666     IntegerHelper.getTwoBytes(formatIndex, data, 2);
667
668     // Do the cell attributes
669
int cellAttributes = 0;
670
671     if (getLocked())
672     {
673       cellAttributes |= 0x01;
674     }
675
676     if (getHidden())
677     {
678       cellAttributes |= 0x02;
679     }
680
681     if (xfFormatType == style)
682     {
683       cellAttributes |= 0x04;
684       parentFormat = 0xffff;
685     }
686
687     cellAttributes |= (parentFormat << 4);
688
689     IntegerHelper.getTwoBytes(cellAttributes, data, 4);
690
691     int alignMask = align.getValue();
692
693     if (wrap)
694     {
695       alignMask |= 0x08;
696     }
697
698     alignMask |= (valign.getValue() << 4);
699
700     alignMask |= (orientation.getValue() << 8);
701
702     IntegerHelper.getTwoBytes(alignMask, data, 6);
703
704     data[9] = (byte) 0x10;
705
706     // Set the borders
707
int borderMask = leftBorder.getValue();
708     borderMask |= (rightBorder.getValue() << 4);
709     borderMask |= (topBorder.getValue() << 8);
710     borderMask |= (bottomBorder.getValue() << 12);
711
712     IntegerHelper.getTwoBytes(borderMask, data, 10);
713
714     // Set the border palette information if border mask is non zero
715
// Hard code the colours to be black
716
if (borderMask != 0)
717     {
718         byte lc = (byte)leftBorderColour.getValue();
719         byte rc = (byte)rightBorderColour.getValue();
720         byte tc = (byte)topBorderColour.getValue();
721         byte bc = (byte)bottomBorderColour.getValue();
722
723       int sideColourMask = (lc & 0x7f) | ((rc & 0x7f) << 7);
724       int topColourMask = (tc & 0x7f) | ((bc & 0x7f) << 7);
725
726       IntegerHelper.getTwoBytes(sideColourMask, data, 12);
727       IntegerHelper.getTwoBytes(topColourMask, data, 14);
728     }
729
730     // Set the background pattern
731
int patternVal = pattern.getValue() << 10;
732     IntegerHelper.getTwoBytes(patternVal, data, 16);
733
734     // Set the colour palette
735
int colourPaletteMask = backgroundColour.getValue();
736     colourPaletteMask |= (0x40 << 7);
737     IntegerHelper.getTwoBytes(colourPaletteMask, data, 18);
738
739     // Set the cell options
740
options |= indentation & 0x0f;
741
742     if (shrinkToFit)
743     {
744       options |= 0x10;
745     }
746     else
747     {
748       options &= 0xef;
749     }
750
751     data[8] = (byte) options;
752
753     if (biffType == biff8)
754     {
755       // usedAttributes = 0x4 << 2;
756
data[9] = usedAttributes;
757     }
758
759     return data;
760   }
761
762   /**
763    * Accessor for the locked flag
764    *
765    * @return TRUE if this XF record locks cells, FALSE otherwise
766    */

767   protected final boolean getLocked()
768   {
769     return locked;
770   }
771
772   /**
773    * Accessor for the hidden flag
774    *
775    * @return TRUE if this XF record hides the cell, FALSE otherwise
776    */

777   protected final boolean getHidden()
778   {
779     return hidden;
780   }
781
782   /**
783    * Sets whether or not this XF record locks the cell
784    *
785    * @param l the locked flag
786    */

787   protected final void setXFLocked(boolean l)
788   {
789     locked = l;
790   }
791
792   /**
793    * Sets the cell options
794    *
795    * @param opt the cell options
796    */

797   protected final void setXFCellOptions(int opt)
798   {
799     options |= opt;
800   }
801
802   /**
803    * Sets the horizontal alignment for the data in this cell.
804    * This method should only be called from its writable subclass
805    * CellXFRecord
806    *
807    * @param a the alignment
808    */

809   protected void setXFAlignment(Alignment a)
810   {
811     Assert.verify(!initialized);
812     align = a;
813   }
814
815   /**
816    * Sets the indentation
817    *
818    * @param i the indentation
819    */

820   protected void setXFIndentation(int i)
821   {
822     Assert.verify(!initialized);
823     indentation = i;
824   }
825
826   /**
827    * Sets the shrink to fit flag
828    *
829    * @param s the shrink to fit flag
830    */

831   protected void setXFShrinkToFit(boolean s)
832   {
833     Assert.verify(!initialized);
834     shrinkToFit = s;
835   }
836
837   /**
838    * Gets the horizontal cell alignment
839    *
840    * @return the alignment
841    */

842   public Alignment getAlignment()
843   {
844     if (!formatInfoInitialized)
845     {
846       initializeFormatInformation();
847     }
848
849     return align;
850   }
851
852   /**
853    * Gets the indentation
854    *
855    * @return the indentation
856    */

857   public int getIndentation()
858   {
859     if (!formatInfoInitialized)
860     {
861       initializeFormatInformation();
862     }
863
864     return indentation;
865   }
866
867   /**
868    * Gets the shrink to fit flag
869    *
870    * @return TRUE if this format is shrink to fit, FALSE otherise
871    */

872   public boolean isShrinkToFit()
873   {
874     if (!formatInfoInitialized)
875     {
876       initializeFormatInformation();
877     }
878
879     return shrinkToFit;
880   }
881
882   /**
883    * Accessor for whether a particular cell is locked
884    *
885    * @return TRUE if this cell is locked, FALSE otherwise
886    */

887   public boolean isLocked()
888   {
889     if (!formatInfoInitialized)
890     {
891       initializeFormatInformation();
892     }
893
894     return locked;
895   }
896
897
898   /**
899    * Gets the vertical cell alignment
900    *
901    * @return the alignment
902    */

903   public VerticalAlignment getVerticalAlignment()
904   {
905     if (!formatInfoInitialized)
906     {
907       initializeFormatInformation();
908     }
909
910     return valign;
911   }
912
913   /**
914    * Gets the orientation
915    *
916    * @return the orientation
917    */

918   public Orientation getOrientation()
919   {
920     if (!formatInfoInitialized)
921     {
922       initializeFormatInformation();
923     }
924
925     return orientation;
926   }
927
928   /**
929    * Sets the horizontal alignment for the data in this cell.
930    * This method should only be called from its writable subclass
931    * CellXFRecord
932    *
933    * @param c the background colour
934    * @param p the background pattern
935    */

936   protected void setXFBackground(Colour c, Pattern p)
937   {
938     Assert.verify(!initialized);
939     backgroundColour = c;
940     pattern = p;
941   }
942
943   /**
944    * Gets the background colour used by this cell
945    *
946    * @return the foreground colour
947    */

948   public Colour getBackgroundColour()
949   {
950     if (!formatInfoInitialized)
951     {
952       initializeFormatInformation();
953     }
954
955     return backgroundColour;
956   }
957
958   /**
959    * Gets the pattern used by this cell format
960    *
961    * @return the background pattern
962    */

963   public Pattern getPattern()
964   {
965     if (!formatInfoInitialized)
966     {
967       initializeFormatInformation();
968     }
969
970     return pattern;
971   }
972
973   /**
974    * Sets the vertical alignment for the data in this cell
975    * This method should only be called from its writable subclass
976    * CellXFRecord
977
978    *
979    * @param va the vertical alignment
980    */

981   protected void setXFVerticalAlignment(VerticalAlignment va)
982   {
983     Assert.verify(!initialized);
984     valign = va;
985   }
986
987   /**
988    * Sets the vertical alignment for the data in this cell
989    * This method should only be called from its writable subclass
990    * CellXFRecord
991
992    *
993    * @param o the orientation
994    */

995   protected void setXFOrientation(Orientation o)
996   {
997     Assert.verify(!initialized);
998     orientation = o;
999   }
1000
1001  /**
1002   * Sets whether the data in this cell is wrapped
1003   * This method should only be called from its writable subclass
1004   * CellXFRecord
1005   *
1006   * @param w the wrap flag
1007   */

1008  protected void setXFWrap(boolean w)
1009  {
1010    Assert.verify(!initialized);
1011    wrap = w;
1012  }
1013
1014  /**
1015   * Gets whether or not the contents of this cell are wrapped
1016   *
1017   * @return TRUE if this cell's contents are wrapped, FALSE otherwise
1018   */

1019  public boolean getWrap()
1020  {
1021    if (!formatInfoInitialized)
1022    {
1023      initializeFormatInformation();
1024    }
1025
1026    return wrap;
1027  }
1028
1029  /**
1030   * Sets the border for this cell
1031   * This method should only be called from its writable subclass
1032   * CellXFRecord
1033   *
1034   * @param b the border
1035   * @param ls the border line style
1036   */

1037  protected void setXFBorder(Border b, BorderLineStyle ls, Colour c)
1038  {
1039    Assert.verify(!initialized);
1040    
1041    if (c==Colour.BLACK)
1042    {
1043      c = Colour.PALETTE_BLACK;
1044    }
1045
1046    if (b == Border.LEFT)
1047    {
1048      leftBorder = ls;
1049      leftBorderColour = c;
1050    }
1051    else if (b == Border.RIGHT)
1052    {
1053      rightBorder = ls;
1054      rightBorderColour = c;
1055    }
1056    else if (b == Border.TOP)
1057    {
1058      topBorder = ls;
1059      topBorderColour = c;
1060    }
1061    else if (b == Border.BOTTOM)
1062    {
1063      bottomBorder = ls;
1064      bottomBorderColour = c;
1065    }
1066    return;
1067  }
1068
1069
1070  /**
1071   * Gets the line style for the given cell border
1072   * If a border type of ALL or NONE is specified, then a line style of
1073   * NONE is returned
1074   *
1075   * @param border the cell border we are interested in
1076   * @return the line style of the specified border
1077   */

1078  public BorderLineStyle getBorder(Border border)
1079  {
1080    return getBorderLine(border);
1081  }
1082
1083  /**
1084   * Gets the line style for the given cell border
1085   * If a border type of ALL or NONE is specified, then a line style of
1086   * NONE is returned
1087   *
1088   * @param border the cell border we are interested in
1089   * @return the line style of the specified border
1090   */

1091  public BorderLineStyle getBorderLine(Border border)
1092  {
1093    // Don't bother with the short cut records
1094
if (border == Border.NONE ||
1095        border == Border.ALL)
1096    {
1097      return BorderLineStyle.NONE;
1098    }
1099
1100    if (!formatInfoInitialized)
1101    {
1102      initializeFormatInformation();
1103    }
1104
1105    if (border == Border.LEFT)
1106    {
1107      return leftBorder;
1108    }
1109    else if (border == Border.RIGHT)
1110    {
1111      return rightBorder;
1112    }
1113    else if (border == Border.TOP)
1114    {
1115      return topBorder;
1116    }
1117    else if (border == Border.BOTTOM)
1118    {
1119      return bottomBorder;
1120    }
1121
1122    return BorderLineStyle.NONE;
1123  }
1124
1125  /**
1126   * Gets the line style for the given cell border
1127   * If a border type of ALL or NONE is specified, then a line style of
1128   * NONE is returned
1129   *
1130   * @param border the cell border we are interested in
1131   * @return the line style of the specified border
1132   */

1133  public Colour getBorderColour(Border border)
1134  {
1135    // Don't bother with the short cut records
1136
if (border == Border.NONE ||
1137        border == Border.ALL)
1138    {
1139      return Colour.PALETTE_BLACK;
1140    }
1141
1142    if (!formatInfoInitialized)
1143    {
1144      initializeFormatInformation();
1145    }
1146
1147    if (border == Border.LEFT)
1148    {
1149      return leftBorderColour;
1150    }
1151    else if (border == Border.RIGHT)
1152    {
1153      return rightBorderColour;
1154    }
1155    else if (border == Border.TOP)
1156    {
1157      return topBorderColour;
1158    }
1159    else if (border == Border.BOTTOM)
1160    {
1161      return bottomBorderColour;
1162    }
1163
1164    return Colour.BLACK;
1165  }
1166
1167
1168  /**
1169   * Determines if this cell format has any borders at all. Used to
1170   * set the new borders when merging a group of cells
1171   *
1172   * @return TRUE if this cell has any borders, FALSE otherwise
1173   */

1174  public final boolean hasBorders()
1175  {
1176    if (!formatInfoInitialized)
1177    {
1178      initializeFormatInformation();
1179    }
1180
1181    if (leftBorder == BorderLineStyle.NONE &&
1182        rightBorder == BorderLineStyle.NONE &&
1183        topBorder == BorderLineStyle.NONE &&
1184        bottomBorder == BorderLineStyle.NONE)
1185    {
1186      return false;
1187    }
1188
1189    return true;
1190  }
1191
1192  /**
1193   * If this cell has not been read in from an existing Excel sheet,
1194   * then initializes this record with the XF index passed in. Calls
1195   * initialized on the font and format record
1196   *
1197   * @param pos the xf index to initialize this record with
1198   * @param fr the containing formatting records
1199   * @param fonts the container for the fonts
1200   * @exception NumFormatRecordsException
1201   */

1202  public final void initialize(int pos, FormattingRecords fr, Fonts fonts)
1203    throws NumFormatRecordsException
1204  {
1205    xfIndex = pos;
1206    formattingRecords = fr;
1207
1208    // If this file has been read in or copied,
1209
// the font and format indexes will
1210
// already be initialized, so just set the initialized flag and
1211
// return
1212
if (read || copied)
1213    {
1214      initialized = true;
1215      return;
1216    }
1217
1218    if (!font.isInitialized())
1219    {
1220      fonts.addFont(font);
1221    }
1222
1223    if (!format.isInitialized())
1224    {
1225      fr.addFormat(format);
1226    }
1227
1228    fontIndex = font.getFontIndex();
1229    formatIndex = format.getFormatIndex();
1230
1231    initialized = true;
1232  }
1233
1234  /**
1235   * Resets the initialize flag. This is called by the constructor of
1236   * WritableWorkbookImpl to reset the statically declared fonts
1237   */

1238  public final void uninitialize()
1239  {
1240    // As the default formats are cloned internally, the initialized
1241
// flag should never be anything other than false
1242
if (initialized == true)
1243    {
1244      logger.warn("A default format has been initialized");
1245    }
1246    initialized = false;
1247  }
1248
1249  /**
1250   * Sets the XF index. Called when rationalizing the XF records
1251   * immediately prior to writing
1252   *
1253   * @param xfi the new xf index
1254   */

1255  final void setXFIndex(int xfi)
1256  {
1257    xfIndex = xfi;
1258  }
1259
1260  /**
1261   * Accessor for the XF index
1262   *
1263   * @return the XF index for this cell
1264   */

1265  public final int getXFIndex()
1266  {
1267    return xfIndex;
1268  }
1269
1270  /**
1271   * Accessor to see if this format is initialized
1272   *
1273   * @return TRUE if this format is initialized, FALSE otherwise
1274   */

1275  public final boolean isInitialized()
1276  {
1277    return initialized;
1278  }
1279
1280  /**
1281   * Accessor to see if this format was read in. Used when checking merged
1282   * cells
1283   *
1284   * @return TRUE if this XF record was read in, FALSE if it was generated by
1285   * the user API
1286   */

1287  public final boolean isRead()
1288  {
1289    return read;
1290  }
1291
1292  /**
1293   * Gets the format used by this format
1294   *
1295   * @return the format
1296   */

1297  public Format JavaDoc getFormat()
1298  {
1299    if (!formatInfoInitialized)
1300    {
1301      initializeFormatInformation();
1302    }
1303    return excelFormat;
1304  }
1305
1306  /**
1307   * Gets the font used by this format
1308   *
1309   * @return the font
1310   */

1311  public Font getFont()
1312  {
1313    if (!formatInfoInitialized)
1314    {
1315      initializeFormatInformation();
1316    }
1317    return font;
1318  }
1319
1320  /**
1321   * Initializes the internal format information from the data read in
1322   */

1323  private void initializeFormatInformation()
1324  {
1325    // Initialize the cell format string
1326
if (formatIndex < BuiltInFormat.builtIns.length &&
1327        BuiltInFormat.builtIns[formatIndex] != null)
1328    {
1329      excelFormat = BuiltInFormat.builtIns[formatIndex];
1330    }
1331    else
1332    {
1333      excelFormat = formattingRecords.getFormatRecord(formatIndex);
1334    }
1335
1336    // Initialize the font
1337
font = formattingRecords.getFonts().getFont(fontIndex);
1338
1339    // Initialize the cell format data from the binary record
1340
byte[] data = getRecord().getData();
1341
1342    // Get the parent record
1343
int cellAttributes = IntegerHelper.getInt(data[4], data[5]);
1344    parentFormat = (cellAttributes & 0xfff0) >> 4;
1345    int formatType = cellAttributes & 0x4;
1346    xfFormatType = formatType == 0 ? cell : style;
1347    locked = ((cellAttributes & 0x1) != 0);
1348    hidden = ((cellAttributes & 0x2) != 0);
1349
1350    if (xfFormatType == cell &&
1351        (parentFormat & 0xfff) == 0xfff)
1352    {
1353      // Something is screwy with the parent format - set to zero
1354
parentFormat = 0;
1355      logger.warn("Invalid parent format found - ignoring");
1356    }
1357
1358
1359    int alignMask = IntegerHelper.getInt(data[6], data[7]);
1360
1361    // Get the wrap
1362
if ((alignMask & 0x08) != 0)
1363    {
1364      wrap = true;
1365    }
1366
1367    // Get the horizontal alignment
1368
align = Alignment.getAlignment(alignMask & 0x7);
1369
1370    // Get the vertical alignment
1371
valign = VerticalAlignment.getAlignment((alignMask >> 4) & 0x7);
1372
1373    // Get the orientation
1374
orientation = Orientation.getOrientation((alignMask >> 8) & 0xff);
1375
1376    int attr = IntegerHelper.getInt(data[8], data[9]);
1377
1378    // Get the indentation
1379
indentation = (int) (attr & 0x0F);
1380
1381    // Get the shrink to fit flag
1382
shrinkToFit = (attr & 0x10) != 0;
1383
1384    // Get the used attribute
1385
if (biffType == biff8)
1386    {
1387      usedAttributes = data[9];
1388    }
1389
1390    // Get the borders
1391
int borderMask = IntegerHelper.getInt(data[10], data[11]);
1392
1393    leftBorder = BorderLineStyle.getStyle(borderMask & 0x7);
1394    rightBorder = BorderLineStyle.getStyle((borderMask >> 4) & 0x7);
1395    topBorder = BorderLineStyle.getStyle((borderMask >> 8) & 0x7);
1396    bottomBorder = BorderLineStyle.getStyle((borderMask >> 12) & 0x7);
1397
1398    int borderColourMask = IntegerHelper.getInt(data[12], data[13]);
1399
1400    leftBorderColour = Colour.getInternalColour(borderColourMask & 0x7f);
1401    rightBorderColour = Colour.getInternalColour
1402      ((borderColourMask & 0x3f80) >> 7);
1403
1404    borderColourMask = IntegerHelper.getInt(data[14], data[15]);
1405    topBorderColour = Colour.getInternalColour(borderColourMask & 0x7f);
1406    bottomBorderColour = Colour.getInternalColour
1407      ((borderColourMask & 0x3f80) >> 7);
1408    
1409    if (biffType == biff8)
1410    {
1411      // Get the background pattern. This is the six most significant bits
1412
int patternVal = IntegerHelper.getInt(data[16], data[17]);
1413      patternVal = patternVal & 0xfc00;
1414      patternVal = patternVal >> 10;
1415      pattern = Pattern.getPattern(patternVal);
1416
1417      // Get the background colour
1418
int colourPaletteMask = IntegerHelper.getInt(data[18], data[19]);
1419      backgroundColour = Colour.getInternalColour(colourPaletteMask & 0x3f);
1420
1421      if (backgroundColour == Colour.UNKNOWN ||
1422          backgroundColour == Colour.DEFAULT_BACKGROUND1)
1423      {
1424        backgroundColour = Colour.DEFAULT_BACKGROUND;
1425      }
1426    }
1427    else
1428    {
1429      pattern = Pattern.NONE;
1430      backgroundColour = Colour.DEFAULT_BACKGROUND;
1431    }
1432
1433    // Set the lazy initialization flag
1434
formatInfoInitialized = true;
1435  }
1436
1437  /**
1438   * Standard hash code implementation
1439   * @return the hash code
1440   */

1441  public int hashCode()
1442  {
1443    // Must have its formats info initialized in order to compute the hash code
1444
if (!formatInfoInitialized)
1445    {
1446      initializeFormatInformation();
1447    }
1448
1449    int hashValue = 17;
1450    int oddPrimeNumber = 37;
1451
1452    // The boolean fields
1453
hashValue = oddPrimeNumber*hashValue + (hidden ? 1:0);
1454    hashValue = oddPrimeNumber*hashValue + (locked ? 1:0);
1455    hashValue = oddPrimeNumber*hashValue + (wrap ? 1:0);
1456    hashValue = oddPrimeNumber*hashValue + (shrinkToFit ? 1:0);
1457
1458    // The enumerations
1459
if (xfFormatType == cell)
1460    {
1461      hashValue = oddPrimeNumber*hashValue + 1;
1462    }
1463    else if (xfFormatType == style)
1464    {
1465      hashValue = oddPrimeNumber*hashValue + 2;
1466    }
1467
1468    hashValue = oddPrimeNumber*hashValue + (align.getValue() + 1);
1469    hashValue = oddPrimeNumber*hashValue + (valign.getValue() + 1);
1470    hashValue = oddPrimeNumber*hashValue + (orientation.getValue());
1471
1472    hashValue ^= leftBorder.getDescription().hashCode();
1473    hashValue ^= rightBorder.getDescription().hashCode();
1474    hashValue ^= topBorder.getDescription().hashCode();
1475    hashValue ^= bottomBorder.getDescription().hashCode();
1476
1477    hashValue = oddPrimeNumber*hashValue + (leftBorderColour.getValue());
1478    hashValue = oddPrimeNumber*hashValue + (rightBorderColour.getValue());
1479    hashValue = oddPrimeNumber*hashValue + (topBorderColour.getValue());
1480    hashValue = oddPrimeNumber*hashValue + (bottomBorderColour.getValue());
1481    hashValue = oddPrimeNumber*hashValue + (backgroundColour.getValue());
1482    hashValue = oddPrimeNumber*hashValue + (pattern.getValue() + 1);
1483
1484    // The integer fields
1485
hashValue = oddPrimeNumber*hashValue + usedAttributes;
1486    hashValue = oddPrimeNumber*hashValue + parentFormat;
1487    hashValue = oddPrimeNumber*hashValue + fontIndex;
1488    hashValue = oddPrimeNumber*hashValue + formatIndex;
1489    hashValue = oddPrimeNumber*hashValue + indentation;
1490
1491    return hashValue;
1492  }
1493
1494  /**
1495   * Equals method. This is called when comparing writable formats
1496   * in order to prevent duplicate formats being added to the workbook
1497   *
1498   * @param o object to compare
1499   * @return TRUE if the objects are equal, FALSE otherwise
1500   */

1501  public boolean equals(Object JavaDoc o)
1502  {
1503    if (o == this)
1504    {
1505      return true;
1506    }
1507
1508    if (!(o instanceof XFRecord))
1509    {
1510      return false;
1511    }
1512
1513    XFRecord xfr = (XFRecord) o;
1514
1515    // Both records must be writable and have their format info initialized
1516
if (!formatInfoInitialized)
1517    {
1518      initializeFormatInformation();
1519    }
1520
1521    if (!xfr.formatInfoInitialized)
1522    {
1523      xfr.initializeFormatInformation();
1524    }
1525
1526    if (xfFormatType != xfr.xfFormatType ||
1527        parentFormat != xfr.parentFormat ||
1528        locked != xfr.locked ||
1529        hidden != xfr.hidden ||
1530        usedAttributes != xfr.usedAttributes)
1531    {
1532      return false;
1533    }
1534
1535    if (align != xfr.align ||
1536        valign != xfr.valign ||
1537        orientation != xfr.orientation ||
1538        wrap != xfr.wrap ||
1539        shrinkToFit != xfr.shrinkToFit ||
1540        indentation != xfr.indentation)
1541    {
1542      return false;
1543    }
1544
1545    if (leftBorder != xfr.leftBorder ||
1546        rightBorder != xfr.rightBorder ||
1547        topBorder != xfr.topBorder ||
1548        bottomBorder != xfr.bottomBorder)
1549    {
1550      return false;
1551    }
1552
1553    if (leftBorderColour != xfr.leftBorderColour ||
1554        rightBorderColour != xfr.rightBorderColour ||
1555        topBorderColour != xfr.topBorderColour ||
1556        bottomBorderColour != xfr.bottomBorderColour)
1557    {
1558      return false;
1559    }
1560
1561    if (backgroundColour != xfr.backgroundColour ||
1562        pattern != xfr.pattern)
1563    {
1564      return false;
1565    }
1566
1567    // Sufficient to just do shallow equals on font, format objects,
1568
// since we are testing for the presence of clones anwyay
1569
// Use indices rather than objects because of the rationalization
1570
// process (which does not set the object on an XFRecord)
1571
if (fontIndex != xfr.fontIndex ||
1572        formatIndex != xfr.formatIndex)
1573    {
1574      return false;
1575    }
1576
1577    return true;
1578  }
1579
1580  /**
1581   * Sets the format index. This is called during the rationalization process
1582   * when some of the duplicate number formats have been removed
1583   * @param newindex the new format index
1584   */

1585  void setFormatIndex(int newindex)
1586  {
1587    formatIndex = newindex;
1588  }
1589
1590  /**
1591   * Accessor for the font index. Called by the FormattingRecords objects
1592   * during the rationalization process
1593   * @return the font index
1594   */

1595  int getFontIndex()
1596  {
1597    return fontIndex;
1598  }
1599
1600
1601  /**
1602   * Sets the font index. This is called during the rationalization process
1603   * when some of the duplicate fonts have been removed
1604   * @param newindex the new index
1605   */

1606  void setFontIndex(int newindex)
1607  {
1608    fontIndex = newindex;
1609  }
1610
1611  /**
1612   * Sets the format type and parent format from the writable subclass
1613   * @param t the xf type
1614   * @param pf the parent format
1615   */

1616  protected void setXFDetails(XFType t, int pf)
1617  {
1618    xfFormatType = t;
1619    parentFormat = pf;
1620  }
1621
1622  /**
1623   * Changes the appropriate indexes during the rationalization process
1624   * @param xfMapping the xf index re-mappings
1625   */

1626  void rationalize(IndexMapping xfMapping)
1627  {
1628    xfIndex = xfMapping.getNewIndex(xfIndex);
1629
1630    if (xfFormatType == cell)
1631    {
1632      parentFormat = xfMapping.getNewIndex(parentFormat);
1633    }
1634  }
1635
1636  /**
1637   * Sets the font object with a workbook specific clone. Called from
1638   * the CellValue object when the font has been identified as a statically
1639   * shared font
1640   */

1641  public void setFont(FontRecord f)
1642  {
1643    // This style cannot be initialized, otherwise it would mean it would
1644
// have been initialized with shared font
1645
// However, sometimes (when setting a row or column format) an initialized
1646
// XFRecord may have its font overridden by the column/row
1647

1648    font = f;
1649  }
1650}
1651
1652
Popular Tags