1 /*
   2  * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
  29  *
  30  * The original version of this source code and documentation is
  31  * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
  32  * of IBM. These materials are provided under terms of a License
  33  * Agreement between Taligent and Sun. This technology is protected
  34  * by multiple US and International patents.
  35  *
  36  * This notice and attribution to Taligent may not be removed.
  37  * Taligent is a registered trademark of Taligent, Inc.
  38  *
  39  */
  40 
  41 package java.awt.font;
  42 import java.lang.String;
  43 
  44 /**
  45  * The {@code TextHitInfo} class represents a character position in a
  46  * text model, and a <b>bias</b>, or "side," of the character.  Biases are
  47  * either <EM>leading</EM> (the left edge, for a left-to-right character)
  48  * or <EM>trailing</EM> (the right edge, for a left-to-right character).
  49  * Instances of {@code TextHitInfo} are used to specify caret and
  50  * insertion positions within text.
  51  * <p>
  52  * For example, consider the text "abc".  TextHitInfo.trailing(1)
  53  * corresponds to the right side of the 'b' in the text.
  54  * <p>
  55  * {@code TextHitInfo} is used primarily by {@link TextLayout} and
  56  * clients of {@code TextLayout}.  Clients of {@code TextLayout}
  57  * query {@code TextHitInfo} instances for an insertion offset, where
  58  * new text is inserted into the text model.  The insertion offset is equal
  59  * to the character position in the {@code TextHitInfo} if the bias
  60  * is leading, and one character after if the bias is trailing.  The
  61  * insertion offset for TextHitInfo.trailing(1) is 2.
  62  * <p>
  63  * Sometimes it is convenient to construct a {@code TextHitInfo} with
  64  * the same insertion offset as an existing one, but on the opposite
  65  * character.  The {@code getOtherHit} method constructs a new
  66  * {@code TextHitInfo} with the same insertion offset as an existing
  67  * one, with a hit on the character on the other side of the insertion offset.
  68  * Calling {@code getOtherHit} on trailing(1) would return leading(2).
  69  * In general, {@code getOtherHit} for trailing(n) returns
  70  * leading(n+1) and {@code getOtherHit} for leading(n)
  71  * returns trailing(n-1).
  72  * <p>
  73  * <strong>Example</strong>:<p>
  74  * Converting a graphical point to an insertion point within a text
  75  * model
  76  * <blockquote><pre>
  77  * TextLayout layout = ...;
  78  * Point2D.Float hitPoint = ...;
  79  * TextHitInfo hitInfo = layout.hitTestChar(hitPoint.x, hitPoint.y);
  80  * int insPoint = hitInfo.getInsertionIndex();
  81  * // insPoint is relative to layout;  may need to adjust for use
  82  * // in a text model
  83  * </pre></blockquote>
  84  *
  85  * @see TextLayout
  86  */
  87 
  88 public final class TextHitInfo {
  89     private int charIndex;
  90     private boolean isLeadingEdge;
  91 
  92     /**
  93      * Constructs a new {@code TextHitInfo}.
  94      * @param charIndex the index of the character hit
  95      * @param isLeadingEdge {@code true} if the leading edge of the
  96      * character was hit
  97      */
  98     private TextHitInfo(int charIndex, boolean isLeadingEdge) {
  99         this.charIndex = charIndex;
 100         this.isLeadingEdge = isLeadingEdge;
 101     }
 102 
 103     /**
 104      * Returns the index of the character hit.
 105      * @return the index of the character hit.
 106      */
 107     public int getCharIndex() {
 108         return charIndex;
 109     }
 110 
 111     /**
 112      * Returns {@code true} if the leading edge of the character was
 113      * hit.
 114      * @return {@code true} if the leading edge of the character was
 115      * hit; {@code false} otherwise.
 116      */
 117     public boolean isLeadingEdge() {
 118         return isLeadingEdge;
 119     }
 120 
 121     /**
 122      * Returns the insertion index.  This is the character index if
 123      * the leading edge of the character was hit, and one greater
 124      * than the character index if the trailing edge was hit.
 125      * @return the insertion index.
 126      */
 127     public int getInsertionIndex() {
 128         return isLeadingEdge ? charIndex : charIndex + 1;
 129     }
 130 
 131     /**
 132      * Returns the hash code.
 133      * @return the hash code of this {@code TextHitInfo}, which is
 134      * also the {@code charIndex} of this {@code TextHitInfo}.
 135      */
 136     public int hashCode() {
 137         return charIndex;
 138     }
 139 
 140     /**
 141      * Returns {@code true} if the specified {@code Object} is a
 142      * {@code TextHitInfo} and equals this {@code TextHitInfo}.
 143      * @param obj the {@code Object} to test for equality
 144      * @return {@code true} if the specified {@code Object}
 145      * equals this {@code TextHitInfo}; {@code false} otherwise.
 146      */
 147     public boolean equals(Object obj) {
 148         return (obj instanceof TextHitInfo) && equals((TextHitInfo)obj);
 149     }
 150 
 151     /**
 152      * Returns {@code true} if the specified {@code TextHitInfo}
 153      * has the same {@code charIndex} and {@code isLeadingEdge}
 154      * as this {@code TextHitInfo}.  This is not the same as having
 155      * the same insertion offset.
 156      * @param hitInfo a specified {@code TextHitInfo}
 157      * @return {@code true} if the specified {@code TextHitInfo}
 158      * has the same {@code charIndex} and {@code isLeadingEdge}
 159      * as this {@code TextHitInfo}.
 160      */
 161     public boolean equals(TextHitInfo hitInfo) {
 162         return hitInfo != null && charIndex == hitInfo.charIndex &&
 163             isLeadingEdge == hitInfo.isLeadingEdge;
 164     }
 165 
 166     /**
 167      * Returns a {@code String} representing the hit for debugging
 168      * use only.
 169      * @return a {@code String} representing this
 170      * {@code TextHitInfo}.
 171      */
 172     public String toString() {
 173         return "TextHitInfo[" + charIndex + (isLeadingEdge ? "L" : "T")+"]";
 174     }
 175 
 176     /**
 177      * Creates a {@code TextHitInfo} on the leading edge of the
 178      * character at the specified {@code charIndex}.
 179      * @param charIndex the index of the character hit
 180      * @return a {@code TextHitInfo} on the leading edge of the
 181      * character at the specified {@code charIndex}.
 182      */
 183     public static TextHitInfo leading(int charIndex) {
 184         return new TextHitInfo(charIndex, true);
 185     }
 186 
 187     /**
 188      * Creates a hit on the trailing edge of the character at
 189      * the specified {@code charIndex}.
 190      * @param charIndex the index of the character hit
 191      * @return a {@code TextHitInfo} on the trailing edge of the
 192      * character at the specified {@code charIndex}.
 193      */
 194     public static TextHitInfo trailing(int charIndex) {
 195         return new TextHitInfo(charIndex, false);
 196     }
 197 
 198     /**
 199      * Creates a {@code TextHitInfo} at the specified offset,
 200      * associated with the character before the offset.
 201      * @param offset an offset associated with the character before
 202      * the offset
 203      * @return a {@code TextHitInfo} at the specified offset.
 204      */
 205     public static TextHitInfo beforeOffset(int offset) {
 206         return new TextHitInfo(offset-1, false);
 207     }
 208 
 209     /**
 210      * Creates a {@code TextHitInfo} at the specified offset,
 211      * associated with the character after the offset.
 212      * @param offset an offset associated with the character after
 213      * the offset
 214      * @return a {@code TextHitInfo} at the specified offset.
 215      */
 216     public static TextHitInfo afterOffset(int offset) {
 217         return new TextHitInfo(offset, true);
 218     }
 219 
 220     /**
 221      * Creates a {@code TextHitInfo} on the other side of the
 222      * insertion point.  This {@code TextHitInfo} remains unchanged.
 223      * @return a {@code TextHitInfo} on the other side of the
 224      * insertion point.
 225      */
 226     public TextHitInfo getOtherHit() {
 227         if (isLeadingEdge) {
 228             return trailing(charIndex - 1);
 229         } else {
 230             return leading(charIndex + 1);
 231         }
 232     }
 233 
 234     /**
 235      * Creates a {@code TextHitInfo} whose character index is offset
 236      * by {@code delta} from the {@code charIndex} of this
 237      * {@code TextHitInfo}. This {@code TextHitInfo} remains
 238      * unchanged.
 239      * @param delta the value to offset this {@code charIndex}
 240      * @return a {@code TextHitInfo} whose {@code charIndex} is
 241      * offset by {@code delta} from the {@code charIndex} of
 242      * this {@code TextHitInfo}.
 243      */
 244     public TextHitInfo getOffsetHit(int delta) {
 245         return new TextHitInfo(charIndex + delta, isLeadingEdge);
 246     }
 247 }