KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > biff > drawing > Comment


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 package jxl.biff.drawing;
21
22 import java.io.IOException JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24
25 import common.Assert;
26 import common.Logger;
27
28 import jxl.WorkbookSettings;
29 import jxl.biff.ByteData;
30 import jxl.biff.IntegerHelper;
31 import jxl.biff.StringHelper;
32 import jxl.biff.IndexMapping;
33 import jxl.biff.Type;
34 import jxl.biff.ContinueRecord;
35 import jxl.write.biff.File;
36
37 /**
38  * Contains the various biff records used to insert a cell note into a
39  * worksheet
40  */

41 public class Comment implements DrawingGroupObject
42 {
43   /**
44    * The logger
45    */

46   private static Logger logger = Logger.getLogger(Comment.class);
47
48   /**
49    * The spContainer that was read in
50    */

51   private EscherContainer readSpContainer;
52
53   /**
54    * The spContainer that was generated
55    */

56   private EscherContainer spContainer;
57
58   /**
59    * The MsoDrawingRecord associated with the drawing
60    */

61   private MsoDrawingRecord msoDrawingRecord;
62
63   /**
64    * The ObjRecord associated with the drawing
65    */

66   private ObjRecord objRecord;
67
68   /**
69    * Initialized flag
70    */

71   private boolean initialized = false;
72
73   /**
74    * The object id, assigned by the drawing group
75    */

76   private int objectId;
77
78   /**
79    * The blip id
80    */

81   private int blipId;
82
83   /**
84    * The shape id
85    */

86   private int shapeId;
87
88   /**
89    * The column
90    */

91   private int column;
92
93   /**
94    * The row position of the image
95    */

96   private int row;
97
98   /**
99    * The width of the image in cells
100    */

101   private double width;
102
103   /**
104    * The height of the image in cells
105    */

106   private double height;
107
108   /**
109    * The number of places this drawing is referenced
110    */

111   private int referenceCount;
112
113   /**
114    * The top level escher container
115    */

116   private EscherContainer escherData;
117
118   /**
119    * Where this image came from (read, written or a copy)
120    */

121   private Origin origin;
122
123   /**
124    * The drawing group for all the images
125    */

126   private DrawingGroup drawingGroup;
127
128   /**
129    * The drawing data
130    */

131   private DrawingData drawingData;
132
133   /**
134    * The type of this drawing object
135    */

136   private ShapeType type;
137
138   /**
139    * The drawing position on the sheet
140    */

141   private int drawingNumber;
142
143   /**
144    * An mso drawing record, which sometimes appears
145    */

146   private MsoDrawingRecord mso;
147
148   /**
149    * The text object record
150    */

151   private TextObjectRecord txo;
152
153   /**
154    * The note record
155    */

156   private NoteRecord note;
157
158   /**
159    * Text data from the first continue record
160    */

161   private ContinueRecord text;
162
163   /**
164    * Formatting data from the second continue record
165    */

166   private ContinueRecord formatting;
167
168   /**
169    * The comment text
170    */

171   private String JavaDoc commentText;
172   
173   /**
174    * The workbook settings
175    */

176   private WorkbookSettings workbookSettings;
177
178   /**
179    * Constructor used when reading images
180    *
181    * @param mso the drawing record
182    * @param obj the object record
183    * @param dd the drawing data for all drawings on this sheet
184    * @param dg the drawing group
185    * @param ws the workbook settings
186    */

187   public Comment(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd,
188                  DrawingGroup dg, WorkbookSettings ws)
189   {
190     drawingGroup = dg;
191     msoDrawingRecord = mso;
192     drawingData = dd;
193     objRecord = obj;
194     initialized = false;
195     workbookSettings = ws;
196     origin = Origin.READ;
197     drawingData.addData(msoDrawingRecord.getData());
198     drawingNumber = drawingData.getNumDrawings() - 1;
199     drawingGroup.addDrawing(this);
200
201     Assert.verify(mso != null && obj != null);
202
203     if (!initialized)
204     {
205       initialize();
206     }
207   }
208
209   /**
210    * Copy constructor used to copy drawings from read to write
211    *
212    * @param d the drawing to copy
213    */

214   /*protected*/ public Comment(DrawingGroupObject dgo,
215                                DrawingGroup dg,
216                                WorkbookSettings ws)
217   {
218     Comment d = (Comment) dgo;
219     Assert.verify(d.origin == Origin.READ);
220     msoDrawingRecord = d.msoDrawingRecord;
221     objRecord = d.objRecord;
222     initialized = false;
223     origin = Origin.READ;
224     drawingData = d.drawingData;
225     drawingGroup = dg;
226     drawingNumber = d.drawingNumber;
227     drawingGroup.addDrawing(this);
228     mso = d.mso;
229     txo = d.txo;
230     text = d.text;
231     formatting = d.formatting;
232     note = d.note;
233     width = d.width;
234     height = d.height;
235     workbookSettings = ws;
236   }
237
238   /**
239    * Constructor invoked when writing the images
240    *
241    * @param text the comment text
242    * @param c the column
243    * @param r the row
244    * @param width the width in cells
245    * @param height the height in cells
246    */

247   public Comment(String JavaDoc text, int c, int r)
248   {
249     initialized = true;
250     origin = Origin.WRITE;
251     column = c;
252     row = r;
253     referenceCount = 1;
254     type = ShapeType.TEXT_BOX;
255     commentText = text;
256     width = 3;
257     height = 4;
258   }
259
260   /**
261    * Initializes the member variables from the Escher stream data
262    */

263   private void initialize()
264   {
265     readSpContainer = drawingData.getSpContainer(drawingNumber);
266     Assert.verify(readSpContainer != null);
267
268     EscherRecord[] children = readSpContainer.getChildren();
269
270     Sp sp = (Sp) readSpContainer.getChildren()[0];
271     objectId = objRecord.getObjectId();
272     shapeId = sp.getShapeId();
273     type = ShapeType.getType(sp.getShapeType());
274
275     if (type == ShapeType.UNKNOWN)
276     {
277       logger.warn("Unknown shape type");
278     }
279
280     Opt opt = (Opt) readSpContainer.getChildren()[1];
281
282     ClientAnchor clientAnchor = null;
283     for (int i = 0 ; i < children.length && clientAnchor == null ; i++)
284     {
285       if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
286       {
287         clientAnchor = (ClientAnchor) children[i];
288       }
289     }
290     
291     if (clientAnchor == null)
292     {
293       logger.warn("client anchor not found");
294     }
295     else
296     {
297       column = (int) clientAnchor.getX1() - 1;
298       row = (int) clientAnchor.getY1() + 1;
299       width = clientAnchor.getX2() - clientAnchor.getX1();
300       height = clientAnchor.getY2() - clientAnchor.getY1();
301     }
302
303     initialized = true;
304   }
305
306
307   /**
308    * Sets the object id. Invoked by the drawing group when the object is
309    * added to id
310    *
311    * @param objid the object id
312    * @param bip the blip id
313    * @param sid the shape id
314    */

315   public final void setObjectId(int objid, int bip, int sid)
316   {
317     objectId = objid;
318     blipId = bip;
319     shapeId = sid;
320
321     if (origin == Origin.READ)
322     {
323       origin = Origin.READ_WRITE;
324     }
325   }
326
327   /**
328    * Accessor for the object id
329    *
330    * @return the object id
331    */

332   public final int getObjectId()
333   {
334     if (!initialized)
335     {
336       initialize();
337     }
338
339     return objectId;
340   }
341
342   /**
343    * Accessor for the shape id
344    *
345    * @return the object id
346    */

347   public final int getShapeId()
348   {
349     if (!initialized)
350     {
351       initialize();
352     }
353
354     return shapeId;
355   }
356
357   /**
358    * Accessor for the blip id
359    *
360    * @return the blip id
361    */

362   public final int getBlipId()
363   {
364     if (!initialized)
365     {
366       initialize();
367     }
368
369     return blipId;
370   }
371
372   /**
373    * Gets the drawing record which was read in
374    *
375    * @return the drawing record
376    */

377   public MsoDrawingRecord getMsoDrawingRecord()
378   {
379     return msoDrawingRecord;
380   }
381   
382   /**
383    * Creates the main Sp container for the drawing
384    *
385    * @return the SP container
386    */

387   public EscherContainer getSpContainer()
388   {
389     if (!initialized)
390     {
391       initialize();
392     }
393
394     if (origin == Origin.READ)
395     {
396       return getReadSpContainer();
397     }
398
399     if (spContainer == null)
400     {
401       spContainer = new SpContainer();
402       Sp sp = new Sp(type, shapeId, 2560);
403       spContainer.add(sp);
404       Opt opt = new Opt();
405       opt.addProperty(344, false, false, 0); // ?
406
opt.addProperty(385, false, false, 134217808); // fill colour
407
opt.addProperty(387, false, false, 134217808); // background colour
408
opt.addProperty(959, false, false, 131074); // hide
409
spContainer.add(opt);
410
411       ClientAnchor clientAnchor = new ClientAnchor(column + 1.3,
412                                                    Math.max(0, row - 0.6),
413                                                    column + width,
414                                                    row + height);
415       
416       spContainer.add(clientAnchor);
417       
418       ClientData clientData = new ClientData();
419       spContainer.add(clientData);
420       
421       ClientTextBox clientTextBox = new ClientTextBox();
422       spContainer.add(clientTextBox);
423     }
424
425     return spContainer;
426   }
427
428   /**
429    * Sets the drawing group for this drawing. Called by the drawing group
430    * when this drawing is added to it
431    *
432    * @param dg the drawing group
433    */

434   public void setDrawingGroup(DrawingGroup dg)
435   {
436     drawingGroup = dg;
437   }
438
439   /**
440    * Accessor for the drawing group
441    *
442    * @return the drawing group
443    */

444   public DrawingGroup getDrawingGroup()
445   {
446     return drawingGroup;
447   }
448
449   /**
450    * Gets the origin of this drawing
451    *
452    * @return where this drawing came from
453    */

454   public Origin getOrigin()
455   {
456     return origin;
457   }
458   
459   /**
460    * Accessor for the reference count on this drawing
461    *
462    * @return the reference count
463    */

464   public int getReferenceCount()
465   {
466     return referenceCount;
467   }
468
469   /**
470    * Sets the new reference count on the drawing
471    *
472    * @param r the new reference count
473    */

474   public void setReferenceCount(int r)
475   {
476     referenceCount = r;
477   }
478
479   /**
480    * Accessor for the column of this drawing
481    *
482    * @return the column
483    */

484   public double getX()
485   {
486     if (!initialized)
487     {
488       initialize();
489     }
490     return column;
491   }
492
493   /**
494    * Sets the column position of this drawing. Used when inserting/removing
495    * columns from the spreadsheet
496    *
497    * @param x the column
498    */

499   public void setX(double x)
500   {
501     if (origin == Origin.READ)
502     {
503       if (!initialized)
504       {
505         initialize();
506       }
507       origin = Origin.READ_WRITE;
508     }
509
510     column = (int) x;
511   }
512
513   /**
514    * Accessor for the row of this drawing
515    *
516    * @return the row
517    */

518   public double getY()
519   {
520     if (!initialized)
521     {
522       initialize();
523     }
524
525     return row;
526   }
527
528   /**
529    * Accessor for the row of the drawing
530    *
531    * @param y the row
532    */

533   public void setY(double y)
534   {
535     if (origin == Origin.READ)
536     {
537       if (!initialized)
538       {
539         initialize();
540       }
541       origin = Origin.READ_WRITE;
542     }
543
544     row = (int) y;
545   }
546
547
548   /**
549    * Accessor for the width of this drawing
550    *
551    * @return the number of columns spanned by this image
552    */

553   public double getWidth()
554   {
555     if (!initialized)
556     {
557       initialize();
558     }
559
560     return width;
561   }
562
563   /**
564    * Accessor for the width
565    *
566    * @param w the number of columns to span
567    */

568   public void setWidth(double w)
569   {
570     if (origin == Origin.READ)
571     {
572       if (!initialized)
573       {
574         initialize();
575       }
576       origin = Origin.READ_WRITE;
577     }
578
579     width = w;
580   }
581
582   /**
583    * Accessor for the height of this drawing
584    *
585    * @return the number of rows spanned by this image
586    */

587   public double getHeight()
588   {
589     if (!initialized)
590     {
591       initialize();
592     }
593
594     return height;
595   }
596
597   /**
598    * Accessor for the height of this drawing
599    *
600    * @param h the number of rows spanned by this image
601    */

602   public void setHeight(double h)
603   {
604     if (origin == Origin.READ)
605     {
606       if (!initialized)
607       {
608         initialize();
609       }
610       origin = Origin.READ_WRITE;
611     }
612
613     height = h;
614   }
615
616   
617   /**
618    * Gets the SpContainer that was read in
619    *
620    * @return the read sp container
621    */

622   private EscherContainer getReadSpContainer()
623   {
624     if (!initialized)
625     {
626       initialize();
627     }
628
629     return readSpContainer;
630   }
631
632   /**
633    * Accessor for the image data
634    *
635    * @return the image data
636    */

637   public byte[] getImageData()
638   {
639     Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
640
641     if (!initialized)
642     {
643       initialize();
644     }
645     
646     return drawingGroup.getImageData(blipId);
647   }
648
649   /**
650    * Accessor for the type
651    *
652    * @return the type
653    */

654   public ShapeType getType()
655   {
656     return type;
657   }
658
659   /**
660    * Sets the text object
661    */

662   public void setTextObject(TextObjectRecord t)
663   {
664     txo = t;
665   }
666
667   /**
668    * Sets the note object
669    */

670   public void setNote(NoteRecord t)
671   {
672     note = t;
673   }
674
675   /**
676    * Sets the text data
677    */

678   public void setText(ContinueRecord t)
679   {
680     text = t;
681   }
682
683   /**
684    * Sets the formatting
685    */

686   public void setFormatting(ContinueRecord t)
687   {
688     formatting = t;
689   }
690
691   /**
692    * Accessor for the image data
693    *
694    * @return the image data
695    */

696   public byte[] getImageBytes()
697   {
698     Assert.verify(false);
699     return null;
700   }
701
702   /**
703    * Accessor for the image file path. Normally this is the absolute path
704    * of a file on the directory system, but if this drawing was constructed
705    * using an byte[] then the blip id is returned
706    *
707    * @return the image file path, or the blip id
708    */

709   public String JavaDoc getImageFilePath()
710   {
711     Assert.verify(false);
712     return null;
713   }
714
715   public void addMso(MsoDrawingRecord d)
716   {
717     mso = d;
718     drawingData.addRawData(mso.getData());
719   }
720
721   public void writeAdditionalRecords(File outputFile) throws IOException JavaDoc
722   {
723     if (origin == Origin.READ)
724     {
725       outputFile.write(objRecord);
726
727       if (mso != null)
728       {
729         outputFile.write(mso);
730       }
731       outputFile.write(txo);
732       outputFile.write(text);
733       if (formatting != null)
734       {
735         outputFile.write(formatting);
736       }
737       return;
738     }
739
740     // Create the obj record
741
ObjRecord objRecord = new ObjRecord(objectId,
742                                         ObjRecord.EXCELNOTE);
743     
744     outputFile.write(objRecord);
745
746     // Create the mso data record. Write the text box record again,
747
// although it is already included in the SpContainer
748
ClientTextBox textBox = new ClientTextBox();
749     MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData());
750     outputFile.write(msod);
751
752     TextObjectRecord txo = new TextObjectRecord(getText());
753     outputFile.write(txo);
754
755     // Data for the first continue record
756
byte[] textData = new byte[commentText.length() * 2 + 1];
757     textData[0] = 0x1; // unicode indicator
758
StringHelper.getUnicodeBytes(commentText, textData, 1);
759     //StringHelper.getBytes(commentText, textData, 1);
760
ContinueRecord textContinue = new ContinueRecord(textData);
761     outputFile.write(textContinue);
762
763     // Data for the formatting runs
764

765     byte[] frData = new byte[16];
766
767     // First txo run (the user)
768
IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character
769
IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default)
770
// Mandatory last txo run
771
IntegerHelper.getTwoBytes(commentText.length(), frData, 8);
772     IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default)
773

774     ContinueRecord frContinue = new ContinueRecord(frData);
775     outputFile.write(frContinue);
776   }
777
778   /**
779    * Writes any records that need to be written after all the drawing group
780    * objects have been written
781    * Writes out all the note records
782    */

783   public void writeTailRecords(File outputFile) throws IOException JavaDoc
784   {
785     if (origin == Origin.READ)
786     {
787       outputFile.write(note);
788       return;
789     }
790
791     // The note record
792
NoteRecord noteRecord = new NoteRecord(column, row, objectId);
793     outputFile.write(noteRecord);
794   }
795
796   /**
797    * Accessor for the row
798    */

799   public int getRow()
800   {
801     return note.getRow();
802   }
803
804   /**
805    * Accessor for the column
806    */

807   public int getColumn()
808   {
809     return note.getColumn();
810   }
811
812   /**
813    * Accessor for the comment text
814    */

815   public String JavaDoc getText()
816   {
817     if (commentText == null)
818     {
819       Assert.verify(text != null);
820
821       byte[] td = text.getData();
822       if (td[0] == 0)
823       {
824         commentText = StringHelper.getString
825           (td, td.length-1, 1, workbookSettings);
826       }
827       else
828       {
829         commentText = StringHelper.getUnicodeString
830           (td, (td.length - 1)/2, 1);
831       }
832     }
833
834     return commentText;
835   }
836
837   /**
838    * Hashing algorithm
839    */

840   public int hashCode()
841   {
842     return commentText.hashCode();
843   }
844
845   /**
846    * Called when the comment text is changed during the sheet copy process
847    *
848    * @param t the new text
849    */

850   public void setCommentText(String JavaDoc t)
851   {
852     commentText = t;
853     
854     if (origin == Origin.READ)
855     {
856       origin = Origin.READ_WRITE;
857     }
858   }
859
860   /**
861    * Accessor for the first drawing on the sheet. This is used when
862    * copying unmodified sheets to indicate that this drawing contains
863    * the first time Escher gubbins
864    *
865    * @return TRUE if this MSORecord is the first drawing on the sheet
866    */

867   public boolean isFirst()
868   {
869     return msoDrawingRecord.isFirst();
870   }
871
872   /**
873    * Queries whether this object is a form object. Form objects have their
874    * drawings records spread over several records and require special handling
875    *
876    * @return TRUE if this is a form object, FALSE otherwise
877    */

878   public boolean isFormObject()
879   {
880     return true;
881   }
882 }
883
884
885
886
Popular Tags