/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.euclidian.draw; import org.geogebra.common.awt.GColor; import org.geogebra.common.awt.GFont; import org.geogebra.common.awt.GGraphics2D; import org.geogebra.common.awt.GRectangle; import org.geogebra.common.euclidian.BoundingBox; import org.geogebra.common.euclidian.Drawable; import org.geogebra.common.euclidian.EuclidianView; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.Matrix.Coords; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoText; import org.geogebra.common.kernel.kernelND.GeoPointND; import org.geogebra.common.main.App; /** * Drawable representation of text * * @author Markus */ public final class DrawText extends Drawable { /** * color used to draw rectangle around text when highlighted */ public static final GColor HIGHLIGHT_COLOR = GColor.LIGHT_GRAY; // private static final int SELECTION_DIAMETER_ADD = 4; // private static final int SELECTION_OFFSET = SELECTION_DIAMETER_ADD / 2; private GeoText text; private boolean isVisible, isLaTeX; private int fontSize = -1; private int fontStyle = -1; private boolean serifFont; private GFont textFont; private GeoPointND loc; // text location // private Image eqnImage; private int oldXpos, oldYpos; private boolean needsBoundingBoxOld; /** * Creates new DrawText * * @param view * view * @param text * text */ public DrawText(EuclidianView view, GeoText text) { this.view = view; this.text = text; geo = text; textFont = view.getApplication().getPlainFontCommon() .deriveFont(GFont.PLAIN, view.getFontSize()); // this is needed as (bold) LaTeX texts are created with isLaTeX = false // at this stage updateStrokes(text); update(); } @Override final public void update() { isVisible = geo.isEuclidianVisible(); if (!isVisible && !text.isNeedsUpdatedBoundingBox()) { // Corner[Element[text return; } if (isLaTeX) { updateStrokes(text); } if (isLaTeX) { updateStrokes(text); } String newText = text.getTextString(); boolean textChanged = labelDesc == null || !labelDesc.equals(newText) || isLaTeX != text.isLaTeX() || text.isNeedsUpdatedBoundingBox() != needsBoundingBoxOld; labelDesc = newText; isLaTeX = text.isLaTeX(); needsBoundingBoxOld = text.isNeedsUpdatedBoundingBox(); // compute location of text if (text.isAbsoluteScreenLocActive()) { xLabel = text.getAbsoluteScreenLocX(); yLabel = text.getAbsoluteScreenLocY(); } else { loc = text.getStartPoint(); if (loc == null) { xLabel = (int) view.getXZero(); yLabel = (int) view.getYZero(); } else { if (!loc.isDefined()) { isVisible = false; return; } // looks if it's on view Coords p = view.getCoordsForView(loc.getInhomCoordsInD3()); if (!Kernel.isZero(p.getZ())) { isVisible = false; return; } xLabel = view.toScreenCoordX(p.getX()); yLabel = view.toScreenCoordY(p.getY()); } xLabel += text.labelOffsetX; yLabel += text.labelOffsetY; text.setTotalWidth((int) labelRectangle.getWidth()); text.setTotalHeight((int) labelRectangle.getHeight()); } boolean positionChanged = xLabel != oldXpos || yLabel != oldYpos; oldXpos = xLabel; oldYpos = yLabel; boolean fontChanged = doUpdateFontSize(); // some commented code for LaTeX speedup removed in r22321 // We need check for null bounding box because of // SetValue[text,Text["a",(1,1)]] makes it null if (text.isNeedsUpdatedBoundingBox() && (textChanged || positionChanged || fontChanged || text.getKernel().getForceUpdatingBoundingBox() || text.getBoundingBox() == null)) { // ensure that bounding box gets updated by drawing text once if (isLaTeX) { drawMultilineLaTeX(view.getTempGraphics2D(textFont), textFont, geo.getObjectColor(), view.getBackgroundCommon()); } else { drawMultilineText(view.getTempGraphics2D(textFont), textFont); } // update corners for Corner[] command double xRW = view.toRealWorldCoordX(labelRectangle.getX()); double yRW = view.toRealWorldCoordY(labelRectangle.getY()); text.setBoundingBox(xRW, yRW, labelRectangle.getWidth() * view.getInvXscale(), -labelRectangle.getHeight() * view.getInvYscale()); } } @Override final public void draw(GGraphics2D g2) { if (isVisible) { GColor bg = geo.getBackgroundColor(); if (bg != null) { // needed to calculate labelRectangle if (isLaTeX) { drawMultilineLaTeX(view.getTempGraphics2D(textFont), textFont, geo.getObjectColor(), view.getBackgroundCommon()); } else { drawMultilineText(view.getTempGraphics2D(textFont), textFont); } g2.setStroke(objStroke); g2.setPaint(bg); g2.fill(labelRectangle); } if (isLaTeX) { g2.setPaint(geo.getObjectColor()); g2.setFont(textFont); g2.setStroke(objStroke); // needed eg for \sqrt drawMultilineLaTeX(g2, textFont, geo.getObjectColor(), bg != null ? bg : view.getBackgroundCommon()); } else { g2.setPaint(geo.getObjectColor()); // g2.setFont(textFont); drawMultilineText(g2, textFont); } // draw label rectangle if (geo.doHighlighting()) { g2.setStroke(objStroke); g2.setPaint(HIGHLIGHT_COLOR); g2.draw(labelRectangle); } } } /** * was this object clicked at? (mouse pointer location (x,y) in screen * coords) */ @Override final public boolean hit(int x, int y, int hitThreshold) { return super.hitLabel(x, y); } @Override final public boolean isInside(GRectangle rect) { return rect.contains(labelRectangle); } @Override public boolean intersectsRectangle(GRectangle rect) { return labelRectangle.intersects(rect); } /** * Returns false */ @Override public boolean hitLabel(int x, int y) { return false; } @Override final public GeoElement getGeoElement() { return geo; } @Override final public void setGeoElement(GeoElement geo) { this.geo = geo; } private boolean doUpdateFontSize() { // text's font size is relative to the global font size int newFontSize = (int) Math.max(4, view.getFontSize() * text.getFontSizeMultiplier()); int newFontStyle = text.getFontStyle(); boolean newSerifFont = text.isSerifFont(); if (text.getTextString() != null && textFont.canDisplayUpTo(text.getTextString()) != -1 || fontSize != newFontSize || fontStyle != newFontStyle || newSerifFont != serifFont) { super.updateFontSize(); fontSize = newFontSize; fontStyle = newFontStyle; serifFont = newSerifFont; // if (isLaTeX) { // //setEqnFontSize(); // } else { App app = view.getApplication(); textFont = app.getFontCanDisplay(text.getTextString(), serifFont, fontStyle, fontSize); // } return true; } return false; } /** * Returns the bounding box of this Drawable in screen coordinates. */ @Override final public GRectangle getBounds() { if (!geo.isDefined() || !geo.isEuclidianVisible()) { return null; } return labelRectangle; } @Override public BoundingBox getBoundingBox() { // TODO Auto-generated method stub return null; } @Override public void updateBoundingBox() { // TODO Auto-generated method stub } }