All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.spreadsheet.SheetOverlayWrapper Maven / Gradle / Ivy

There is a newer version: 24.6.0
Show newest version
/**
 * Copyright 2000-2024 Vaadin Ltd.
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See {@literal } for the full
 * license.
 */
package com.vaadin.flow.component.spreadsheet;

import java.io.Serializable;

import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.spreadsheet.client.OverlayInfo;
import com.vaadin.flow.server.StreamResource;

@SuppressWarnings("serial")
public abstract class SheetOverlayWrapper implements Serializable {

    public interface OverlayChangeListener extends Serializable {
        void overlayChanged();
    }

    private static long counter;

    private final ClientAnchor anchor;
    private final String id;

    private boolean visible;

    public SheetOverlayWrapper(ClientAnchor anchor) {
        this.anchor = anchor;
        id = "sheet-overlay-" + counter;
        counter++;
    }

    /**
     * If this overlay's state can be dynamically changed (like minimizing),
     * this method can inform the spreadsheet.
     *
     * @param listener
     */
    public void setOverlayChangeListener(OverlayChangeListener listener) {
        // NOP
    }

    /**
     * Determines if this image should be visible within the given visible area.
     *
     * @param r1
     *            Row index of topmost row, 1-based
     * @param c1
     *            Column index of leftmost column, 1-based
     * @param r2
     *            Row index of bottom-most row, 1-based
     * @param c2
     *            Column index of rightmost column, 1-based
     *
     * @return true if the image should be visible inside the range, false
     *         otherwise
     */
    public boolean isVisible(int r1, int c1, int r2, int c2) {
        int col1 = anchor.getCol1() + 1;
        int col2 = anchor.getCol2() + 1;
        int row1 = anchor.getRow1() + 1;
        int row2 = anchor.getRow2() + 1;

        // sanity check
        if (r2 - r1 < 0 || c2 - c1 < 0) {
            return false;
        }

        boolean col1isBetweenc1andc2 = c1 <= col1 && col1 <= c2;

        boolean col2isBetweenc1andc2 = c1 <= col2 && col2 <= c2;

        boolean inColumnRange = col1isBetweenc1andc2 || col2isBetweenc1andc2;

        boolean row1isBetweenr1andr2 = r1 <= row1 && row1 <= r2;

        boolean row2isBetweenr1andr2 = r1 <= row2 && row2 <= r2;

        boolean inRowRange = row1isBetweenr1andr2 || row2isBetweenr1andr2;

        return inColumnRange && inRowRange;
    }

    /**
     * Returns the coordinate of the left edge of the image inside the leftmost
     * column this image occupies. Value is converted to pixels.
     *
     * @param sheet
     *            The Sheet this image is in
     * @return coordinate of image's left edge in PX
     */
    float getDx1(Sheet sheet) {
        if (anchor instanceof XSSFClientAnchor) {
            return (float) anchor.getDx1() / Units.EMU_PER_PIXEL;
        } else {
            return sheet.getColumnWidthInPixels(anchor.getCol1())
                    * anchor.getDx1() / 1023f;
        }
    }

    /**
     * Returns the coordinate of the right edge of the image inside the
     * rightmost column this image occupies. Value is converted to pixels.
     *
     * @param sheet
     *            The Sheet this image is in
     * @return coordinate of image's right edge in PX
     */
    private float getDx2(Sheet sheet) {
        if (anchor instanceof XSSFClientAnchor) {
            return (float) anchor.getDx2() / Units.EMU_PER_PIXEL;
        } else {
            return sheet.getColumnWidthInPixels(anchor.getCol2())
                    * anchor.getDx2() / 1023f;
        }
    }

    /**
     * Returns the coordinate of the top edge of the image inside the topmost
     * row this image occupies. Value is converted to pixels.
     *
     * @param sheet
     *            The Sheet this image is in
     * @return coordinate of image's top edge in PX
     */
    float getDy1(Sheet sheet) {
        if (anchor instanceof XSSFClientAnchor) {
            return (float) anchor.getDy1() / Units.EMU_PER_POINT;
        } else {
            Row row = sheet.getRow(anchor.getRow1());
            return (row == null ? sheet.getDefaultRowHeightInPoints()
                    : row.getHeightInPoints()) * anchor.getDy1() / 255f;
        }
    }

    /**
     * Returns the coordinate of the bottom edge of the image inside the bottom
     * row this image occupies. Value is converted to pixels.
     *
     * @param sheet
     *            The Sheet this image is in
     * @return coordinate of image's bottom edge in PX
     */
    private float getDy2(Sheet sheet) {
        if (anchor instanceof XSSFClientAnchor) {
            return (float) anchor.getDy2() / Units.EMU_PER_POINT;
        } else {
            Row row = sheet.getRow(anchor.getRow2());
            return (row == null ? sheet.getDefaultRowHeightInPoints()
                    : row.getHeightInPoints()) * anchor.getDy2() / 255f;
        }
    }

    /**
     * Calculates the width of the image. Might not be 100% correct because of
     * bugs in POI (returns inconsistent values for Dx and Dy).
     * 

* If the image doesn't have a specified width and should be sized to image * file size, -1 is returned. * * @param sheet * The sheet this image belongs to * @param colW * Array of column widths in pixels * @param defaultColumnWidthPX * Default column width in pixels * @return Width of the image in pixels, or -1 if image file width should be * used */ public float getWidth(Sheet sheet, int colW[], int defaultColumnWidthPX) { float width; short col1 = anchor.getCol1(); short col2 = anchor.getCol2(); width = getDx2(sheet) - getDx1(sheet); if (col1 < col2) { for (int i = col1; i < col2; i++) { if (!sheet.isColumnHidden(i)) { if (i < colW.length) { width += colW[i]; } else { width += defaultColumnWidthPX; } } } } else if (col1 > col2) { // for some reason POI (3.9) gives a col2 of 0 for certain // type of anchors .. width = -1.0F; } // else col1 == col2 -> keep dx2-dx1 return width; } /** * Calculates the height of the image. Might not be 100% correct because of * bugs in POI (returns inconsistent values for Dx and Dy). *

* If the image doesn't have a specified height and should be sized to image * file size, -1 is returned. * * @param sheet * The sheet this image belongs to * @param rowH * Array of row heights in points * @return Image height in points, or -1 if image file height should be * used. */ public float getHeight(Sheet sheet, float[] rowH) { float height; int row1 = anchor.getRow1(); int row2 = anchor.getRow2(); height = getDy2(sheet) - getDy1(sheet); if (row1 < row2) { for (int i = row1; i < row2; i++) { Row row = sheet.getRow(i); if (row == null || !row.getZeroHeight()) { if (i < rowH.length) { height += rowH[i]; } else { height += sheet.getDefaultRowHeightInPoints(); } } } } else if (row1 > row2) { // for some reason POI (3.9) gives a rol2 of 0 for some // type of anchors.. height = -1.0F; } // else row1 == row2 -> keep dy2-dy1 return height; } /** * Returns a unique ID of this overlay, used also as a resource key for * images. */ public String getId() { return id; } /** * Gets the visibility state of this overlay in the current spreadsheet * view. * * @return true if overlay is visible, false otherwise */ public boolean isVisible() { return visible; } /** * Marks this as image visible or hidden in the current spreadsheet view. * Only used for the spreadsheet to remember if data needs to be removed, * doesn't affect real visibility. * * @param visible * true to set visible, false to set hidden */ public void setVisible(boolean visible) { this.visible = visible; } /** * Gets the anchor for this image within the sheet containing this image. * * @return Anchor for this image */ public ClientAnchor getAnchor() { return anchor; } public StreamResource getResource() { return null; } /** * Returns the component contained in this wrapper if there is one. * * @param init * false if you don't want to initialize the component, calling * with true after the first time has no effect. */ public Component getComponent(final boolean init) { return null; } public abstract OverlayInfo.Type getType(); @Override public String toString() { String anchor = ", anchor=null"; if (getAnchor() != null) { anchor = ", col1=" + getAnchor().getCol1() + ", col2=" + getAnchor().getCol2() + ", row1=" + getAnchor().getRow1() + ", row2=" + getAnchor().getRow2() + ", dx1=" + getAnchor().getDx1() + ", dx2=" + getAnchor().getDx2() + ", dy1=" + getAnchor().getDy1() + ", dy2=" + getAnchor().getDy2() + ", type=" + getAnchor().getAnchorType(); } return "OverlayData [resourceKey=" + getId() + anchor + "]"; } @Override public int hashCode() { return id.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } SheetOverlayWrapper other = (SheetOverlayWrapper) obj; if (getAnchor() == null) { if (other.getAnchor() != null) { return false; } } else if (!getAnchor().equals(other.getAnchor())) { return false; } if (id == null) { if (other.id != null) { return false; } } else if (!id.equals(other.id)) { return false; } return true; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy