Package com.cburch.draw.util

Source Code of com.cburch.draw.util.EditableLabel

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.draw.util;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;

import javax.swing.JTextField;

import com.cburch.logisim.data.Bounds;

public class EditableLabel implements Cloneable {
  public static final int LEFT = JTextField.LEFT;
  public static final int RIGHT = JTextField.RIGHT;
  public static final int CENTER = JTextField.CENTER;
 
  public static final int TOP = 8;
  public static final int MIDDLE = 9;
  public static final int BASELINE = 10;
  public static final int BOTTOM = 11;
 
  private int x;
  private int y;
  private String text;
  private Font font;
  private Color color;
  private int horzAlign;
  private int vertAlign;
  private boolean dimsKnown;
  private int width;
  private int ascent;
  private int descent;
  private int[] charX;
  private int[] charY;
 
  public EditableLabel(int x, int y, String text, Font font) {
    this.x = x;
    this.y = y;
    this.text = text;
    this.font = font;
    this.color = Color.BLACK;
    this.horzAlign = LEFT;
    this.vertAlign = BASELINE;
    this.dimsKnown = false;
  }
 
  @Override
  public EditableLabel clone() {
    try {
      return (EditableLabel) super.clone();
    } catch (CloneNotSupportedException e) {
      return new EditableLabel(x, y, text, font);
    }
  }
 
  @Override
  public boolean equals(Object other) {
    if (other instanceof EditableLabel) {
      EditableLabel that = (EditableLabel) other;
      return this.x == that.x && this.y == that.y
        && this.text.equals(that.text) && this.font.equals(that.font)
        && this.color.equals(that.color)
        && this.horzAlign == that.horzAlign
        && this.vertAlign == that.vertAlign;
    } else {
      return false;
    }
  }
 
  @Override
  public int hashCode() {
    int ret = x * 31 + y;
    ret = ret * 31 + text.hashCode();
    ret = ret * 31 + font.hashCode();
    ret = ret * 31 + color.hashCode();
    ret = ret * 31 + horzAlign;
    ret = ret * 31 + vertAlign;
    return ret;
  }

  //
  // accessor methods
  //
  public int getX() {
    return x;
  }
 
  public int getY() {
    return y;
  }

  public void setLocation(int x, int y) {
    this.x = x;
    this.y = y;
  }
 
  public String getText() {
    return text;
  }
 
  public void setText(String value) {
    dimsKnown = false;
    text = value;
  }

  public Font getFont() {
    return font;
  }
 
  public void setFont(Font value) {
    font = value;
    dimsKnown = false;
  }
 
  public Color getColor() {
    return color;
  }
 
  public void setColor(Color value) {
    color = value;
  }
 
  public int getHorizontalAlignment() {
    return horzAlign;
  }

  public void setHorizontalAlignment(int value) {
    if (value != LEFT && value != CENTER && value != RIGHT) {
      throw new IllegalArgumentException("argument must be LEFT, CENTER, or RIGHT");
    }
    horzAlign = value;
    dimsKnown = false;
  }
 
  public int getVerticalAlignment() {
    return vertAlign;
  }
 
  public void setVerticalAlignment(int value) {
    if (value != TOP && value != MIDDLE && value != BASELINE && value != BOTTOM) {
      throw new IllegalArgumentException("argument must be TOP, MIDDLE, BASELINE, or BOTTOM");
    }
    vertAlign = value;
    dimsKnown = false;
  }
 
  //
  // more complex methods
  //
  public Bounds getBounds() {
    int x0 = getLeftX();
    int y0 = getBaseY() - ascent;
    int w = width;
    int h = ascent + descent;
    return Bounds.create(x0, y0, w, h);
  }
 
  public boolean contains(int qx, int qy) {
    int x0 = getLeftX();
    int y0 = getBaseY();
    if (qx >= x0 && qx < x0 + width
        && qy >= y0 - ascent && qy < y0 + descent) {
      int[] xs = charX;
      int[] ys = charY;
      if (xs == null || ys == null) {
        return true;
      } else {
        int i = Arrays.binarySearch(xs, qx - x0);
        if (i < 0) i = -(i + 1);
        if (i >= xs.length) {
          return false;
        } else {
          int asc = (ys[i] >> 16) & 0xFFFF;
          int desc = ys[i] & 0xFFFF;
          int dy = y0 - qy;
          return dy >= -desc && dy <= asc;
        }
      }
    } else {
      return false;
    }
  }
 
  private int getLeftX() {
    switch (horzAlign) {
    case LEFT:   return x;
    case CENTER: return x - width / 2;
    case RIGHT:  return x - width;
    default:     return x;
    }
  }
 
  private int getBaseY() {
    switch (vertAlign) {
    case TOP:      return y + ascent;
    case MIDDLE:   return y + (ascent - descent) / 2;
    case BASELINE: return y;
    case BOTTOM:   return y - descent;
    default:       return y;
    }
  }
 
  public void configureTextField(EditableLabelField field) {
    configureTextField(field, 1.0);
  }
 
  public void configureTextField(EditableLabelField field, double zoom) {
    Font f = font;
    if (zoom != 1.0) {
      f = f.deriveFont(AffineTransform.getScaleInstance(zoom, zoom));
    }
    field.setFont(f);
   
    Dimension dim = field.getPreferredSize();
    int w;
    int border = EditableLabelField.FIELD_BORDER;
    if (dimsKnown) {
      w = width + 1 + 2 * border;
    } else {
      FontMetrics fm = field.getFontMetrics(font);
      ascent = fm.getAscent();
      descent = fm.getDescent();
      w = 0;
    }
   
    int x0 = x;
    int y0 = getBaseY() - ascent;
    if (zoom != 1.0) {
      x0 = (int) Math.round(x0 * zoom);
      y0 = (int) Math.round(y0 * zoom);
      w = (int) Math.round(w * zoom);
    }
   
    w = Math.max(w, dim.width);
    int h = dim.height;
    switch (horzAlign) {
    case LEFT:   x0 = x0 - border; break;
    case CENTER: x0 = x0 - (w / 2) + 1; break;
    case RIGHT:  x0 = x0 - w + border + 1; break;
    default:     x0 = x0 - border;
    }
    y0 = y0 - border;
   
    field.setHorizontalAlignment(horzAlign);
    field.setForeground(color);
    field.setBounds(x0, y0, w, h);
  }
 
  public void paint(Graphics g) {
    g.setFont(font);
    if (!dimsKnown) {
      computeDimensions(g, font, g.getFontMetrics());
    }
    int x0 = getLeftX();
    int y0 = getBaseY();
    g.setColor(color);
    g.drawString(text, x0, y0);
  }
 
  private void computeDimensions(Graphics g, Font font, FontMetrics fm) {
    String s = text;
    FontRenderContext frc = ((Graphics2D) g).getFontRenderContext();
    width = fm.stringWidth(s);
    ascent = fm.getAscent();
    descent = fm.getDescent();
    int[] xs = new int[s.length()];
    int[] ys = new int[s.length()];
    for (int i = 0; i < xs.length; i++) {
      xs[i] = fm.stringWidth(s.substring(0, i + 1));
      TextLayout lay = new TextLayout(s.substring(i, i + 1), font, frc);
      Rectangle2D rect = lay.getBounds();
      int asc = (int) Math.ceil(-rect.getMinY());
      int desc = (int) Math.ceil(rect.getMaxY());
      if (asc < 0) asc = 0;
      if (asc > 0xFFFF) asc = 0xFFFF;
      if (desc < 0) desc = 0;
      if (desc > 0xFFFF) desc = 0xFFFF;
      ys[i] = (asc << 16) | desc;
    }
    charX = xs;
    charY = ys;
    dimsKnown = true;
  }
}
TOP

Related Classes of com.cburch.draw.util.EditableLabel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.