package org.geogebra.common.euclidian.draw;
import org.geogebra.common.awt.GDimension;
import org.geogebra.common.awt.GFont;
import org.geogebra.common.awt.GGraphics2D;
import org.geogebra.common.awt.GPoint;
import org.geogebra.common.awt.GRectangle;
import org.geogebra.common.awt.font.GTextLayout;
import org.geogebra.common.euclidian.Drawable;
import org.geogebra.common.euclidian.EuclidianStatic;
import org.geogebra.common.factories.AwtFactory;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.TextProperties;
import org.geogebra.common.main.App;
public abstract class CanvasDrawable extends Drawable {
private static final int HIGHLIGHT_MARGIN = 2;
// private boolean drawingOnCanvas;
private GFont labelFont;
GPoint labelSize = new GPoint(0, 0);
private int labelFontSize;
private GRectangle hitRect = AwtFactory.getPrototype().newRectangle();
int boxLeft;
int boxTop;
int boxWidth;
int boxHeight;
public static boolean isLatexString(String text) {
return text.startsWith("$") && text.trim().endsWith("$");
}
protected GDimension measureLatex(GGraphics2D g2, GeoElement geo0,
GFont font, String text) {
return drawLatex(g2, geo0, font, text, Integer.MIN_VALUE,
Integer.MIN_VALUE);
}
protected GDimension drawLatex(GGraphics2D g2, GeoElement geo0, GFont font,
String text, int x, int y) {
App app = view.getApplication();
boolean serif = false;
if (geo0 instanceof TextProperties) {
serif = ((TextProperties) geo0).isSerifFont();
}
return app.getDrawEquation().drawEquation(app, geo0, g2, x, y, text,
font, serif, geo.getObjectColor(), geo.getBackgroundColor(),
false, false, null);
}
public static GDimension measureLatex(App app,
GeoElement geo0, GFont font, String text) {
return app.getDrawEquation().measureEquation(app, geo0,
Integer.MIN_VALUE, Integer.MIN_VALUE, text, font, false);
}
protected boolean measureLabel(GGraphics2D g2, GeoElement geo0,
String text) {
boolean latex = false;
if (geo.isLabelVisible()) {
latex = isLatexString(text);
// no drawing, just measuring.
if (latex) {
GDimension d = measureLatex(g2, geo0, getLabelFont(), text);
labelSize.x = d.getWidth();
labelSize.y = d.getHeight();
} else {
g2.setFont(getLabelFont());
setLabelSize(
EuclidianStatic.drawIndexedString(view.getApplication(),
g2, text, 0, 0, false, false));
}
calculateBoxBounds(latex);
} else {
calculateBoxBounds();
}
return latex;
}
protected void calculateBoxBounds(boolean latex) {
boxLeft = xLabel + labelSize.x + 2;
boxTop = latex
? yLabel + (labelSize.y - getPreferredSize().getHeight()) / 2
: yLabel;
boxWidth = getPreferredSize().getWidth();
boxHeight = getPreferredSize().getHeight();
}
protected void calculateBoxBounds() {
boxLeft = xLabel + 2;
boxTop = yLabel;
boxWidth = getPreferredSize().getWidth();
boxHeight = getPreferredSize().getHeight();
}
protected void highlightLabel(GGraphics2D g2, boolean latex) {
if (geo.isLabelVisible() && geo.doHighlighting()) {
if (latex) {
g2.fillRect(xLabel, yLabel, labelSize.x, labelSize.y);
} else {
g2.fillRect(xLabel, yLabel + ((boxHeight - getH()) / 2),
labelSize.x, getH() + HIGHLIGHT_MARGIN);
}
}
}
protected int getTextBottom() {
return (getPreferredSize().getHeight() / 2)
+ (int) (getLabelFontSize() * 0.4);
}
protected int getH() {
return (int) (getLabelFontSize() * 1.2 + HIGHLIGHT_MARGIN);
}
protected void drawLabel(GGraphics2D g2, GeoElement geo0, String text) {
if (isLatexString(text)) {
drawLatex(g2, geo0, getLabelFont(), text, xLabel, yLabel);
} else {
g2.setPaint(geo.getObjectColor());
EuclidianStatic.drawIndexedString(view.getApplication(), g2, text,
xLabel, yLabel + getTextBottom(), false);
}
}
protected void drawOnCanvas(GGraphics2D g2, String text) {
App app = view.getApplication();
getPreferredSize();
GFont vFont = view.getFont();
setLabelFont(app.getFontCanDisplay(text, false, vFont.getStyle(),
getLabelFontSize()));
g2.setFont(getLabelFont());
g2.setStroke(EuclidianStatic.getDefaultStroke());
g2.setPaint(geo.getObjectColor());
if (geo.isVisible()) {
drawWidget(g2);
}
}
protected int getDefaultTextHeight(GGraphics2D g2) {
return getFullTextHeight(g2, "Apq");
}
protected int getFullTextHeight(GGraphics2D g2, String text) {
// make sure layout won't be null ("" makes it null).
GTextLayout layout = getLayout(g2, text, getLabelFont());
return (int) (layout.getAscent() + layout.getDescent());
}
protected int getTextHeight(GGraphics2D g2, String text) {
// make sure layout won't be null ("" makes it null).
GTextLayout layout = getTextLayout("".equals(text) ? "A" : text,
getLabelFont(), g2);
return (int) (layout.getBounds().getHeight());
}
protected int getTextDescent(GGraphics2D g2, String text) {
// make sure layout won't be null ("" makes it null).
GTextLayout layout = getLayout(g2, text, getLabelFont());
return (int) (layout.getDescent());
}
protected GTextLayout getLayout(GGraphics2D g2, String text, GFont font) {
// make sure layout won't be null ("" makes it null).
return getTextLayout("".equals(text) ? "A" : text, font, g2);
}
protected abstract void drawWidget(GGraphics2D g2);
/**
* was this object clicked at? (mouse pointer location (x,y) in screen
* coords)
*/
@Override
public boolean hit(int x, int y, int hitThreshold) {
boolean res = false;
int left = xLabel;
int top = boxTop;
int right = left + labelSize.x + boxWidth;
int bottom = top + boxHeight;
//
res = (x > left && x < right && y > top && y < bottom)
|| (x > xLabel && x < xLabel + labelSize.x && y > yLabel
&& y < yLabel + labelSize.y);
return res;
}
public GFont getLabelFont() {
return labelFont;
}
private void setLabelFont(GFont labelFont) {
this.labelFont = labelFont;
}
private void setLabelSize(GPoint labelSize) {
this.labelSize = labelSize;
}
public int getLabelFontSize() {
return labelFontSize;
}
public void setLabelFontSize(int labelFontSize) {
this.labelFontSize = labelFontSize;
}
public abstract GDimension getPreferredSize();
@Override
public boolean isInside(GRectangle rect) {
return rect.contains(labelRectangle);
}
@Override
public boolean intersectsRectangle(GRectangle rect) {
return hitRect.intersects(rect);
}
/**
* Returns false
*/
@Override
public boolean hitLabel(int x, int y) {
return false;
}
@Override
final public GeoElement getGeoElement() {
return geo;
}
@Override
public void setGeoElement(GeoElement geo) {
this.geo = geo;
}
protected abstract void showWidget();
protected abstract void hideWidget();
public void setWidgetVisible(boolean show) {
if (geo.isEuclidianVisible() && view.isVisibleInThisView(geo) && show) {
showWidget();
} else {
hideWidget();
}
}
public GRectangle getHitRect() {
return labelRectangle;
}
}