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: package org.apache.poi.hslf.model;
018:
019: import org.apache.poi.ddf.*;
020: import org.apache.poi.util.LittleEndian;
021:
022: import java.util.ArrayList;
023: import java.util.List;
024: import java.util.Iterator;
025: import java.awt.*;
026:
027: /**
028: * Represents a table in a PowerPoint presentation
029: *
030: * @author Yegor Kozlov
031: */
032: public class Table extends ShapeGroup {
033:
034: protected static final int BORDER_TOP = 1;
035: protected static final int BORDER_RIGHT = 2;
036: protected static final int BORDER_BOTTOM = 3;
037: protected static final int BORDER_LEFT = 4;
038:
039: protected static final int BORDERS_ALL = 5;
040: protected static final int BORDERS_OUTSIDE = 6;
041: protected static final int BORDERS_INSIDE = 7;
042: protected static final int BORDERS_NONE = 8;
043:
044: protected TableCell[][] cells;
045:
046: /**
047: * Create a new Table of the given number of rows and columns
048: *
049: * @param numrows the number of rows
050: * @param numcols the number of columns
051: */
052: public Table(int numrows, int numcols) {
053: super ();
054:
055: int x = 0, y = 0, tblWidth = 0, tblHeight = 0;
056: cells = new TableCell[numrows][numcols];
057: for (int i = 0; i < cells.length; i++) {
058: x = 0;
059: for (int j = 0; j < cells[i].length; j++) {
060: cells[i][j] = new TableCell(this );
061: Rectangle anchor = new Rectangle(x, y,
062: TableCell.DEFAULT_WIDTH,
063: TableCell.DEFAULT_HEIGHT);
064: cells[i][j].setAnchor(anchor);
065: x += TableCell.DEFAULT_WIDTH;
066: }
067: y += TableCell.DEFAULT_HEIGHT;
068: }
069: tblWidth = x;
070: tblHeight = y;
071: setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
072:
073: EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer()
074: .getChild(0);
075: List lst = spCont.getChildRecords();
076: EscherOptRecord opt = new EscherOptRecord();
077: opt.setRecordId((short) 0xF122);
078: opt
079: .addEscherProperty(new EscherSimpleProperty(
080: (short) 0x39F, 1));
081: EscherArrayProperty p = new EscherArrayProperty((short) 0x43A0,
082: false, null);
083: p.setSizeOfElements(0x0004);
084: p.setNumberOfElementsInArray(numrows);
085: p.setNumberOfElementsInMemory(numrows);
086: opt.addEscherProperty(p);
087: lst.add(lst.size() - 1, opt);
088:
089: }
090:
091: /**
092: * Create a Table object and initilize it from the supplied Record container.
093: *
094: * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
095: * @param parent the parent of the shape
096: */
097: protected Table(EscherContainerRecord escherRecord, Shape parent) {
098: super (escherRecord, parent);
099: }
100:
101: /**
102: * Gets a cell
103: *
104: * @param row the row index (0-based)
105: * @param col the column index (0-based)
106: * @return the cell
107: */
108: public TableCell getCell(int row, int col) {
109: return cells[row][col];
110: }
111:
112: public int getNumberOfColumns() {
113: return cells[0].length;
114: }
115:
116: public int getNumberOfRows() {
117: return cells.length;
118: }
119:
120: protected void afterInsert(Sheet sh) {
121: EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer()
122: .getChild(0);
123: List lst = spCont.getChildRecords();
124: EscherOptRecord opt = (EscherOptRecord) lst.get(lst.size() - 2);
125: EscherArrayProperty p = (EscherArrayProperty) opt
126: .getEscherProperty(1);
127: for (int i = 0; i < cells.length; i++) {
128: TableCell cell = cells[i][0];
129: int rowHeight = cell.getAnchor().height * MASTER_DPI
130: / POINT_DPI;
131: byte[] val = new byte[4];
132: LittleEndian.putInt(val, rowHeight);
133: p.setElement(i, val);
134: for (int j = 0; j < cells[i].length; j++) {
135: TableCell c = cells[i][j];
136: addShape(c);
137:
138: Line bt = c.getBorderTop();
139: if (bt != null)
140: addShape(bt);
141:
142: Line br = c.getBorderRight();
143: if (br != null)
144: addShape(br);
145:
146: Line bb = c.getBorderBottom();
147: if (bb != null)
148: addShape(bb);
149:
150: Line bl = c.getBorderLeft();
151: if (bl != null)
152: addShape(bl);
153:
154: }
155: }
156:
157: }
158:
159: /**
160: * Sets the row height.
161: *
162: * @param row the row index (0-based)
163: * @param height the height to set (in pixels)
164: */
165: public void setRowHeight(int row, int height) {
166: int currentHeight = cells[row][0].getAnchor().height;
167: int dy = height - currentHeight;
168:
169: for (int i = row; i < cells.length; i++) {
170: for (int j = 0; j < cells[i].length; j++) {
171: Rectangle anchor = cells[i][j].getAnchor();
172: if (i == row)
173: anchor.height = height;
174: else
175: anchor.y += dy;
176: cells[i][j].setAnchor(anchor);
177: }
178: }
179: Rectangle tblanchor = getAnchor();
180: tblanchor.height += dy;
181: setAnchor(tblanchor);
182:
183: }
184:
185: /**
186: * Sets the column width.
187: *
188: * @param col the column index (0-based)
189: * @param width the width to set (in pixels)
190: */
191: public void setColumnWidth(int col, int width) {
192: int currentWidth = cells[0][col].getAnchor().width;
193: int dx = width - currentWidth;
194: for (int i = 0; i < cells.length; i++) {
195: Rectangle anchor = cells[i][col].getAnchor();
196: anchor.width = width;
197: cells[i][col].setAnchor(anchor);
198:
199: if (col < cells[i].length - 1)
200: for (int j = col + 1; j < cells[i].length; j++) {
201: anchor = cells[i][j].getAnchor();
202: anchor.x += dx;
203: cells[i][j].setAnchor(anchor);
204: }
205: }
206: Rectangle tblanchor = getAnchor();
207: tblanchor.width += dx;
208: setAnchor(tblanchor);
209: }
210:
211: /**
212: * Format the table and apply the specified Line to all cell boundaries,
213: * both outside and inside
214: *
215: * @param line the border line
216: */
217: public void setAllBorders(Line line) {
218: for (int i = 0; i < cells.length; i++) {
219: for (int j = 0; j < cells[i].length; j++) {
220: TableCell cell = cells[i][j];
221: cell.setBorderTop(cloneBorder(line));
222: cell.setBorderLeft(cloneBorder(line));
223: if (j == cells[i].length - 1)
224: cell.setBorderRight(cloneBorder(line));
225: if (i == cells.length - 1)
226: cell.setBorderBottom(cloneBorder(line));
227: }
228: }
229: }
230:
231: /**
232: * Format the outside border using the specified Line object
233: *
234: * @param line the border line
235: */
236: public void setOutsideBorders(Line line) {
237: for (int i = 0; i < cells.length; i++) {
238: for (int j = 0; j < cells[i].length; j++) {
239: TableCell cell = cells[i][j];
240:
241: if (j == 0)
242: cell.setBorderLeft(cloneBorder(line));
243: if (j == cells[i].length - 1)
244: cell.setBorderRight(cloneBorder(line));
245: else {
246: cell.setBorderLeft(null);
247: cell.setBorderLeft(null);
248: }
249:
250: if (i == 0)
251: cell.setBorderTop(cloneBorder(line));
252: else if (i == cells.length - 1)
253: cell.setBorderBottom(cloneBorder(line));
254: else {
255: cell.setBorderTop(null);
256: cell.setBorderBottom(null);
257: }
258: }
259: }
260: }
261:
262: /**
263: * Format the inside border using the specified Line object
264: *
265: * @param line the border line
266: */
267: public void setInsideBorders(Line line) {
268: for (int i = 0; i < cells.length; i++) {
269: for (int j = 0; j < cells[i].length; j++) {
270: TableCell cell = cells[i][j];
271:
272: if (j != cells[i].length - 1)
273: cell.setBorderRight(cloneBorder(line));
274: else {
275: cell.setBorderLeft(null);
276: cell.setBorderLeft(null);
277: }
278: if (i != cells.length - 1)
279: cell.setBorderBottom(cloneBorder(line));
280: else {
281: cell.setBorderTop(null);
282: cell.setBorderBottom(null);
283: }
284: }
285: }
286: }
287:
288: private Line cloneBorder(Line line) {
289: Line border = createBorder();
290: border.setLineWidth(line.getLineWidth());
291: border.setLineStyle(line.getLineStyle());
292: border.setLineDashing(line.getLineDashing());
293: border.setLineColor(line.getLineColor());
294: return border;
295: }
296:
297: /**
298: * Create a border to format this table
299: *
300: * @return the created border
301: */
302: public Line createBorder() {
303: Line line = new Line(this );
304:
305: EscherOptRecord opt = (EscherOptRecord) getEscherChild(line
306: .getSpContainer(), EscherOptRecord.RECORD_ID);
307: setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
308: setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
309: setEscherProperty(opt,
310: EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
311: setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE,
312: 0x80000);
313:
314: return line;
315: }
316: }
|