001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.record;
019:
020: import java.util.ArrayList;
021: import java.util.Iterator;
022:
023: import org.apache.poi.util.LittleEndian;
024:
025: /**
026: * Title: Merged Cells Record
027: * <br>
028: * Description: Optional record defining a square area of cells to "merged" into
029: * one cell. <br>
030: * REFERENCE: NONE (UNDOCUMENTED PRESENTLY) <br>
031: * @author Andrew C. Oliver (acoliver at apache dot org)
032: * @version 2.0-pre
033: */
034: public class MergeCellsRecord extends Record {
035: public final static short sid = 0xe5;
036: private ArrayList field_2_regions;
037:
038: public MergeCellsRecord() {
039: }
040:
041: /**
042: * Constructs a MergedCellsRecord and sets its fields appropriately
043: * @param in the RecordInputstream to read the record from
044: */
045:
046: public MergeCellsRecord(RecordInputStream in) {
047: super (in);
048: }
049:
050: protected void fillFields(RecordInputStream in) {
051: short numAreas = in.readShort();
052: field_2_regions = new ArrayList(numAreas + 10);
053:
054: for (int k = 0; k < numAreas; k++) {
055: MergedRegion region = new MergedRegion(in.readShort(), in
056: .readShort(), in.readShort(), in.readShort());
057:
058: field_2_regions.add(region);
059: }
060: }
061:
062: /**
063: * get the number of merged areas. If this drops down to 0 you should just go
064: * ahead and delete the record.
065: * @return number of areas
066: */
067:
068: public short getNumAreas() {
069: //if the array size is larger than a short (65536), the record can't hold that many merges anyway
070: if (field_2_regions == null)
071: return 0;
072: return (short) field_2_regions.size();
073: }
074:
075: /**
076: * set the number of merged areas. You do not need to call this if you use addArea,
077: * it will be incremented automatically or decremented when an area is removed. If
078: * you are setting this to 0 then you are a terrible person. Just remove the record.
079: * (just kidding about you being a terrible person..hehe)
080: * @deprecated We now link the size to the actual array of merged regions
081: * @see #getNumAreas()
082: * @param numareas number of areas
083: */
084:
085: public void setNumAreas(short numareas) {
086:
087: }
088:
089: /**
090: * Add an area to consider a merged cell. The index returned is only gauranteed to
091: * be correct provided you do not add ahead of or remove ahead of it (in which case
092: * you should increment or decrement appropriately....in other words its an arrayList)
093: *
094: * @param rowfrom - the upper left hand corner's row
095: * @param colfrom - the upper left hand corner's col
096: * @param rowto - the lower right hand corner's row
097: * @param colto - the lower right hand corner's col
098: * @return new index of said area (don't depend on it if you add/remove)
099: */
100:
101: //public int addArea(short rowfrom, short colfrom, short rowto, short colto)
102: public int addArea(int rowfrom, short colfrom, int rowto,
103: short colto) {
104: if (field_2_regions == null) {
105: field_2_regions = new ArrayList(10);
106: }
107: MergedRegion region = new MergedRegion(rowfrom, rowto, colfrom,
108: colto);
109:
110: field_2_regions.add(region);
111: return field_2_regions.size() - 1;
112: }
113:
114: /**
115: * essentially unmerge the cells in the "area" stored at the passed in index
116: * @param area index
117: */
118:
119: public void removeAreaAt(int area) {
120: field_2_regions.remove(area);
121: }
122:
123: /**
124: * return the MergedRegion at the given index.
125: *
126: * @return MergedRegion representing the area that is Merged (r1,c1 - r2,c2)
127: */
128:
129: public MergedRegion getAreaAt(int index) {
130: return (MergedRegion) field_2_regions.get(index);
131: }
132:
133: public int getRecordSize() {
134: int retValue;
135:
136: retValue = 6 + (8 * field_2_regions.size());
137: return retValue;
138: }
139:
140: public short getSid() {
141: return sid;
142: }
143:
144: public int serialize(int offset, byte[] data) {
145: int recordsize = getRecordSize();
146: int pos = 6;
147:
148: LittleEndian.putShort(data, offset + 0, sid);
149: LittleEndian.putShort(data, offset + 2,
150: (short) (recordsize - 4));
151: LittleEndian.putShort(data, offset + 4, getNumAreas());
152: for (int k = 0; k < getNumAreas(); k++) {
153: MergedRegion region = getAreaAt(k);
154:
155: //LittleEndian.putShort(data, offset + pos, region.row_from);
156: LittleEndian.putShort(data, offset + pos,
157: (short) region.row_from);
158: pos += 2;
159: //LittleEndian.putShort(data, offset + pos, region.row_to);
160: LittleEndian.putShort(data, offset + pos,
161: (short) region.row_to);
162: pos += 2;
163: LittleEndian.putShort(data, offset + pos, region.col_from);
164: pos += 2;
165: LittleEndian.putShort(data, offset + pos, region.col_to);
166: pos += 2;
167: }
168: return recordsize;
169: }
170:
171: public String toString() {
172: StringBuffer retval = new StringBuffer();
173:
174: retval.append("[MERGEDCELLS]").append("\n");
175: retval.append(" .sid =").append(sid).append("\n");
176: retval.append(" .numregions =").append(getNumAreas())
177: .append("\n");
178: for (int k = 0; k < getNumAreas(); k++) {
179: MergedRegion region = (MergedRegion) field_2_regions.get(k);
180:
181: retval.append(" .rowfrom =").append(region.row_from)
182: .append("\n");
183: retval.append(" .colfrom =").append(region.col_from)
184: .append("\n");
185: retval.append(" .rowto =").append(region.row_to)
186: .append("\n");
187: retval.append(" .colto =").append(region.col_to)
188: .append("\n");
189: }
190: retval.append("[MERGEDCELLS]").append("\n");
191: return retval.toString();
192: }
193:
194: protected void validateSid(short id) {
195: if (id != sid) {
196: throw new RecordFormatException(
197: "NOT A MERGEDCELLS RECORD!! " + id);
198: }
199: }
200:
201: /**
202: * this is a low level representation of a MergedRegion of cells. It is an
203: * inner class because we do not want it used without reference to this class.
204: *
205: */
206:
207: public class MergedRegion {
208:
209: /**
210: * create a merged region all in one stroke.
211: */
212:
213: //public MergedRegion(short row_from, short row_to, short col_from,
214: public MergedRegion(int row_from, int row_to, short col_from,
215: short col_to) {
216: this .row_from = row_from;
217: this .row_to = row_to;
218: this .col_from = col_from;
219: this .col_to = col_to;
220: }
221:
222: /**
223: * upper lefthand corner row
224: */
225:
226: //public short row_from;
227: public int row_from;
228:
229: /**
230: * lower right hand corner row
231: */
232:
233: //public short row_to;
234: public int row_to;
235:
236: /**
237: * upper right hand corner col
238: */
239:
240: public short col_from;
241:
242: /**
243: * lower right hand corner col
244: */
245:
246: public short col_to;
247: }
248:
249: public Object clone() {
250: MergeCellsRecord rec = new MergeCellsRecord();
251: rec.field_2_regions = new ArrayList();
252: Iterator iterator = field_2_regions.iterator();
253: while (iterator.hasNext()) {
254: MergedRegion oldRegion = (MergedRegion) iterator.next();
255: rec.addArea(oldRegion.row_from, oldRegion.col_from,
256: oldRegion.row_to, oldRegion.col_to);
257: }
258:
259: return rec;
260: }
261: }
|