package org.xmind.ui.internal.figures; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.swt.graphics.Font; import org.xmind.gef.draw2d.RotatableWrapLabel; import org.xmind.gef.draw2d.geometry.PrecisionDimension; import org.xmind.gef.draw2d.geometry.PrecisionRectangle; public class BoundaryTitleFigure extends RotatableWrapLabel { private static final float PADDING = 1.5f; private static final float H_MARGIN = 8.0f; private static final float V_MARGIN = 3.0f; private static final String NULLSTR = ""; //$NON-NLS-1$ private static final String ONESPACE = " "; //$NON-NLS-1$ private BoundaryFigure boundary; private PrecisionRectangle textArea; public BoundaryTitleFigure() { } public BoundaryTitleFigure(String text) { super(text); } public BoundaryTitleFigure(int renderStyle) { super(renderStyle); } public BoundaryTitleFigure(String text, int renderStyle) { super(text, renderStyle); } protected void flushCaches() { super.flushCaches(); textArea = null; } private int getPreferenceWHint(int wHint) { if (getBoundary() != null) { return wHint > getBoundary().getBounds().width ? getBoundary().getBounds().width : wHint; } return wHint; } protected PrecisionRectangle getTextArea(int wHint) { wHint = getPreferenceWHint(wHint); receiveWidthCaches(wHint); if (textArea == null) { PrecisionDimension size = calculateTextSize(wHint); textArea = new PrecisionRectangle(); float h_margin = H_MARGIN; float v_margin = V_MARGIN; int height = getFont().getFontData()[0].getHeight(); if (height > 30) h_margin = h_margin + 5; textArea.width = size.width + PADDING * 2 + h_margin; textArea.height = size.height + PADDING * 2 + v_margin; textArea.x = -(textArea.width / 2); textArea.y = -(textArea.height / 2); } return textArea; } @Override protected String calculateAppliedText(double wHint) { String theText = getText(); if (wHint <= 5 || theText.length() == 0) return theText; Font f = getFont(); String[] lines = forceSplitText(theText, f, wHint); return getForceSplitText(lines); } private String[] forceSplitText(String theText, Font f, double wHint) { wHint = wHint - 5; List<String> buffer = new ArrayList<String>(); theText = theText.trim(); if (getShowLooseTextSize(theText, f).width < wHint) { buffer.add(theText); return buffer.toArray(new String[buffer.size()]); } String cachedString = NULLSTR; String appendString = NULLSTR; String[] lines = theText.split(ONESPACE); int i = 0; do { if (lines[i].equals(NULLSTR)) { lines[i] = ONESPACE; } if (getShowLooseTextSize(lines[i], f).width >= wHint) { if (cachedString.trim() != NULLSTR) { buffer.add(cachedString.trim()); cachedString = NULLSTR; } cachedString = truncate(lines[i], buffer, wHint, f); i++; continue; } appendString = cachedString + lines[i]; if (getShowLooseTextSize(appendString, f).width >= wHint) { if (cachedString.trim() != NULLSTR) { buffer.add(cachedString.trim()); } cachedString = lines[i]; } else { cachedString = cachedString + lines[i]; } cachedString += ONESPACE; i++; } while (i < lines.length); if (cachedString.trim() != NULLSTR) { buffer.add(cachedString.trim()); } return buffer.toArray(new String[buffer.size()]); } private String truncate(String s, List<String> buffer, double wHint, Font f) { String token = s; while (wHint > 0 && !token.equals(NULLSTR)) { boolean isLastSnip = true; String current = token; while (getShowLooseTextSize(current, f).width >= wHint) { isLastSnip = false; current = current.substring(0, current.length() - 1); } if (getShowLooseTextSize(current, f).width < wHint && !isLastSnip) { buffer.add(token.substring(0, current.length()).trim()); token = token.substring(current.length()); } else return token; } return token; } private String getForceSplitText(String[] lines) { StringBuffer sb = new StringBuffer(); for (String line : lines) sb.append(line + '\n'); if (sb.charAt(sb.length() - 1) == '\n') sb.deleteCharAt(sb.length() - 1); return sb.toString(); } private Dimension getShowLooseTextSize(String s, Font f) { int textCase = getTextCase(); s = getShowText(s, textCase); return getLooseTextSize(s, f); } private BoundaryFigure getBoundary() { return boundary; } public void setBoundary(IFigure boundary) { this.boundary = (BoundaryFigure) boundary; } }