2004-04-09 09:05:39 -04:00
|
|
|
/* ====================================================================
|
2006-12-22 14:18:16 -05:00
|
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
|
|
this work for additional information regarding copyright ownership.
|
|
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
|
(the "License"); you may not use this file except in compliance with
|
|
|
|
the License. You may obtain a copy of the License at
|
2004-04-09 09:05:39 -04:00
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
==================================================================== */
|
2004-08-23 04:52:54 -04:00
|
|
|
|
2004-04-09 07:45:38 -04:00
|
|
|
package org.apache.poi.hssf.usermodel;
|
|
|
|
|
2012-06-08 13:47:37 -04:00
|
|
|
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
2012-06-18 16:59:32 -04:00
|
|
|
import org.apache.poi.ddf.EscherRecord;
|
2015-10-26 06:32:30 -04:00
|
|
|
import org.apache.poi.ss.SpreadsheetVersion;
|
2008-11-12 02:15:37 -05:00
|
|
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A client anchor is attached to an excel worksheet. It anchors against a
|
|
|
|
* top-left and buttom-right cell.
|
|
|
|
*/
|
2009-08-18 12:50:24 -04:00
|
|
|
public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2015-10-26 06:32:30 -04:00
|
|
|
public static final int MAX_COL = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
|
|
|
|
public static final int MAX_ROW = SpreadsheetVersion.EXCEL97.getLastRowIndex();
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
private EscherClientAnchorRecord _escherClientAnchor;
|
2012-06-08 13:47:37 -04:00
|
|
|
|
|
|
|
public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
|
2012-06-18 16:59:32 -04:00
|
|
|
this._escherClientAnchor = escherClientAnchorRecord;
|
2012-06-08 13:47:37 -04:00
|
|
|
}
|
|
|
|
|
2004-04-09 07:45:38 -04:00
|
|
|
/**
|
|
|
|
* Creates a new client anchor and defaults all the anchor positions to 0.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public HSSFClientAnchor() {
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new client anchor and sets the top-left and bottom-right
|
|
|
|
* coordinates of the anchor.
|
2014-08-31 07:40:22 -04:00
|
|
|
*
|
|
|
|
* Note: Microsoft Excel seems to sometimes disallow
|
|
|
|
* higher y1 than y2 or higher x1 than x2, you might need to
|
|
|
|
* reverse them and draw shapes vertically or horizontally flipped!
|
2004-04-09 07:45:38 -04:00
|
|
|
*
|
2012-06-18 16:59:32 -04:00
|
|
|
* @param dx1 the x coordinate within the first cell.
|
|
|
|
* @param dy1 the y coordinate within the first cell.
|
|
|
|
* @param dx2 the x coordinate within the second cell.
|
|
|
|
* @param dy2 the y coordinate within the second cell.
|
|
|
|
* @param col1 the column (0 based) of the first cell.
|
|
|
|
* @param row1 the row (0 based) of the first cell.
|
|
|
|
* @param col2 the column (0 based) of the second cell.
|
|
|
|
* @param row2 the row (0 based) of the second cell.
|
2004-04-09 07:45:38 -04:00
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {
|
|
|
|
super(dx1, dy1, dx2, dy2);
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
checkRange(dx1, 0, 1023, "dx1");
|
|
|
|
checkRange(dx2, 0, 1023, "dx2");
|
|
|
|
checkRange(dy1, 0, 255, "dy1");
|
|
|
|
checkRange(dy2, 0, 255, "dy2");
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(col1, 0, MAX_COL, "col1");
|
|
|
|
checkRange(col2, 0, MAX_COL, "col2");
|
|
|
|
checkRange(row1, 0, MAX_ROW, "row1");
|
|
|
|
checkRange(row2, 0, MAX_ROW, "row2");
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2012-07-11 08:08:38 -04:00
|
|
|
setCol1((short) Math.min(col1, col2));
|
|
|
|
setCol2((short) Math.max(col1, col2));
|
2015-10-26 06:32:30 -04:00
|
|
|
setRow1(Math.min(row1, row2));
|
|
|
|
setRow2(Math.max(row1, row2));
|
2012-07-11 08:08:38 -04:00
|
|
|
|
|
|
|
if (col1 > col2){
|
|
|
|
_isHorizontallyFlipped = true;
|
|
|
|
}
|
|
|
|
if (row1 > row2){
|
|
|
|
_isVerticallyFlipped = true;
|
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the height of a client anchor in points.
|
|
|
|
*
|
2012-06-18 16:59:32 -04:00
|
|
|
* @param sheet the sheet the anchor will be attached to
|
|
|
|
* @return the shape height.
|
2004-04-09 07:45:38 -04:00
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public float getAnchorHeightInPoints(HSSFSheet sheet) {
|
2007-12-24 04:48:11 -05:00
|
|
|
int y1 = getDy1();
|
|
|
|
int y2 = getDy2();
|
2012-06-18 16:59:32 -04:00
|
|
|
int row1 = Math.min(getRow1(), getRow2());
|
|
|
|
int row2 = Math.max(getRow1(), getRow2());
|
2004-04-09 07:45:38 -04:00
|
|
|
|
|
|
|
float points = 0;
|
2012-06-18 16:59:32 -04:00
|
|
|
if (row1 == row2) {
|
2004-04-09 07:45:38 -04:00
|
|
|
points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2);
|
2012-06-18 16:59:32 -04:00
|
|
|
} else {
|
2004-04-09 07:45:38 -04:00
|
|
|
points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1);
|
2012-06-18 16:59:32 -04:00
|
|
|
for (int i = row1 + 1; i < row2; i++) {
|
2004-04-09 07:45:38 -04:00
|
|
|
points += getRowHeightInPoints(sheet, i);
|
|
|
|
}
|
|
|
|
points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return points;
|
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) {
|
2004-04-09 07:45:38 -04:00
|
|
|
HSSFRow row = sheet.getRow(rowNum);
|
2009-08-18 12:50:24 -04:00
|
|
|
if (row == null) {
|
2004-04-09 07:45:38 -04:00
|
|
|
return sheet.getDefaultRowHeightInPoints();
|
2009-08-18 12:50:24 -04:00
|
|
|
}
|
|
|
|
return row.getHeightInPoints();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @return the column(0 based) of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public short getCol1() {
|
|
|
|
return _escherClientAnchor.getCol1();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @param col1 the column(0 based) of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setCol1(short col1) {
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(col1, 0, MAX_COL, "col1");
|
2012-06-18 16:59:32 -04:00
|
|
|
_escherClientAnchor.setCol1(col1);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
2012-06-18 16:59:32 -04:00
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @param col1 0-based column of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setCol1(int col1) {
|
|
|
|
setCol1((short) col1);
|
2008-11-12 02:15:37 -05:00
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @return the column(0 based) of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public short getCol2() {
|
|
|
|
return _escherClientAnchor.getCol2();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @param col2 the column(0 based) of the second cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setCol2(short col2) {
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(col2, 0, MAX_COL, "col2");
|
2012-06-18 16:59:32 -04:00
|
|
|
_escherClientAnchor.setCol2(col2);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @param col2 the column(0 based) of the second cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setCol2(int col2) {
|
|
|
|
setCol2((short) col2);
|
2008-11-12 02:15:37 -05:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @return the row(0 based) of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public int getRow1() {
|
2015-10-26 06:32:30 -04:00
|
|
|
return unsignedValue(_escherClientAnchor.getRow1());
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @param row1 0-based row of the first cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setRow1(int row1) {
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(row1, 0, MAX_ROW, "row1");
|
2012-06-18 16:59:32 -04:00
|
|
|
_escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue());
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
|
|
|
* @return the row(0 based) of the second cell.
|
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public int getRow2() {
|
2015-10-26 06:32:30 -04:00
|
|
|
return unsignedValue(_escherClientAnchor.getRow2());
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-08-06 17:06:12 -04:00
|
|
|
/**
|
2012-11-16 07:00:02 -05:00
|
|
|
* @param row2 the row(0 based) of the second cell.
|
2012-08-06 17:06:12 -04:00
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setRow2(int row2) {
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(row2, 0, MAX_ROW, "row2");
|
2012-06-18 16:59:32 -04:00
|
|
|
_escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-08-31 07:40:22 -04:00
|
|
|
* Sets the top-left and bottom-right coordinates of
|
|
|
|
* the anchor.
|
|
|
|
*
|
|
|
|
* Note: Microsoft Excel seems to sometimes disallow
|
|
|
|
* higher y1 than y2 or higher x1 than x2, you might need to
|
|
|
|
* reverse them and draw shapes vertically or horizontally flipped!
|
2004-04-09 07:45:38 -04:00
|
|
|
*
|
|
|
|
* @param x1 the x coordinate within the first cell.
|
|
|
|
* @param y1 the y coordinate within the first cell.
|
|
|
|
* @param x2 the x coordinate within the second cell.
|
|
|
|
* @param y2 the y coordinate within the second cell.
|
2012-06-18 16:59:32 -04:00
|
|
|
* @param col1 the column (0 based) of the first cell.
|
|
|
|
* @param row1 the row (0 based) of the first cell.
|
|
|
|
* @param col2 the column (0 based) of the second cell.
|
|
|
|
* @param row2 the row (0 based) of the second cell.
|
2004-04-09 07:45:38 -04:00
|
|
|
*/
|
2012-06-18 16:59:32 -04:00
|
|
|
public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) {
|
|
|
|
checkRange(getDx1(), 0, 1023, "dx1");
|
|
|
|
checkRange(getDx2(), 0, 1023, "dx2");
|
|
|
|
checkRange(getDy1(), 0, 255, "dy1");
|
|
|
|
checkRange(getDy2(), 0, 255, "dy2");
|
2015-10-26 06:32:30 -04:00
|
|
|
checkRange(getCol1(), 0, MAX_COL, "col1");
|
|
|
|
checkRange(getCol2(), 0, MAX_COL, "col2");
|
|
|
|
checkRange(getRow1(), 0, MAX_ROW, "row1");
|
|
|
|
checkRange(getRow2(), 0, MAX_ROW, "row2");
|
2012-06-18 16:59:32 -04:00
|
|
|
|
|
|
|
setCol1(col1);
|
|
|
|
setRow1(row1);
|
|
|
|
setDx1(x1);
|
|
|
|
setDy1(y1);
|
|
|
|
setCol2(col2);
|
|
|
|
setRow2(row2);
|
|
|
|
setDx2(x2);
|
|
|
|
setDy2(y2);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
public boolean isHorizontallyFlipped() {
|
2012-07-11 08:08:38 -04:00
|
|
|
return _isHorizontallyFlipped;
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
public boolean isVerticallyFlipped() {
|
2012-07-11 08:08:38 -04:00
|
|
|
return _isVerticallyFlipped;
|
2012-06-18 16:59:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-08-06 17:06:12 -04:00
|
|
|
protected EscherRecord getEscherAnchor() {
|
2012-06-18 16:59:32 -04:00
|
|
|
return _escherClientAnchor;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void createEscherAnchor() {
|
|
|
|
_escherClientAnchor = new EscherClientAnchorRecord();
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2005-05-01 07:26:18 -04:00
|
|
|
/**
|
|
|
|
* Gets the anchor type
|
2015-11-25 02:16:43 -05:00
|
|
|
* @return the anchor type
|
2005-05-01 07:26:18 -04:00
|
|
|
*/
|
2015-11-25 02:16:43 -05:00
|
|
|
@Override
|
|
|
|
public AnchorType getAnchorType() {
|
|
|
|
return AnchorType.byId(_escherClientAnchor.getFlag());
|
2005-05-01 07:26:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the anchor type
|
2015-11-25 02:16:43 -05:00
|
|
|
* @param anchorType the anchor type to set
|
2005-05-01 07:26:18 -04:00
|
|
|
*/
|
2015-11-25 02:16:43 -05:00
|
|
|
@Override
|
|
|
|
public void setAnchorType(AnchorType anchorType) {
|
|
|
|
_escherClientAnchor.setFlag(anchorType.value);
|
2005-05-01 07:26:18 -04:00
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
private void checkRange(int value, int minRange, int maxRange, String varName) {
|
2004-04-09 07:45:38 -04:00
|
|
|
if (value < minRange || value > maxRange)
|
2013-12-31 10:11:44 -05:00
|
|
|
throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange + ", but was: " + value);
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|
|
|
|
|
2015-10-26 06:32:30 -04:00
|
|
|
/**
|
|
|
|
* Given a 16-bit unsigned integer stored in a short, return the unsigned value.
|
|
|
|
*
|
|
|
|
* @param s A 16-bit value intended to be interpreted as an unsigned integer.
|
|
|
|
* @return The value represented by <code>s</code>.
|
|
|
|
*/
|
|
|
|
private static int unsignedValue(final short s) {
|
|
|
|
return (s < 0 ? 0x10000 + s : s);
|
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (obj == null)
|
|
|
|
return false;
|
|
|
|
if (obj == this)
|
|
|
|
return true;
|
|
|
|
if (obj.getClass() != getClass())
|
|
|
|
return false;
|
|
|
|
HSSFClientAnchor anchor = (HSSFClientAnchor) obj;
|
|
|
|
|
|
|
|
return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1()
|
|
|
|
&& anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2()
|
|
|
|
&& anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType();
|
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
|
2014-02-09 16:19:20 -05:00
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
assert false : "hashCode not designed";
|
|
|
|
return 42; // any arbitrary constant will do
|
|
|
|
}
|
|
|
|
|
2012-06-18 16:59:32 -04:00
|
|
|
@Override
|
|
|
|
public int getDx1() {
|
|
|
|
return _escherClientAnchor.getDx1();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setDx1(int dx1) {
|
|
|
|
_escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getDy1() {
|
|
|
|
return _escherClientAnchor.getDy1();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setDy1(int dy1) {
|
|
|
|
_escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getDy2() {
|
|
|
|
return _escherClientAnchor.getDy2();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setDy2(int dy2) {
|
|
|
|
_escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getDx2() {
|
|
|
|
return _escherClientAnchor.getDx2();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setDx2(int dx2) {
|
|
|
|
_escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue());
|
|
|
|
}
|
2004-04-09 07:45:38 -04:00
|
|
|
}
|