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

org.apache.pivot.wtk.Span Maven / Gradle / Ivy

The newest version!
/*
 * 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.pivot.wtk;

import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.json.JSONSerializer;
import org.apache.pivot.serialization.SerializationException;

/**
 * Class representing a range of integer values. The range includes all
 * values in the interval [start, end]. Values may be negative, and the
 * value of start may be less than or equal to the value of
 * end.
 */
public final class Span {
    public final int start;
    public final int end;

    public static final String START_KEY = "start";
    public static final String END_KEY = "end";

    public Span(int index) {
        start = index;
        end = index;
    }

    public Span(int start, int end) {
        this.start = start;
        this.end = end;
    }

    public Span(Span span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        start = span.start;
        end = span.end;
    }

    public Span(Dictionary span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        if (!span.containsKey(START_KEY)) {
            throw new IllegalArgumentException(START_KEY + " is required.");
        }

        if (!span.containsKey(END_KEY)) {
            throw new IllegalArgumentException(END_KEY + " is required.");
        }

        start = (Integer)span.get(START_KEY);
        end = (Integer)span.get(END_KEY);
    }

    /**
     * Returns the length of the span.
     *
     * @return
     * The absolute value of (end minus start) + 1.
     */
    public long getLength() {
        return Math.abs((long)end - (long)start) + 1;
    }

    /**
     * Determines whether this span contains another span.
     *
     * @param span
     * The span to test for containment.
     *
     * @return
     * true if this span contains span; false,
     * otherwise.
     */
    public boolean contains(Span span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        Span normalizedSpan = span.normalize();

        boolean contains;
        if (start < end) {
            contains = (start <= normalizedSpan.start
                && end >= normalizedSpan.end);
        } else {
            contains = (end <= normalizedSpan.start
                && start >= normalizedSpan.end);
        }

        return contains;
    }

    /**
     * Determines whether this span intersects with another span.
     *
     * @param span
     * The span to test for intersection.
     *
     * @return
     * true if this span intersects with span;
     * false, otherwise.
     */
    public boolean intersects(Span span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        Span normalizedSpan = span.normalize();

        boolean intersects;
        if (start < end) {
            intersects = (start <= normalizedSpan.end
                && end >= normalizedSpan.start);
        } else {
            intersects = (end <= normalizedSpan.end
                && start >= normalizedSpan.start);
        }

        return intersects;
    }

    /**
     * Calculates the intersection of this span and another span.
     *
     * @param span
     * The span to intersect with this span.
     *
     * @return
     * A new Span instance representing the intersection of this span and
     * span, or null if the spans do not intersect.
     */
    public Span intersect(Span span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        Span intersection = null;

        if (intersects(span)) {
            intersection = new Span(Math.max(start, span.start),
                Math.min(end, span.end));
        }

        return intersection;
    }

    /**
     * Calculates the union of this span and another span.
     *
     * @param span
     * The span to union with this span.
     *
     * @return
     * A new Span instance representing the union of this span and
     * span.
     */
    public Span union(Span span) {
        if (span == null) {
            throw new IllegalArgumentException("span is null.");
        }

        return new Span(Math.min(start, span.start),
            Math.max(end, span.end));
    }

    /**
     * Returns a normalized equivalent of the span in which
     * start is guaranteed to be less than end.
     */
    public Span normalize() {
        return new Span(Math.min(start, end), Math.max(start, end));
    }

    /**
     * Returns a new {@link Span} with both values offset by the given value.
     * 

This is useful while moving through a {@link TextPane} document * for instance, where you have to subtract off the starting offset for * child nodes. * * @param offset The positive or negative amount by which to "move" this * span (both start and end). * @return A new {@link Span} with updated values. */ public Span offset(int offset) { return new Span(this.start + offset, this.end + offset); } @Override public boolean equals(Object o) { boolean equal = false; if (o instanceof Span) { Span span = (Span)o; equal = (start == span.start && end == span.end); } return equal; } @Override public int hashCode() { return 31 * start + end; } @Override public String toString() { return ("{start: " + start + ", end: " + end + "}"); } public static Span decode(String value) { if (value == null) { throw new IllegalArgumentException(); } Span span; if (value.startsWith("{")) { try { span = new Span(JSONSerializer.parseMap(value)); } catch (SerializationException exception) { throw new IllegalArgumentException(exception); } } else { span = new Span(Integer.parseInt(value)); } return span; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy