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.Collections;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.poi.util.LittleEndian;
028:
029: /**
030: * <p>Record that contains the functionality page breaks (horizontal and vertical)</p>
031: *
032: * <p>The other two classes just specifically set the SIDS for record creation.</p>
033: *
034: * <p>REFERENCE: Microsoft Excel SDK page 322 and 420</p>
035: *
036: * @see HorizontalPageBreakRecord
037: * @see VerticalPageBreakRecord
038: * @author Danny Mui (dmui at apache dot org)
039: */
040: public class PageBreakRecord extends Record {
041: public static final short HORIZONTAL_SID = (short) 0x1B;
042: public static final short VERTICAL_SID = (short) 0x1A;
043: public short sid;
044: private short numBreaks;
045: private List breaks;
046: private Map BreakMap;
047:
048: /**
049: * Since both records store 2byte integers (short), no point in
050: * differentiating it in the records.
051: * <p>
052: * The subs (rows or columns, don't seem to be able to set but excel sets
053: * them automatically)
054: */
055: public class Break {
056:
057: public short main;
058: public short subFrom;
059: public short subTo;
060:
061: public Break(short main, short subFrom, short subTo) {
062: this .main = main;
063: this .subFrom = subFrom;
064: this .subTo = subTo;
065: }
066: }
067:
068: public PageBreakRecord() {
069:
070: }
071:
072: /**
073: *
074: * @param sid
075: */
076: public PageBreakRecord(short sid) {
077: super ();
078: this .sid = sid;
079: }
080:
081: public PageBreakRecord(RecordInputStream in) {
082: super (in);
083: this .sid = in.getSid();
084: }
085:
086: protected void fillFields(RecordInputStream in) {
087: short loadedBreaks = in.readShort();
088: setNumBreaks(loadedBreaks);
089: for (int k = 0; k < loadedBreaks; k++) {
090: addBreak((short) (in.readShort() - 1), in.readShort(), in
091: .readShort());
092: }
093:
094: }
095:
096: public short getSid() {
097: return sid;
098: }
099:
100: public int serialize(int offset, byte data[]) {
101: int recordsize = getRecordSize();
102: int pos = 6;
103: LittleEndian.putShort(data, offset + 0, getSid());
104: LittleEndian.putShort(data, offset + 2,
105: (short) (recordsize - 4));
106: LittleEndian.putShort(data, offset + 4, getNumBreaks());
107: for (Iterator iterator = getBreaksIterator(); iterator
108: .hasNext();) {
109: Break Break = (Break) iterator.next();
110: LittleEndian.putShort(data, offset + pos,
111: (short) (Break.main + 1));
112: pos += 2;
113: LittleEndian.putShort(data, offset + pos, Break.subFrom);
114: pos += 2;
115: LittleEndian.putShort(data, offset + pos, Break.subTo);
116: pos += 2;
117: }
118:
119: return recordsize;
120: }
121:
122: protected void validateSid(short id) {
123: if (id != HORIZONTAL_SID && id != VERTICAL_SID)
124: throw new RecordFormatException(
125: "NOT A HorizontalPageBreak or VerticalPageBreak RECORD!! "
126: + id);
127: else
128: return;
129: }
130:
131: public short getNumBreaks() {
132: return breaks != null ? (short) breaks.size() : numBreaks;
133: }
134:
135: public void setNumBreaks(short numBreaks) {
136: this .numBreaks = numBreaks;
137: }
138:
139: public Iterator getBreaksIterator() {
140: if (breaks == null)
141: return Collections.EMPTY_LIST.iterator();
142: else
143: return breaks.iterator();
144: }
145:
146: public String toString() {
147: StringBuffer retval = new StringBuffer();
148:
149: if (getSid() != HORIZONTAL_SID && getSid() != VERTICAL_SID)
150: return "[INVALIDPAGEBREAK]\n .sid =" + getSid()
151: + "[INVALIDPAGEBREAK]";
152:
153: String label;
154: String mainLabel;
155: String subLabel;
156:
157: if (getSid() == HORIZONTAL_SID) {
158: label = "HORIZONTALPAGEBREAK";
159: mainLabel = "row";
160: subLabel = "col";
161: } else {
162: label = "VERTICALPAGEBREAK";
163: mainLabel = "column";
164: subLabel = "row";
165: }
166:
167: retval.append("[" + label + "]").append("\n");
168: retval.append(" .sid =").append(getSid()).append(
169: "\n");
170: retval.append(" .numbreaks =").append(getNumBreaks())
171: .append("\n");
172: Iterator iterator = getBreaksIterator();
173: for (int k = 0; k < getNumBreaks(); k++) {
174: Break region = (Break) iterator.next();
175:
176: retval.append(" .").append(mainLabel).append(
177: " (zero-based) =").append(region.main).append("\n");
178: retval.append(" .").append(subLabel)
179: .append("From =").append(region.subFrom).append(
180: "\n");
181: retval.append(" .").append(subLabel)
182: .append("To =").append(region.subTo).append(
183: "\n");
184: }
185:
186: retval.append("[" + label + "]").append("\n");
187: return retval.toString();
188: }
189:
190: /**
191: * Adds the page break at the specified parameters
192: * @param main Depending on sid, will determine row or column to put page break (zero-based)
193: * @param subFrom No user-interface to set (defaults to minumum, 0)
194: * @param subTo No user-interface to set
195: */
196: public void addBreak(short main, short subFrom, short subTo) {
197: if (breaks == null) {
198: breaks = new ArrayList(getNumBreaks() + 10);
199: BreakMap = new HashMap();
200: }
201: Integer key = new Integer(main);
202: Break region = (Break) BreakMap.get(key);
203: if (region != null) {
204: region.main = main;
205: region.subFrom = subFrom;
206: region.subTo = subTo;
207: } else {
208: region = new Break(main, subFrom, subTo);
209: breaks.add(region);
210: }
211: BreakMap.put(key, region);
212: }
213:
214: /**
215: * Removes the break indicated by the parameter
216: * @param main (zero-based)
217: */
218: public void removeBreak(short main) {
219: Integer rowKey = new Integer(main);
220: Break region = (Break) BreakMap.get(rowKey);
221: breaks.remove(region);
222: BreakMap.remove(rowKey);
223: }
224:
225: public int getRecordSize() {
226: return 6 + getNumBreaks() * 6;
227: }
228:
229: /**
230: * Retrieves the region at the row/column indicated
231: * @param main FIXME: Document this!
232: * @return The Break or null if no break exists at the row/col specified.
233: */
234: public Break getBreak(short main) {
235: if (BreakMap == null)
236: return null;
237: Integer rowKey = new Integer(main);
238: return (Break) BreakMap.get(rowKey);
239: }
240:
241: /* Clones the page break record
242: * @see java.lang.Object#clone()
243: */
244: public Object clone() {
245: PageBreakRecord record = new PageBreakRecord(getSid());
246: Iterator iterator = getBreaksIterator();
247: while (iterator.hasNext()) {
248: Break original = (Break) iterator.next();
249: record.addBreak(original.main, original.subFrom,
250: original.subTo);
251: }
252: return record;
253: }
254:
255: }
|