123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /* ====================================================================
- 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
-
- 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.
- ==================================================================== */
-
- package org.apache.poi.hssf.usermodel;
-
- import org.apache.poi.ddf.EscherClientAnchorRecord;
- import org.apache.poi.ddf.EscherRecord;
- import org.apache.poi.ss.SpreadsheetVersion;
- import org.apache.poi.ss.usermodel.ClientAnchor;
- import org.apache.poi.util.Removal;
-
- /**
- * A client anchor is attached to an excel worksheet. It anchors against a
- * top-left and buttom-right cell.
- */
- public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
-
- public static final int MAX_COL = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
- public static final int MAX_ROW = SpreadsheetVersion.EXCEL97.getLastRowIndex();
-
- private EscherClientAnchorRecord _escherClientAnchor;
-
- public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
- this._escherClientAnchor = escherClientAnchorRecord;
- }
-
- /**
- * Creates a new client anchor and defaults all the anchor positions to 0.
- */
- public HSSFClientAnchor() {
- }
-
- /**
- * Creates a new client anchor and 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!
- *
- * @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.
- */
- public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {
- super(dx1, dy1, dx2, dy2);
-
- checkRange(dx1, 0, 1023, "dx1");
- checkRange(dx2, 0, 1023, "dx2");
- checkRange(dy1, 0, 255, "dy1");
- checkRange(dy2, 0, 255, "dy2");
- checkRange(col1, 0, MAX_COL, "col1");
- checkRange(col2, 0, MAX_COL, "col2");
- checkRange(row1, 0, MAX_ROW, "row1");
- checkRange(row2, 0, MAX_ROW, "row2");
-
- setCol1((short) Math.min(col1, col2));
- setCol2((short) Math.max(col1, col2));
- setRow1(Math.min(row1, row2));
- setRow2(Math.max(row1, row2));
-
- if (col1 > col2){
- _isHorizontallyFlipped = true;
- }
- if (row1 > row2){
- _isVerticallyFlipped = true;
- }
- }
-
- /**
- * Calculates the height of a client anchor in points.
- *
- * @param sheet the sheet the anchor will be attached to
- * @return the shape height.
- */
- public float getAnchorHeightInPoints(HSSFSheet sheet) {
- int y1 = getDy1();
- int y2 = getDy2();
- int row1 = Math.min(getRow1(), getRow2());
- int row2 = Math.max(getRow1(), getRow2());
-
- float points = 0;
- if (row1 == row2) {
- points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2);
- } else {
- points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1);
- for (int i = row1 + 1; i < row2; i++) {
- points += getRowHeightInPoints(sheet, i);
- }
- points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2);
- }
-
- return points;
- }
-
- private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) {
- HSSFRow row = sheet.getRow(rowNum);
- if (row == null) {
- return sheet.getDefaultRowHeightInPoints();
- }
- return row.getHeightInPoints();
- }
-
- /**
- * @return the column(0 based) of the first cell.
- */
- public short getCol1() {
- return _escherClientAnchor.getCol1();
- }
-
- /**
- * @param col1 the column(0 based) of the first cell.
- */
- public void setCol1(short col1) {
- checkRange(col1, 0, MAX_COL, "col1");
- _escherClientAnchor.setCol1(col1);
- }
-
- /**
- * @param col1 0-based column of the first cell.
- */
- public void setCol1(int col1) {
- setCol1((short) col1);
- }
-
- /**
- * @return the column(0 based) of the first cell.
- */
- public short getCol2() {
- return _escherClientAnchor.getCol2();
- }
-
- /**
- * @param col2 the column(0 based) of the second cell.
- */
- public void setCol2(short col2) {
- checkRange(col2, 0, MAX_COL, "col2");
- _escherClientAnchor.setCol2(col2);
- }
-
- /**
- * @param col2 the column(0 based) of the second cell.
- */
- public void setCol2(int col2) {
- setCol2((short) col2);
- }
-
- /**
- * @return the row(0 based) of the first cell.
- */
- public int getRow1() {
- return unsignedValue(_escherClientAnchor.getRow1());
- }
-
- /**
- * @param row1 0-based row of the first cell.
- */
- public void setRow1(int row1) {
- checkRange(row1, 0, MAX_ROW, "row1");
- _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue());
- }
-
- /**
- * @return the row(0 based) of the second cell.
- */
- public int getRow2() {
- return unsignedValue(_escherClientAnchor.getRow2());
- }
-
- /**
- * @param row2 the row(0 based) of the second cell.
- */
- public void setRow2(int row2) {
- checkRange(row2, 0, MAX_ROW, "row2");
- _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
- }
-
- /**
- * 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!
- *
- * @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.
- * @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.
- */
- 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");
- checkRange(getCol1(), 0, MAX_COL, "col1");
- checkRange(getCol2(), 0, MAX_COL, "col2");
- checkRange(getRow1(), 0, MAX_ROW, "row1");
- checkRange(getRow2(), 0, MAX_ROW, "row2");
-
- setCol1(col1);
- setRow1(row1);
- setDx1(x1);
- setDy1(y1);
- setCol2(col2);
- setRow2(row2);
- setDx2(x2);
- setDy2(y2);
- }
-
- public boolean isHorizontallyFlipped() {
- return _isHorizontallyFlipped;
- }
-
- public boolean isVerticallyFlipped() {
- return _isVerticallyFlipped;
- }
-
- @Override
- protected EscherRecord getEscherAnchor() {
- return _escherClientAnchor;
- }
-
- @Override
- protected void createEscherAnchor() {
- _escherClientAnchor = new EscherClientAnchorRecord();
- }
-
- /**
- * Gets the anchor type
- * Changed from returning an int to an enum in POI 3.14 beta 1.
- * @return the anchor type
- */
- @Override
- public AnchorType getAnchorType() {
- return AnchorType.byId(_escherClientAnchor.getFlag());
- }
-
- /**
- * Sets the anchor type
- * @param anchorType the anchor type to set
- * @since POI 3.14
- */
- @Override
- public void setAnchorType(AnchorType anchorType) {
- _escherClientAnchor.setFlag(anchorType.value);
- }
- /**
- * Sets the anchor type
- * @param anchorType the anchor type to set
- * @deprecated POI 3.15. Use {@link #setAnchorType(AnchorType)} instead.
- */
- @Removal(version="3.17")
- @Override
- public void setAnchorType(int anchorType) {
- _escherClientAnchor.setFlag((short) anchorType);
- }
-
- private void checkRange(int value, int minRange, int maxRange, String varName) {
- if (value < minRange || value > maxRange)
- throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange + ", but was: " + value);
- }
-
- /**
- * 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);
- }
-
- @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();
- }
-
- @Override
- public int hashCode() {
- assert false : "hashCode not designed";
- return 42; // any arbitrary constant will do
- }
-
- @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());
- }
- }
|