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

de.gsi.chart.axes.spi.TickMark Maven / Gradle / Ivy

package de.gsi.chart.axes.spi;

import javafx.geometry.VPos;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;

import de.gsi.chart.ui.geometry.Side;

/**
 * TickMark represents the label text, its associated tick mark value and position along the axis for each tick.
 *
 * @author rstein
 */
public class TickMark extends Text {
    private final Side side; // tick mark side (LEFT, TOP; RIGHT; BOTTOM)
    private double tickValue; // tick mark in data units
    private double tickPosition; // tick position along axis in display units
    private double tickRotation; // tick mark rotation (here: centre axis)

    /**
     * Creates and initialises an instance of TickMark.
     *
     * @param side where tick mark is supposed to be drawn (N.B. controls text alignment together with rotation)
     * @param tickValue numeric value of tick
     * @param tickPosition position of tick in canvas pixel coordinates
     * @param tickRotation rotation of the tick mark label in degree
     * @param tickMarkLabel string label associated with tick
     */
    public TickMark(final Side side, final double tickValue, final double tickPosition, final double tickRotation,
            final String tickMarkLabel) {
        super();
        this.side = side;
        this.tickValue = tickValue;
        this.tickPosition = tickPosition;
        this.tickRotation = tickRotation;
        setText(tickMarkLabel);
        setRotate(tickRotation);
        recomputeAlignment(); // NOPMD may be overwritten in user-code

        fontProperty().addListener((ch, o, n) -> applyCss());
        fillProperty().addListener((ch, o, n) -> applyCss());
        visibleProperty().addListener((ch, o, n) -> applyCss());
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof TickMark)) {
            return false;
        }
        final TickMark other = (TickMark) obj;

        // text is not a critical for equals/hashCode
        return (tickPosition == other.tickPosition) && (tickRotation == other.tickRotation)
                && (tickValue == other.tickValue);
    }

    /**
     * @return the height of the tick mark including rotation etc.
     */
    public double getHeight() {
        // N.B. important: usage of getBoundsInParent() which also takes into
        // account text rotations
        return getBoundsInParent().getHeight();
    }

    /**
     * @return value tick position along the axis in display units
     */
    public double getPosition() {
        return tickPosition;
    }

    /**
     * @return value tick rotation
     */
    public double getRotation() {
        return tickRotation;
    }

    /**
     * @return side of axis where tick mark is supposed to be drawn (N.B. controls text alignment together with
     *         rotation)
     */
    public Side getSide() {
        return side;
    }

    /**
     * @return tick mark value in data units
     */
    public double getValue() {
        return tickValue;
    }

    /**
     * @return the width of the tick mark including rotation etc.
     */
    public double getWidth() {
        // N.B. important: usage of getBoundsInParent() which also takes into
        // account text rotations
        return getBoundsInParent().getWidth();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;

        temp = Double.doubleToLongBits(tickPosition);
        result = (prime * result) + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(tickRotation);
        result = (prime * result) + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(tickValue);
        result = (prime * result) + (int) (temp ^ (temp >>> 32));
        // text is not a critical for equals/hashCode

        return result;
    }

    public void recomputeAlignment() {
        // normalise rotation to [-360, +360]
        final int rotation = ((int) getRotation() % 360);
        switch (side) {
        case TOP:
            setTextAlignment(TextAlignment.CENTER);
            setTextOrigin(VPos.BOTTOM);
            //special alignment treatment if axes labels are to be rotated
            if ((rotation != 0) && ((rotation % 90) == 0)) {
                setTextAlignment(TextAlignment.LEFT);
                setTextOrigin(VPos.CENTER);
            } else if ((rotation % 90) != 0) {
                // pivoting point to left-bottom label corner
                setTextAlignment(TextAlignment.LEFT);
                setTextOrigin(VPos.BOTTOM);
            }
            break;
        case BOTTOM:
        case CENTER_HOR:
            setTextAlignment(TextAlignment.CENTER);
            setTextOrigin(VPos.TOP);
            // special alignment treatment if axes labels are to be rotated
            if ((rotation != 0) && ((rotation % 90) == 0)) {
                setTextAlignment(TextAlignment.LEFT);
                setTextOrigin(VPos.CENTER);
            } else if ((rotation % 90) != 0) {
                // pivoting point to left-top label corner
                setTextAlignment(TextAlignment.LEFT);
                setTextOrigin(VPos.TOP);
            }
            break;
        case LEFT:
            setTextAlignment(TextAlignment.RIGHT);
            setTextOrigin(VPos.CENTER);
            // special alignment treatment if axes labels are to be rotated
            if ((rotation != 0) && ((rotation % 90) == 0)) {
                setTextAlignment(TextAlignment.CENTER);
                setTextOrigin(VPos.BOTTOM);
            }
            break;
        case RIGHT:
        case CENTER_VER:
            setTextAlignment(TextAlignment.LEFT);
            setTextOrigin(VPos.CENTER);
            // special alignment treatment if axes labels are to be rotated
            if ((rotation != 0) && ((rotation % 90) == 0)) {
                setTextAlignment(TextAlignment.CENTER);
                setTextOrigin(VPos.TOP);
            }
            break;
        default:
        }
    }

    /**
     * @param value tick position along the axis in display units
     */
    public void setPosition(final double value) {
        tickPosition = value;
    }

    /**
     * @param value tick rotation
     */
    public void setRotation(final double value) {
        tickRotation = value;
        setRotate(tickRotation);
        recomputeAlignment();
    }

    /**
     * @param newValue tick mark value in data units
     */
    public void setValue(final Double newValue) {
        tickValue = newValue;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy