/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community 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.osedu.org/licenses/ECL-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 tufts.vue;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Point2D;
import java.awt.geom.RectangularShape;
import java.awt.geom.Point2D.Float;
import java.awt.geom.Line2D;
import java.util.Enumeration;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.Style;
import javax.swing.text.html.CSS;
import com.lightdev.app.shtm.SHTMLDocument;
import com.lightdev.app.shtm.VueStyleSheet;
import tufts.Util;
import static tufts.Util.grow;
public class LWText extends LWComponent {
protected static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(LWText.class);
public static final Object TYPE_RICHTEXT = "richTextNode";
protected transient RichTextBox richLabelBox = null;
private String richLabel = null;
//protected RectangularShape mShape;
public static final boolean WrapText = false;
protected boolean isAutoSized = false; // compute size from label &
// children
public LWText()
{
super();
// VUE-747
Float p = null;
if(VUE.getActiveViewer() != null)
{
p = VUE.getActiveViewer().getLastMapMousePoint();
}
if(p!=null)
{
setLocation(p.x, p.y);
}
// end VUE-747 mods
super.label = label; // make sure label initially set for debugging
initText();
}
public boolean isAutoSized() { return isAutoSized; }
public long getSupportedPropertyBits() {
return 0;
}
public String getRichText()
{
if (richLabelBox == null) {
Log.warn("getRichText: box was null");
return "";
} else
return richLabelBox.getRichText();
}
/** Apply all style properties from styleSource to this component */
public void copyStyle(LWComponent styleSource) {
super.copyStyle(styleSource, ~0L);
if (styleSource == null)
return;
else
this.getRichLabelBox().copyStyle(styleSource);
}
public void setRichText(String text)
{
// super.label = text;
richLabel = text;
return;
}
public LWText(String label) {
super();
super.label = label; // make sure label initially set for debugging
initText();
}
public LWText(String label, RectangularShape shape) {
// super(label, 0, 0, shape);
super.label = label; // make sure label initially set for debugging
// setAsTextNode(true);
initText();
}
private void initText() {
//enableProperty(KEY_Alignment);
//
disableProperty(LWKey.StrokeColor);
disableProperty(LWKey.StrokeStyle);
disableProperty(LWKey.StrokeWidth);
//mShape = new java.awt.geom.Rectangle2D.Float();
}
public Object getTypeToken() {
return TYPE_RICHTEXT;
}
public RichTextBox getRichLabelBox() {
return getRichLabelBox(false);
}
public RichTextBox getRichLabelBox(boolean overrideStyleSheet) {
if (this.richLabelBox == null)
{
synchronized (this) {
if (this.richLabelBox == null)
this.richLabelBox = new RichTextBox(this, this.richLabel != null ? this.richLabel : this.label);
}
}
if (VUE.getActiveViewer() != null && VUE.getActiveViewer().getFocal() instanceof LWSlide && overrideStyleSheet)
{
String fontName = (String)((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getPropertyValue(LWKey.FontName);
Integer fontSize = (Integer)((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getPropertyValue(LWKey.FontSize);
VueStyleSheet ss =(VueStyleSheet)((SHTMLDocument)richLabelBox.getDocument()).getStyleSheet();
Color color = ((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getTextColor();
final String colorString = "#" + Integer.toHexString(color.getRGB()).substring(2);
ss.addRule("body {margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;font-size:"+ fontSize +";font-family:"+ fontName +";color: "+colorString+";}");
ss.addRule("ol { margin-top:6;font-family:"+fontName+";vertical-align: middle;margin-left:30;font-size:"+ fontSize +";list-style-position:outside;}");
ss.addRule("p { margin-top:0;margin-left:0;margin-right:0;margin-bottom:0;color: "+ colorString +";}");
ss.addRule("ul { margin-top:6;font-size:"+fontSize +";margin-left:30;vertical-align: middle;list-style-position:outside;font-family:"+fontName+";}");
}else if (VUE.getActiveViewer() != null && overrideStyleSheet)
{
FontEditorPanel fep = VUE.getFormattingPanel().getTextPropsPane().getFontEditorPanel();
String fontName = fep.mFontCombo.getEditor().getItem().toString();
String fontSize = fep.mSizeField.getEditor().getItem().toString();
VueStyleSheet ss =(VueStyleSheet)((SHTMLDocument)richLabelBox.getDocument()).getStyleSheet();
Color color = fep.mTextColorButton.getColor();
final String colorString = "#" + Integer.toHexString(color.getRGB()).substring(2);
ss.addRule("body {margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;font-size:"+ fontSize +";font-family:"+ fontName +";color: "+colorString+";}");
ss.addRule("ol { margin-top:6;font-family:"+fontName+";vertical-align: middle;margin-left:30;font-size:"+ fontSize +";list-style-position:outside;}");
ss.addRule("p { margin-top:0;margin-left:0;margin-right:0;margin-bottom:0;color: "+ colorString +";}");
ss.addRule("ul { margin-top:6;font-size:"+fontSize +";margin-left:30;vertical-align: middle;list-style-position:outside;font-family:"+fontName+";}");
}
return this.richLabelBox;
}
@Override
public boolean isTextNode() {
return true;
}
public void initRichTextBoxLocation(RichTextBox activeRichTextEdit) {
activeRichTextEdit.setBoxCenter(getWidth() / 2, getHeight() / 2);
}
/** does this support user resizing? */
// TODO: change these "supports" calls to an arbitrary property list
// that could have arbitrary properties added to it by plugged-in non-standard tools
public boolean supportsUserResize() {
return (VUE.getActiveViewer().hasActiveTextEdit()) ? false : true;
}
protected void drawNode(DrawContext dc) {
// -------------------------------------------------------
// Fill the shape (if it's not transparent)
// -------------------------------------------------------
getZeroShape(); // will load super.mZeroBounds
if (isSelected() && dc.isInteractive() && dc.focal != this) {
LWPathway p = VUE.getActivePathway();
if (p != null && p.isVisible() && p.getCurrentNode() == this) {
// SPECIAL CASE: as the current element on the current pathway draws a huge semi-transparent stroke around
// it, skip drawing our fat transparent selection stroke on this node. So we just do nothing here.
} else {
dc.g.setColor(COLOR_HIGHLIGHT);
if (isTransparent()) {
dc.g.fill(grow((Rectangle2D.Float) mZeroBounds.clone(), SelectionStrokeWidth/2f));
} else {
dc.g.setStroke(new BasicStroke(getStrokeWidth() + SelectionStrokeWidth));
dc.g.draw(getZeroShape());
}
}
}
// if (imageIcon != null) { // experimental
// //imageIcon.paintIcon(null, g, (int)getX(), (int)getY());
// imageIcon.paintIcon(null, dc.g, 0, 0);
// } else
if (false && (dc.isPresenting() || isPresentationContext())) { // old-style
// "turn
// off
// the
// wrappers"
; // do nothing: no fill
} else {
final Color fillColor = getFillColor();
if (fillColor != null && fillColor.getAlpha() != 0) { // transparent
// if null
dc.g.setColor(fillColor);
// if (isZoomedFocus()) dc.g.setComposite(ZoomTransparency);
dc.g.fill(mZeroBounds);
// if (isZoomedFocus()) dc.g.setComposite(AlphaComposite.Src);
}
}
/*
* if (!isAutoSized()) { // debug g.setColor(Color.green);
* g.setStroke(STROKE_ONE); g.draw(zeroShape); } else if
* (false&&isRollover()) { // debug // temporary debug //g.setColor(new
* Color(0,0,128)); g.setColor(Color.blue); g.draw(zeroShape); } else
*/
if (getStrokeWidth() > 0 /*
* && !isPresentationContext() &&
* !dc.isPresenting()
*/) { // old
// style "turn off the wrappers" if
// (LWSelection.DEBUG_SELECTION && isSelected()) if
// (isSelected()) g.setColor(COLOR_SELECTION); else
dc.g.setColor(getStrokeColor());
dc.g.setStroke(this.stroke);
dc.g.draw(mZeroBounds);
}
// -------------------------------------------------------
// Draw the generated icon
// -------------------------------------------------------
// drawNodeDecorations(dc);
// todo: create drawLabel, drawBorder & drawBody LWComponent methods so can automatically turn this off in
// MapViewer, adjust stroke color for selection, etc.
// TODO BUG: label sometimes getting "set" w/out sending layout event -- has to do with case where we pre-fill a
// textbox with "label", and if they type nothing we don't set a label, but that's not working entirely -- it
// manages to not trigger an update event, but somehow this.label is still getting set -- maybe we have to null it
// out manually (and maybe richLabelBox also)
if (hasLabel() && this.richLabelBox != null
&& this.richLabelBox.getParent() == null) {
// if parent is not null, this box is an active edit on the map
// and we don't want to paint it here as AWT/Swing is handling
// that at the moment (and at a possibly slightly different offset)
drawLabel(dc);
}
}
public final int getAverageTextSize()
{
SHTMLDocument doc = (SHTMLDocument)this.getRichLabelBox().getDocument();
Element paragraphElement = doc.getParagraphElement(1);
if (paragraphElement.getName().equals("p-implied")) //we're in a list item
paragraphElement = paragraphElement.getParentElement();
AttributeSet paragraphAttributeSet = paragraphElement.getAttributes();
Element charElem = null;
charElem = doc.getCharacterElement(1);
AttributeSet charSet = charElem.getAttributes();
Enumeration characterAttributeEnum = charSet.getAttributeNames();
Enumeration elementEnum = paragraphAttributeSet.getAttributeNames();
while (elementEnum.hasMoreElements())
{
Object o = elementEnum.nextElement();
if ((o.toString().equals("font-size")) ||(o.toString().equals("size")))
{
int i = Integer.parseInt(paragraphAttributeSet.getAttribute(o).toString());
return i;
}
}
while (characterAttributeEnum.hasMoreElements())
{
Object o = characterAttributeEnum.nextElement();
if ((o.toString().equals("font-size")) ||(o.toString().equals("size")))
{
int i = Integer.parseInt(charSet.getAttribute(o).toString());
return i;
}
}//done looking at character attributes
return 12;
}
@Override protected void drawImpl(DrawContext dc)
{
if (dc.isLODEnabled()) {
// if net on-screen point size is less than 5 for all text, we allow drawing
// with reduced LOD (level-of-detail)
final float renderScale = (float) dc.getAbsoluteScale();
final float renderFont = getAverageTextSize() * renderScale;
if (renderFont < 5) {
drawTextWithReducedLOD(dc, renderScale);
return; // WE'RE DONE
}
}
// If we're filtered, parent won't have drawn us.
drawNode(dc);
}
private final static Line2D.Float xline = new Line2D.Float();
private void drawTextWithReducedLOD(final DrawContext dc, final float renderScale) {
if (isSelected()) {
dc.g.setColor(COLOR_SELECTION);
dc.setAbsoluteStroke(1);
} else {
dc.g.setStroke(STROKE_ONE);
dc.g.setColor(Color.black);
}
dc.g.draw(getZeroShape());
// imperfect, but good enough -- view in panner to test
final float inc = 3f / renderScale;
final float screenTall = this.height - inc;
final float screenWide = this.width;
xline.setLine(inc*2, 0, screenWide-inc*2, 0);
for (float y = inc*2; y < screenTall; y += inc) {
xline.y1 = xline.y2 = y;
dc.g.draw(xline);
}
}
//private static final Shape mShape = new java.awt.geom.Rectangle2D.Float();
/** Draw without rendering any textual glyphs, possibly without children, possibly as a rectanlge only */
private void drawNodeWithReducedLOD(final DrawContext dc, final float renderScale)
{
//=============================================================================
// DRAW FAST (with little or no detail)
//=============================================================================
// Level-Of-Detail rendering -- increases speed when lots of nodes rendered
// all we do is fill the shape
boolean hasVisibleFill = true;
if (isSelected()) {
dc.g.setColor(COLOR_SELECTION);
} else {
final Color renderFill = getRenderFillColor(dc);
// if (isTransparent() || renderFill.equals(getParent().getRenderFillColor(dc)))
hasVisibleFill = false;
}
if (this.height * renderScale > 5) {
// MEDIUM LEVEL OF DETAIL: retain shape & draw children
drawLODTextLine(dc);
} else {
// LOWEST LEVEL OF DETAIL -- shape is always a rectangle, don't draw children
drawLODTextLine(dc);
}
}
private void drawLODTextLine(final DrawContext dc) {
final int hh = (int) ((getHeight() / 2f) + 0.5f);
int height = (int) getHeight();
//dc.setAntiAlias(false); // too crappy
dc.g.setStroke(STROKE_SEVEN);
dc.g.setColor(Color.black);
double zoomFactor;
if (VUE.getActiveViewer()!=null)
zoomFactor = VUE.getActiveViewer().getZoomFactor();
else
zoomFactor =1;
int scaledHeight =height;
int line =0;
while (line < scaledHeight)
{
dc.g.drawLine(0, line, (int) (getLabelBox().getWidth() * zoomFactor), line);
line+=100;
}
}
protected void drawLabel(DrawContext dc) {
//float lx = 0;//relativeLabelX();
//float ly = 0;//relativeLabelY();
//dc.g.translate(lx, ly);
// if (DEBUG.CONTAINMENT) System.out.println("*** " + this + " drawing
// label at " + lx + "," + ly);
this.richLabelBox.draw(dc);
//dc.g.translate(-lx, -ly);
// todo: this (and in LWLink) is a hack -- can't we
// do this relative to the node?
// this.labelBox.setMapLocation(getX() + lx, getY() + ly);
}
protected float relativeLabelX() {
// Doing this risks slighly moving the damn TextBox just as you edit it.
final float offset = (this.width - getTextSize().width) / 2;
return offset + 1;
}
protected float relativeLabelY() {
// Doing this risks slighly moving the damn TextBox just as you edit it.
// Tho querying the underlying TextBox for it's size every time
// we repaint this object is pretty gross also (e.g., every drag)
return (this.height - getTextSize().height) / 2;
}
/**
* @return the current size of the label object, providing a margin of error
* on the width given sometime java bugs in computing the accurate
* length of a a string in a variable width font.
*/
private static final float TextWidthFudgeFactor = 1; // off for debugging
// (Almost uneeded
// in new Mac JVM's)
protected Size getMinimumTextSize()
{
Size s = new Size(getRichLabelBox().getMinimumSize());
s.width *= TextWidthFudgeFactor;
s.width += 3;
return s;
}
protected Size getTextSize() {
Size s = new Size(getRichLabelBox().getPreferredSize());
s.width *= TextWidthFudgeFactor;
s.width += 3;
return s;
}
@Override
public float getWidth() {
if (richLabelBox == null)
return super.getWidth();
else
{
SHTMLDocument doc = (SHTMLDocument)richLabelBox.getDocument();
if (doc !=null && doc.isEditing())
return (float)richLabelBox.getUnscaledWidth();
else
return richLabelBox.getWidth();
}
}
public float getHeight()
{
//The line height is always off by a 1 line..
if (richLabelBox == null)
{
return super.getHeight();
}
else
{
SHTMLDocument doc = (SHTMLDocument)richLabelBox.getDocument();
if (doc !=null && doc.isEditing())
return (float)richLabelBox.getUnscaledHeight();
else
return richLabelBox.getHeight();
}
}
@Override
public float getLocalWidth() { return (float) (getWidth() * getScale()); }
@Override
public float getLocalHeight() { return (float) (getHeight() * getScale()); }
@Override
public float getMapWidth() { return (float) (getWidth() * getMapScale()); }
@Override
public float getMapHeight() { return (float) (getHeight() * getMapScale()); }
@Override
public float getLocalBorderWidth() { return (float) ((getWidth() + mStrokeWidth.get()) * getScale()); }
@Override
public float getLocalBorderHeight() { return (float) ((getHeight() + mStrokeWidth.get()) * getScale()); }
private boolean inLayout = false;
/**
* Duplicate this node.
*
* @return the new node -- will have the same style (visible properties) of
* the old node
*/
@Override
public LWComponent duplicate(CopyContext cc) {
// LWText newNode = (LWNode) super.duplicate(cc);
boolean isPatcherOwner = false;
if (cc.patcher == null && cc.dupeChildren && hasChildren()) {
// Normally VUE Actions (e.g. Duplicate, Copy, Paste)
// provide a patcher for duplicating a selection of
// objects, but anyone else may not have provided one.
// This will take care of arbitrary single instances of
// duplication, including duplicating an entire Map.
cc.patcher = new LinkPatcher();
isPatcherOwner = true;
}
final LWText containerCopy = (LWText) super.duplicate(cc);
java.awt.Dimension d = getRichLabelBox().getPreferredSize();
containerCopy.getRichLabelBox().setSize(d);
//containerCopy.setLabel0(getRichLabelBox().getText(), true);
// containerCopy.getRichLabelBox().setText(getRichLabelBox().getRichText());
//containerCopy.getRichLabelBox().setText(this.getRichText());
//containerCopy.getRichLabelBox().setText(this.getRichLabelBox().getRichText());
if (isPatcherOwner)
cc.patcher.reconnectLinks();
//containerCopy.setSize(getWidth(), getHeight());
return containerCopy;
}
public void setStyle(LWComponent parentStyle)
{
if (richLabelBox != null)
richLabelBox.overrideTextColor(parentStyle.getTextColor());
}
@Override
public void setXMLlabel(String text)
{
setLabel(text);
}
@Override
public void setLabel(String label)
{
setLabel0(label, true);
}
/**
* Called directly by TextBox after document edit with setDocument=false,
* so we don't attempt to re-update the TextBox, which has just been
* updated.
*/
@Override
void setLabel0(String newLabel, boolean setDocument)
{
Object old = this.label;
if (this.label == newLabel)
return;
if (this.label != null && this.label.equals(newLabel))
return;
if (newLabel == null || newLabel.length() == 0) {
this.label = null;
if (richLabelBox != null)
richLabelBox.setText("");
} else {
this.label = newLabel;
// todo opt: only need to do this if node or link (LWImage?)
// Handle this more completely -- shouldn't need to create
// label box at all -- why can't do entirely lazily?
if (this.richLabelBox == null) {
// figure out how to skip this:
//getLabelBox();
} else if (setDocument) {
getRichLabelBox().setText(newLabel);
// System.out.println("SETTING DOCUMENT ON RESTORE : " + newLabel);
}
}
layout();
notify(LWKey.Label, old);
}
@Override
protected void layoutImpl(Object triggerKey) {
if (triggerKey == LWKey.Alignment) {
// LWText doesn't use the aligment property on a whole-component bases: ignore this
// layout request if we ever get it.
return;
}
layout(triggerKey, new Size(getWidth(), getHeight()), null);
}
@Override protected void setSizeImpl(float w, float h, boolean internal) {
if (DEBUG.LAYOUT) out("*** setSize " + w + "x" + h);
if (isAutoSized() && (w > this.width || h > this.height)) // does this
// handle
// scaling?
setAutomaticAutoSized(false);
layout(LWKey.Size, new Size(getWidth(), getHeight()), new Size(w, h));
}
/**
* For triggering automatic shifts in the auto-size bit based on a call to
* setSize or as a result of a layout
*/
private void setAutomaticAutoSized(boolean tv) {
if (isOrphan()) // if this is during a restore, don't do any automatic
// auto-size computations
return;
if (isAutoSized == tv)
return;
if (DEBUG.LAYOUT)
out("*** setAutomaticAutoSized " + tv);
isAutoSized = tv;
}
/**
* @param triggerKey -
* the property change that triggered this layout
* @param curSize -
* the current size of the node
* @param request -
* the requested new size of the node
*/
protected void layout(Object triggerKey, Size curSize, Size request) {
if (inLayout) {
if (DEBUG.Enabled) {
if (DEBUG.META || DEBUG.LAYOUT)
new Throwable("ALREADY IN LAYOUT " + this).printStackTrace();
else
Log.warn("already in layout: " + Util.tag(this) + " id#" + getID());
}
return;
}
inLayout = true;
if (DEBUG.LAYOUT) {
String msg = "*** LAYOUT, trigger=" + triggerKey + " cur="
+ curSize + " request=" + request + " isAutoSized="
+ isAutoSized();
if (DEBUG.META)
Util.printClassTrace("tufts.vue.LW", msg + " " + this);
else
out(msg);
}
if (DEBUG.LAYOUT
&& getLabelBox().getHeight() != getLabelBox()
.getPreferredSize().height) {
// NOTE: prefHeight often a couple of pixels less than getHeight
System.err.println("prefHeight != height in " + this);
System.err.println("\tpref="
+ getLabelBox().getPreferredSize().height);
System.err.println("\treal=" + getLabelBox().getHeight());
}
// The current width & height is at this moment still a
// "request" size -- e.g., the user may have attempted to drag
// us to a size smaller than our minimum size. During that
// operation, the size of the node is momentarily set to
// whatever the user requests, but then is immediately laid
// out here, during which we will revert the node size to the
// it's minimum size if bigger than the requested size.
// -------------------------------------------------------
// If we're a rectangle (rect or round rect) we use
// layoutBoxed, if anything else, we use layoutCeneter
// -------------------------------------------------------
final Size min;
min = layoutBoxed(request, curSize, triggerKey);
if (request == null)
request = curSize;
if (DEBUG.LAYOUT)
out("*** layout computed minimum=" + min);
// If the size gets set to less than or equal to
// minimize size, lock back into auto-sizing.
// if (request.height <= min.height && request.width <= min.width)
// setAutomaticAutoSized(true);
final float newWidth;
float newHeight;
// we always compute the minimum size, and
// never let us get smaller than that -- so
// only use given size if bigger than min size.
if (request.width > min.width)
newWidth = request.width;
else
newWidth = min.width;
//MK
newHeight = Math.max(min.height,request.height);
this.getRichLabelBox();
/*if (richLabelBox !=null )
{
newHeight = Math.max(newHeight,richLabelBox.getHeight());
}*/
// newHeight = request.height;
//newHeight = min.height;
//System.out.println("MIN.WIDTH : " + min.width);
// System.out.println("MIN.HEIGHT : " + min.height);
//System.out.println("NEW WIDTH : " + newWidth);
// System.out.println("NEW HEIGHT : " + newHeight);
setSizeNoLayout(newWidth, newHeight);
// layout label last in case size is bigger than min and label is
// centered
//layoutBoxed_label();
if (richLabelBox != null)
richLabelBox.setBoxLocation(0,0);
//richLabelBox.setBoxLocation(relativeLabelX(), relativeLabelY());
if (isLaidOut()) {
// todo: should only need to do if size changed
this.parent.layout();
//System.out.println("layout parent");
}
if (!isAutoSized())
notify(LWKey.Size, min); // todo perf: can we optimize this event out?
//System.out.println("OUT OF LAYOUT*************");
inLayout = false;
}
private void setSizeNoLayout(float w, float h) {
if (DEBUG.LAYOUT) out("*** setSizeNoLayout " + w + "x" + h);
setSize(w, h);
richLabelBox.setSize(w,h);
//mShape.setFrame(0, 0, getWidth(), getHeight());
}
private transient Point2D.Float mLabelPos = new Point2D.Float(); // for
// use
// with
// irregular
// node
// shapes
private Size layoutBoxed(Size request, Size oldSize, Object triggerKey) {
final Size min;
min = layoutBoxed_vanilla(request);
return min;
}
private static final int EdgePadY = 0; // Was 3 in VUE 1.5
private static final int LabelPadLeft = 0; // Was 6 in VUE 1.5; fixed
// distance to right of
// iconMargin dividerLine
/** @return new minimum size of node */
private Size layoutBoxed_vanilla(final Size request) {
final Size min = new Size();
final Size text = getMinimumTextSize();
min.width = text.width;
min.height = EdgePadY + text.height + EdgePadY;
// System.out.println("MIN : " + min.height + " << " + text.height);
//min.height = Math.max(min.height, text.height);
//System.out.println("Text.height : " + text.height);
// *** set icon Y position in all cases to a centered vertical
// position, but never such that baseline is below bottom of
// first icon -- this is tricky tho, as first icon can move
// down a bit to be centered with the label!
min.width += LabelPadLeft;
min.width = Math.max(min.width,text.width);
//System.out.println("Min.Wdith : " + min.width);
//System.out.println("Text.Width : " + text.width);
//System.out.println("Text.Min.Width : " + getMinimumTextSize().width);
return min;
}
@Override
public String getDisplayLabel() {
String txt;
if (richLabelBox == null) {
txt = "";
} else {
txt = richLabelBox.getText();
txt = txt.replaceAll("\\s+", " ");
}
return txt;
}
@Override
public String toString() {
String txt;
if (richLabelBox == null)
txt = "<null-RichTextBox>";
else {
txt = richLabelBox.getText();
txt = txt.replaceAll("\\s+", " ");
}
return "LWText[" + getID() + "; " + txt + "]";
}
public void setRichLabelBox(RichTextBox richLabelBox) {
this.richLabelBox = richLabelBox;
}
}