KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*********************************************************************
2 *
3 * Copyright (C) 2004 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.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.io.IOException JavaDoc;
25
26 import common.Logger;
27
28 import jxl.WorkbookSettings;
29 import jxl.biff.IntegerHelper;
30 import jxl.write.biff.File;
31
32 /**
33  * Handles the writing out of the different charts and images on a sheet.
34  * Called by the SheetWriter object
35  */

36 public class SheetDrawingWriter
37 {
38   /**
39    * The logger
40    */

41   private static Logger logger = Logger.getLogger(SheetDrawingWriter.class);
42
43   /**
44    * The drawings on the sheet
45    */

46   private ArrayList JavaDoc drawings;
47   
48   /**
49    * Flag indicating whether the drawings on the sheet were modified
50    */

51   private boolean drawingsModified;
52
53   /**
54    * The charts on the sheet
55    */

56   private Chart[] charts;
57
58   /**
59    * The workbook settings
60    */

61   private WorkbookSettings workbookSettings;
62
63   /**
64    * Constructor
65    *
66    * @param ws the workbook settings
67    */

68   public SheetDrawingWriter(WorkbookSettings ws)
69   {
70     charts = new Chart[0];
71   }
72
73   /**
74    * The drawings on the sheet
75    *
76    * @param dr the list of drawings
77    * @param mod flag indicating whether the drawings have been tampered with
78    */

79   public void setDrawings(ArrayList JavaDoc dr, boolean mod)
80   {
81     drawings = dr;
82     drawingsModified = mod;
83   }
84
85   /**
86    * Writes out the MsoDrawing records and Obj records for each image
87    * and chart on the sheet
88    *
89    * @param outputFile
90    * @exception IOException
91    */

92   public void write(File outputFile) throws IOException JavaDoc
93   {
94     // If there are no drawings or charts on this sheet then exit
95
if (drawings.size() == 0 && charts.length == 0)
96     {
97       return;
98     }
99
100     // See if any drawing has been modified
101
boolean modified = drawingsModified;
102     int numImages = drawings.size();
103
104     // See if any of the drawings has been genuinely modified
105
for (Iterator JavaDoc i = drawings.iterator() ; i.hasNext() && !modified ;)
106     {
107       DrawingGroupObject d = (DrawingGroupObject) i.next();
108       if (d.getOrigin() != Origin.READ)
109       {
110         modified = true;
111       }
112     }
113
114     // If the drawing order has been muddled at all, then we'll need
115
// to regenerate the Escher drawing data
116
if (numImages > 0 && !modified)
117     {
118       DrawingGroupObject d2 = (DrawingGroupObject) drawings.get(0);
119       if (!d2.isFirst())
120       {
121         modified = true;
122       }
123     }
124
125     // Check to see if this sheet consists of just a single chart. If so
126
// there is no MsoDrawingRecord, so write out the data and exit
127
if (numImages == 0 &&
128         charts.length == 1 &&
129         charts[0].getMsoDrawingRecord() == null)
130     {
131       modified = false; // this sheet has not been modified
132
}
133
134     // If no drawing has been modified, then simply write them straight out
135
// again and exit
136
if (!modified)
137     {
138       writeUnmodified(outputFile);
139       return;
140     }
141
142     Object JavaDoc[] spContainerData = new Object JavaDoc[numImages + charts.length];
143     int length = 0;
144     EscherContainer firstSpContainer = null;
145
146     // Get all the spContainer byte data from the drawings
147
// and store in an array
148
for (int i = 0 ; i < numImages; i++)
149     {
150       DrawingGroupObject drawing = (DrawingGroupObject) drawings.get(i);
151
152       EscherContainer spc = drawing.getSpContainer();
153       byte[] data = spc.getData();
154       spContainerData[i] = data;
155
156       if (i == 0)
157       {
158         firstSpContainer = spc;
159       }
160       else
161       {
162         length += data.length;
163       }
164     }
165
166     // Get all the spContainer byte from the charts and add to the array
167
for (int i = 0 ; i < charts.length ; i++)
168     {
169       EscherContainer spContainer= charts[i].getSpContainer();
170       byte[] data = spContainer.getBytes();
171       data = spContainer.setHeaderData(data);
172       spContainerData[i + numImages] = data;
173       
174       if (i == 0 && numImages == 0)
175       {
176         firstSpContainer = spContainer;
177       }
178       else
179       {
180         length += data.length;
181       }
182     }
183
184     // Put the generalised stuff around the first item
185
DgContainer dgContainer = new DgContainer();
186     Dg dg = new Dg(numImages + charts.length);
187     dgContainer.add(dg);
188     
189     SpgrContainer spgrContainer = new SpgrContainer();
190     
191     SpContainer spContainer = new SpContainer();
192     Spgr spgr = new Spgr();
193     spContainer.add(spgr);
194     Sp sp = new Sp(ShapeType.MIN, 1024, 5);
195     spContainer.add(sp);
196     spgrContainer.add(spContainer);
197     
198     spgrContainer.add(firstSpContainer);
199     
200     dgContainer.add(spgrContainer);
201
202     byte[] firstMsoData = dgContainer.getData();
203
204     // Adjust the length of the DgContainer
205
int len = IntegerHelper.getInt(firstMsoData[4],
206                                    firstMsoData[5],
207                                    firstMsoData[6],
208                                    firstMsoData[7]);
209     IntegerHelper.getFourBytes(len+length, firstMsoData, 4);
210
211     // Adjust the length of the SpgrContainer
212
len = IntegerHelper.getInt(firstMsoData[28],
213                                firstMsoData[29],
214                                firstMsoData[30],
215                                firstMsoData[31]);
216     IntegerHelper.getFourBytes(len+length, firstMsoData, 28);
217
218     // Now write out each MsoDrawing record
219

220     // First MsoRecord
221
// test hack for form objects, to remove the ClientTextBox record
222
// from the end of the SpContainer
223
if ( numImages > 0 &&
224          ((DrawingGroupObject)drawings.get(0)).isFormObject())
225     {
226       byte[] msodata2 = new byte[firstMsoData.length - 8];
227       System.arraycopy(firstMsoData, 0, msodata2, 0, msodata2.length);
228       firstMsoData = msodata2;
229     }
230   
231     MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
232     outputFile.write(msoDrawingRecord);
233     
234     if (numImages > 0)
235     {
236       DrawingGroupObject firstDrawing = (DrawingGroupObject) drawings.get(0);
237       firstDrawing.writeAdditionalRecords(outputFile);
238     }
239     else
240     {
241       // first image is a chart
242
Chart chart = charts[0];
243       ObjRecord objRecord = chart.getObjRecord();
244       outputFile.write(objRecord);
245       outputFile.write(chart);
246     }
247
248     // Now do all the others
249
for (int i = 1 ; i < spContainerData.length ; i++)
250     {
251       byte[] bytes = (byte[]) spContainerData[i];
252
253       // test hack for form objects, to remove the ClientTextBox record
254
// from the end of the SpContainer
255
if (i < numImages &&
256           ((DrawingGroupObject) drawings.get(i)).isFormObject())
257       {
258         byte[] bytes2 = new byte[bytes.length - 8];
259         System.arraycopy(bytes, 0, bytes2, 0, bytes2.length);
260         bytes = bytes2;
261       }
262
263       msoDrawingRecord = new MsoDrawingRecord(bytes);
264       outputFile.write(msoDrawingRecord);
265
266       if (i < numImages)
267       {
268         // Write anything else the object needs
269
DrawingGroupObject d = (DrawingGroupObject) drawings.get(i);
270         d.writeAdditionalRecords(outputFile);
271       }
272       else
273       {
274         Chart chart = charts[i - numImages];
275         ObjRecord objRecord = chart.getObjRecord();
276         outputFile.write(objRecord);
277         outputFile.write(chart);
278       }
279     }
280
281     // Write any tail records that need to be written
282
for (Iterator JavaDoc i = drawings.iterator(); i.hasNext(); )
283     {
284       DrawingGroupObject dgo2 = (DrawingGroupObject) i.next();
285       dgo2.writeTailRecords(outputFile);
286     }
287   }
288
289   /**
290    * Writes out the drawings and the charts if nothing has been modified
291    *
292    * @param outputFile
293    * @exception IOException
294    */

295   private void writeUnmodified(File outputFile) throws IOException JavaDoc
296   {
297     if (charts.length == 0 && drawings.size() == 0)
298     {
299       // No drawings or charts
300
return;
301     }
302     else if (charts.length == 0 && drawings.size() != 0)
303     {
304       // If there are no charts, then write out the drawings and return
305
for (Iterator JavaDoc i = drawings.iterator() ; i.hasNext() ; )
306       {
307         DrawingGroupObject d = (DrawingGroupObject) i.next();
308         outputFile.write(d.getMsoDrawingRecord());
309         d.writeAdditionalRecords(outputFile);
310       }
311
312       for (Iterator JavaDoc i = drawings.iterator() ; i.hasNext() ; )
313       {
314         DrawingGroupObject d = (DrawingGroupObject) i.next();
315         d.writeTailRecords(outputFile);
316       }
317       return;
318     }
319     else if (drawings.size() == 0 && charts.length != 0)
320     {
321       // If there are no drawings, then write out the charts and return
322
Chart curChart = null;
323       for (int i = 0 ; i < charts.length ; i++)
324       {
325         curChart = charts[i];
326         if (curChart.getMsoDrawingRecord() != null)
327         {
328           outputFile.write(curChart.getMsoDrawingRecord());
329         }
330
331         if (curChart.getObjRecord() != null)
332         {
333           outputFile.write(curChart.getObjRecord());
334         }
335
336         outputFile.write(curChart);
337       }
338
339       return;
340     }
341
342     // There are both charts and drawings - the output
343
// drawing group records will need
344
// to be re-jigged in order to write the drawings out first, then the
345
// charts
346
int numDrawings = drawings.size();
347     int length = 0;
348     EscherContainer[] spContainers =
349       new EscherContainer[numDrawings + charts.length];
350     boolean[] isFormObject = new boolean[numDrawings + charts.length];
351     
352     for (int i = 0 ; i < numDrawings; i++)
353     {
354       DrawingGroupObject d = (DrawingGroupObject) drawings.get(i);
355       spContainers[i] = d.getSpContainer();
356
357       if (i > 0)
358       {
359         length += spContainers[i].getLength();
360       }
361
362       if (d.isFormObject())
363       {
364         isFormObject[i] = true;
365       }
366     }
367
368     for (int i = 0 ; i < charts.length ; i++)
369     {
370       spContainers[i+numDrawings] = charts[i].getSpContainer();
371       length += spContainers[i+numDrawings].getLength();
372     }
373
374     // Put the generalised stuff around the first item
375
DgContainer dgContainer = new DgContainer();
376     Dg dg = new Dg(numDrawings + charts.length);
377     dgContainer.add(dg);
378     
379     SpgrContainer spgrContainer = new SpgrContainer();
380     
381     SpContainer spContainer = new SpContainer();
382     Spgr spgr = new Spgr();
383     spContainer.add(spgr);
384     Sp sp = new Sp(ShapeType.MIN, 1024, 5);
385     spContainer.add(sp);
386     spgrContainer.add(spContainer);
387     
388     spgrContainer.add(spContainers[0]);
389     
390     dgContainer.add(spgrContainer);
391
392     byte[] firstMsoData = dgContainer.getData();
393
394     // Adjust the length of the DgContainer
395
int len = IntegerHelper.getInt(firstMsoData[4],
396                                    firstMsoData[5],
397                                    firstMsoData[6],
398                                    firstMsoData[7]);
399     IntegerHelper.getFourBytes(len+length, firstMsoData, 4);
400
401     // Adjust the length of the SpgrContainer
402
len = IntegerHelper.getInt(firstMsoData[28],
403                                firstMsoData[29],
404                                firstMsoData[30],
405                                firstMsoData[31]);
406     IntegerHelper.getFourBytes(len+length, firstMsoData, 28);
407
408     // Now write out each MsoDrawing record and object record
409

410     // Hack to remove the last eight bytes (text box escher record)
411
// from the container
412
if (isFormObject[0] == true)
413     {
414       byte[] cbytes = new byte[firstMsoData.length -8];
415       System.arraycopy(firstMsoData, 0, cbytes, 0, cbytes.length);
416       firstMsoData = cbytes;
417     }
418
419     // First MsoRecord
420
MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
421     outputFile.write(msoDrawingRecord);
422     
423     DrawingGroupObject dgo = (DrawingGroupObject) drawings.get(0);
424     dgo.writeAdditionalRecords(outputFile);
425
426     // Now do all the others
427
for (int i = 1 ; i < spContainers.length ; i++)
428     {
429       byte[] bytes = spContainers[i].getBytes();
430       
431
432       byte[] bytes2 = spContainers[i].setHeaderData(bytes);
433
434       // Hack to remove the last eight bytes (text box escher record)
435
// from the container
436
if (isFormObject[i] == true)
437       {
438         byte[] cbytes = new byte[bytes2.length - 8];
439         System.arraycopy(bytes2, 0, cbytes, 0, cbytes.length);
440         bytes2 = cbytes;
441       }
442
443       msoDrawingRecord = new MsoDrawingRecord(bytes2);
444       outputFile.write(msoDrawingRecord);
445
446       if (i < numDrawings)
447       {
448         dgo = (DrawingGroupObject) drawings.get(i);
449         dgo.writeAdditionalRecords(outputFile);
450       }
451       else
452       {
453         Chart chart = charts[i - numDrawings];
454         ObjRecord objRecord = chart.getObjRecord();
455         outputFile.write(objRecord);
456         outputFile.write(chart);
457       }
458     }
459
460     // Write any tail records that need to be written
461
for (Iterator JavaDoc i = drawings.iterator(); i.hasNext(); )
462     {
463       DrawingGroupObject dgo2 = (DrawingGroupObject) i.next();
464       dgo2.writeTailRecords(outputFile);
465     }
466   }
467
468   /**
469    * Sets the charts on the sheet
470    *
471    * @param ch the charts
472    */

473   public void setCharts(Chart[] ch)
474   {
475     charts = ch;
476   }
477
478   /**
479    * Accessor for the charts on the sheet
480    *
481    * @return the charts
482    */

483   public Chart[] getCharts()
484   {
485     return charts;
486   }
487 }
488
Popular Tags