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.hslf.record;
019:
020: import org.apache.poi.util.ArrayUtil;
021: import org.apache.poi.util.LittleEndian;
022:
023: import java.io.IOException;
024: import java.io.OutputStream;
025: import java.util.Vector;
026:
027: /**
028: * These are tricky beasts. They contain the text of potentially
029: * many (normal) slides. They are made up of several sets of
030: * - SlidePersistAtom
031: * - TextHeaderAtom
032: * - TextBytesAtom / TextCharsAtom
033: * - StyleTextPropAtom (optional)
034: * - TextSpecInfoAtom (optional)
035: * - InteractiveInfo (optional)
036: * - TxInteractiveInfoAtom (optional)
037: * and then the next SlidePersistAtom.
038: *
039: * Eventually, Slides will find the blocks that interest them from all
040: * the SlideListWithText entries, and refere to them
041: *
042: * For now, we scan through looking for interesting bits, then creating
043: * the helpful Sheet from model for them
044: *
045: * @author Nick Burch
046: */
047:
048: // For now, pretend to be an atom
049: public class SlideListWithText extends RecordContainer {
050: private byte[] _header;
051: private static long _type = 4080;
052:
053: private SlideAtomsSet[] slideAtomsSets;
054:
055: /**
056: * Create a new holder for slide records
057: */
058: protected SlideListWithText(byte[] source, int start, int len) {
059: // Grab the header
060: _header = new byte[8];
061: System.arraycopy(source, start, _header, 0, 8);
062:
063: // Find our children
064: _children = Record.findChildRecords(source, start + 8, len - 8);
065:
066: // Group our children together into SlideAtomsSets
067: // That way, model layer code can just grab the sets to use,
068: // without having to try to match the children together
069: Vector sets = new Vector();
070: for (int i = 0; i < _children.length; i++) {
071: if (_children[i] instanceof SlidePersistAtom) {
072: // Find where the next SlidePersistAtom is
073: int endPos = i + 1;
074: while (endPos < _children.length
075: && !(_children[endPos] instanceof SlidePersistAtom)) {
076: endPos += 1;
077: }
078:
079: int clen = endPos - i - 1;
080: boolean emptySet = false;
081: if (clen == 0) {
082: emptySet = true;
083: }
084:
085: // Create a SlideAtomsSets, not caring if they're empty
086: //if(emptySet) { continue; }
087: Record[] spaChildren = new Record[clen];
088: System
089: .arraycopy(_children, i + 1, spaChildren, 0,
090: clen);
091: SlideAtomsSet set = new SlideAtomsSet(
092: (SlidePersistAtom) _children[i], spaChildren);
093: sets.add(set);
094:
095: // Wind on
096: i += clen;
097: }
098: }
099:
100: // Turn the vector into an array
101: slideAtomsSets = new SlideAtomsSet[sets.size()];
102: for (int i = 0; i < slideAtomsSets.length; i++) {
103: slideAtomsSets[i] = (SlideAtomsSet) sets.get(i);
104: }
105: }
106:
107: /**
108: * Create a new, empty, SlideListWithText
109: */
110: public SlideListWithText() {
111: _header = new byte[8];
112: LittleEndian.putUShort(_header, 0, 15);
113: LittleEndian.putUShort(_header, 2, (int) _type);
114: LittleEndian.putInt(_header, 4, 0);
115:
116: // We have no children to start with
117: _children = new Record[0];
118: slideAtomsSets = new SlideAtomsSet[0];
119: }
120:
121: /**
122: * Add a new SlidePersistAtom, to the end of the current list,
123: * and update the internal list of SlidePersistAtoms
124: * @param spa
125: */
126: public void addSlidePersistAtom(SlidePersistAtom spa) {
127: // Add the new SlidePersistAtom at the end
128: appendChildRecord(spa);
129:
130: SlideAtomsSet newSAS = new SlideAtomsSet(spa, new Record[0]);
131:
132: // Update our SlideAtomsSets with this
133: SlideAtomsSet[] sas = new SlideAtomsSet[slideAtomsSets.length + 1];
134: System.arraycopy(slideAtomsSets, 0, sas, 0,
135: slideAtomsSets.length);
136: sas[sas.length - 1] = newSAS;
137: slideAtomsSets = sas;
138: }
139:
140: /**
141: * Get access to the SlideAtomsSets of the children of this record
142: */
143: public SlideAtomsSet[] getSlideAtomsSets() {
144: return slideAtomsSets;
145: }
146:
147: /**
148: * Return the value we were given at creation
149: */
150: public long getRecordType() {
151: return _type;
152: }
153:
154: /**
155: * Write the contents of the record back, so it can be written
156: * to disk
157: */
158: public void writeOut(OutputStream out) throws IOException {
159: writeOut(_header[0], _header[1], _type, _children, out);
160: }
161:
162: /**
163: * Shifts a SlideAtomsSet to a new position.
164: * Works by shifting the child records about, then updating
165: * the SlideAtomSets array
166: * @param toMove The SlideAtomsSet to move
167: * @param newPosition The new (0 based) position for the SlideAtomsSet
168: */
169: public void repositionSlideAtomsSet(SlideAtomsSet toMove,
170: int newPosition) {
171: // Ensure it's one of ours
172: int curPos = -1;
173: for (int i = 0; i < slideAtomsSets.length; i++) {
174: if (slideAtomsSets[i] == toMove) {
175: curPos = i;
176: }
177: }
178: if (curPos == -1) {
179: throw new IllegalArgumentException(
180: "The supplied SlideAtomsSet didn't belong to this SlideListWithText");
181: }
182:
183: // Ensure the newPosision is valid
184: if (newPosition < 0 || newPosition >= slideAtomsSets.length) {
185: throw new IllegalArgumentException(
186: "The new position must be between 0, and the number of SlideAtomsSets");
187: }
188:
189: // Build the new records list
190: moveChildrenBefore(toMove.getSlidePersistAtom(),
191: toMove.slideRecords.length, slideAtomsSets[newPosition]
192: .getSlidePersistAtom());
193:
194: // Build the new SlideAtomsSets list
195: ArrayUtil.arrayMoveWithin(slideAtomsSets, curPos, newPosition,
196: 1);
197: }
198:
199: /**
200: * Inner class to wrap up a matching set of records that hold the
201: * text for a given sheet. Contains the leading SlidePersistAtom,
202: * and all of the records until the next SlidePersistAtom. This
203: * includes sets of TextHeaderAtom and TextBytesAtom/TextCharsAtom,
204: * along with some others.
205: */
206: public class SlideAtomsSet {
207: private SlidePersistAtom slidePersistAtom;
208: private Record[] slideRecords;
209:
210: /** Get the SlidePersistAtom, which gives details on the Slide this text is associated with */
211: public SlidePersistAtom getSlidePersistAtom() {
212: return slidePersistAtom;
213: }
214:
215: /** Get the Text related records for this slide */
216: public Record[] getSlideRecords() {
217: return slideRecords;
218: }
219:
220: /** Create one to hold the Records for one Slide's text */
221: public SlideAtomsSet(SlidePersistAtom s, Record[] r) {
222: slidePersistAtom = s;
223: slideRecords = r;
224: }
225: }
226: }
|