/** * Creates a reader that breaks an input text to fit in a given width. * * @param reader Reader of the input text * @param gc The graphic context that defines the currently used font sizes * @param maxLineWidth The max width (pixes) where the text has to fit in */ public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) { fReader = new BufferedReader(reader); fGC = gc; fMaxWidth = maxLineWidth; fOffset = 0; fLine = null; fLineBreakIterator = BreakIterator.getLineInstance(); }
public void doTest() { BreakIterator brkIter; switch (type) { case BreakIterator.KIND_CHARACTER: brkIter = BreakIterator.getCharacterInstance(locale); break; case BreakIterator.KIND_WORD: brkIter = BreakIterator.getWordInstance(locale); break; case BreakIterator.KIND_LINE: brkIter = BreakIterator.getLineInstance(locale); break; case BreakIterator.KIND_SENTENCE: brkIter = BreakIterator.getSentenceInstance(locale); break; default: errln("Unsupported break iterator type " + type); return; } brkIter.setText(text); int[] foundOffsets = new int[maxOffsetCount]; int offset, foundOffsetsCount = 0; // do forwards iteration test while (foundOffsetsCount < maxOffsetCount && (offset = brkIter.next()) != BreakIterator.DONE) { foundOffsets[foundOffsetsCount++] = offset; } if (!offsetsMatchExpected(foundOffsets, foundOffsetsCount)) { // log error for forwards test String textToDisplay = (text.length() <= 16) ? text : text.substring(0, 16); errln( "For type " + type + " " + locale + ", text \"" + textToDisplay + "...\"" + "; expect " + expectOffsets.length + " offsets:" + formatOffsets(expectOffsets, expectOffsets.length) + "; found " + foundOffsetsCount + " offsets fwd:" + formatOffsets(foundOffsets, foundOffsetsCount)); } else { // do backwards iteration test --foundOffsetsCount; // back off one from the end offset while (foundOffsetsCount > 0) { offset = brkIter.previous(); if (offset != foundOffsets[--foundOffsetsCount]) { // log error for backwards test String textToDisplay = (text.length() <= 16) ? text : text.substring(0, 16); errln( "For type " + type + " " + locale + ", text \"" + textToDisplay + "...\"" + "; expect " + expectOffsets.length + " offsets:" + formatOffsets(expectOffsets, expectOffsets.length) + "; found rev offset " + offset + " where expect " + foundOffsets[foundOffsetsCount]); break; } } } }
/** A Figure with an embedded TextFlow within a FlowPage that contains text. */ public class LabelFigure extends ReportElementFigure { private static final Dimension ZERO_DIMENSION = new Dimension(); private TextFlow label; private FlowPage flowPage; private String display; private Dimension recommendSize = new Dimension(); private boolean isFixLayout; /** * Creates a new LabelFigure with a default MarginBorder size 3 and a FlowPage containing a * TextFlow with the style WORD_WRAP_SOFT. */ public LabelFigure() { this(1); } /** @return */ public String getDisplay() { return display; } /** * Creates a new LabelFigure with a MarginBorder that is the given size and a FlowPage containing * a TextFlow with the style WORD_WRAP_HARD. * * @param borderSize the size of the MarginBorder */ public LabelFigure(int borderSize) { setBorder(new MarginBorder(borderSize)); label = new TextFlow() { public void postValidate() { if (DesignChoiceConstants.DISPLAY_BLOCK.equals(display) || DesignChoiceConstants.DISPLAY_INLINE.equals(display)) { List list = getFragments(); FlowBox box; int left = Integer.MAX_VALUE, top = left; int bottom = Integer.MIN_VALUE; for (int i = 0; i < list.size(); i++) { box = (FlowBox) list.get(i); left = Math.min(left, box.getX()); top = Math.min(top, box.getBaseline() - box.getAscent()); bottom = Math.max(bottom, box.getBaseline() + box.getDescent()); } int width = LabelFigure.this.getClientArea().width; if (isFixLayout) { int maxWidth = calcMaxSegment() - getInsets().getWidth(); width = Math.max(width, maxWidth); } setBounds( new Rectangle( left, top, width, Math.max(LabelFigure.this.getClientArea().height, bottom - top))); if (isFixLayout()) { Figure child = (Figure) getParent(); Rectangle rect = child.getBounds(); child.setBounds(new Rectangle(rect.x, rect.y, width, rect.height)); } list = getChildren(); for (int i = 0; i < list.size(); i++) { ((FlowFigure) list.get(i)).postValidate(); } } else { super.postValidate(); } } }; label.setLayoutManager(new ParagraphTextLayout(label, ParagraphTextLayout.WORD_WRAP_SOFT)); flowPage = new FlowPage(); flowPage.add(label); setLayoutManager(new StackLayout()); add(flowPage); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.IFigure#getPreferredSize(int, int) */ private Dimension getPreferredSize( int wHint, int hHint, boolean isFix, boolean forceWidth, boolean forceHeight) { int rx = recommendSize != null ? recommendSize.width : 0; int ry = recommendSize != null ? recommendSize.height : 0; rx = getRealRecommendSizeX(rx, wHint); Dimension dim = null; if (isFix) { int tempHint = wHint; int maxWidth = calcMaxSegment(); if (wHint < maxWidth && !forceWidth) { tempHint = maxWidth; } dim = super.getPreferredSize(tempHint <= 0 ? -1 : tempHint, hHint); } // only when display is block, use passed in wHint else if (DesignChoiceConstants.DISPLAY_BLOCK.equals(display)) { dim = super.getPreferredSize(rx == 0 ? wHint : rx, hHint); } else { dim = super.getPreferredSize(rx == 0 ? -1 : rx, hHint); // fix bug 271116. if (rx == 0 && wHint > 0 && dim.width > wHint) { dim = super.getPreferredSize(wHint, hHint); } } return new Dimension(Math.max(dim.width, rx), Math.max(dim.height, ry)); } public Dimension getPreferredSize(int wHint, int hHint) { return getPreferredSize(wHint, hHint, false, false, false); } public Dimension getMinimumSize(int wHint, int hHint) { return getMinimumSize(wHint, hHint, false, false, false); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.Figure#getMinimumSize(int, int) */ private Dimension getMinimumSize( int wHint, int hHint, boolean isFix, boolean forceWidth, boolean forceHeight) { if (DesignChoiceConstants.DISPLAY_NONE.equals(display)) { return ZERO_DIMENSION; } int rx = recommendSize != null ? recommendSize.width : 0; int ry = recommendSize != null ? recommendSize.height : 0; rx = getRealRecommendSizeX(rx, wHint); if (wHint == -1 && hHint == -1) { int maxWidth = calcMaxSegment(); // use recommend size if specified, otherwise use max segment size Dimension dim = super.getMinimumSize(rx == 0 ? maxWidth : rx, -1); dim.height = Math.max(dim.height, Math.max(getInsets().getHeight(), ry)); return dim; } Dimension dim; // return the true minimum size with minimum width; if (isFix) { int tempHint = wHint; int maxWidth = calcMaxSegment(); if (wHint < maxWidth && !forceWidth) { tempHint = maxWidth; } dim = super.getMinimumSize(tempHint <= 0 ? -1 : tempHint, hHint); return new Dimension(Math.max(dim.width, rx), Math.max(dim.height, ry)); } else { dim = super.getMinimumSize(rx == 0 ? -1 : rx, hHint); } if (dim.width < wHint) { return new Dimension(Math.max(dim.width, rx), Math.max(dim.height, ry)); } dim = super.getMinimumSize(wHint, hHint); return new Dimension(Math.max(dim.width, rx), Math.max(dim.height, ry)); } private int getRealRecommendSizeX(int rx, int wHint) { if (rx > 0 || wHint == -1) { return rx; } if (getParent() != null && getParent().getLayoutManager() != null) { ReportItemConstraint constraint = (ReportItemConstraint) getParent().getLayoutManager().getConstraint(this); if (constraint != null && constraint.getMeasure() != 0 && DesignChoiceConstants.UNITS_PERCENTAGE.equals(constraint.getUnits())) { // compute real percentag recommend size rx = (int) constraint.getMeasure() * wHint / 100; ; } } return rx; } private int calcMaxSegment() { String text = label.getText(); char[] chars = text.toCharArray(); int position = 0; int maxWidth = 0; for (int i = 0; i < chars.length; i++) { if (canBreakAfter(chars[i])) { int tempMaxWidth; String st = text.substring(position, i + 1); tempMaxWidth = FigureUtilities.getStringExtents(st, getFont()).width; if (tempMaxWidth > maxWidth) { maxWidth = tempMaxWidth; } position = i; } } String st = text.substring(position, chars.length); int tempMaxWidth = FigureUtilities.getStringExtents(st, getFont()).width; if (tempMaxWidth > maxWidth) { maxWidth = tempMaxWidth; } return maxWidth + getInsets().getWidth(); } static final BreakIterator LINE_BREAK = BreakIterator.getLineInstance(); static boolean canBreakAfter(char c) { boolean result = Character.isWhitespace(c) || c == '-'; if (!result && (c < 'a' || c > 'z')) { // chinese characters and such would be caught in here // LINE_BREAK is used here because INTERNAL_LINE_BREAK might be in // use LINE_BREAK.setText(c + "a"); // $NON-NLS-1$ result = LINE_BREAK.isBoundary(1); } return result; } private static int getMinimumFontSize(Font ft) { if (ft != null && ft.getFontData().length > 0) { return ft.getFontData()[0].getHeight(); } return 0; } /** * Since Eclipse TextFlow figure ignore the trailing /r/n for calculating the client size, we must * append the extra size ourselves. * * @return dimension for the client area used by the editor. */ public Rectangle getEditorArea() { Rectangle rect = getClientArea().getCopy(); String s = getText(); int count = 0; if (s != null && s.length() > 1) { for (int i = s.length() - 2; i >= 0; i -= 2) { if ("\r\n".equals(s.substring(i, i + 2))) // $NON-NLS-1$ { count++; } else { break; } } } int hh = getMinimumFontSize(getFont()); rect.height += count * hh + ((count == 0) ? 0 : (hh / 2)); return rect; } /** * Sets the recommended size. * * @param recommendSize */ public void setRecommendSize(Dimension recommendSize) { this.recommendSize = recommendSize; } /** * Gets the recommended size. * * @return */ public Dimension getRecommendSize() { return recommendSize; } /** * Sets the display property of the Label. * * @param display the display property. this should be one of the following: * DesignChoiceConstants.DISPLAY_BLOCK | DesignChoiceConstants.DISPLAY_INLINE | * DesignChoiceConstants.DISPLAY_NONE */ public void setDisplay(String display) { // if the display equals none, as the block if (DesignChoiceConstants.DISPLAY_NONE.equals(display)) { setDisplay(DesignChoiceConstants.DISPLAY_BLOCK); } this.display = display; } /** * Returns the text inside the TextFlow. * * @return the text flow inside the text. */ public String getText() { return label.getText(); } /** * Sets the text of the TextFlow to the given value. * * @param newText the new text value. */ public void setText(String newText) { if (newText == null) { newText = ""; // $NON-NLS-1$ } label.setText(newText); } /** * Sets the over-line style of the text. * * @param textOverline The textOverline to set. */ public void setTextOverline(String textOverline) { label.setTextOverline(textOverline); } /** * Sets the line-through style of the text. * * @param textLineThrough The textLineThrough to set. */ public void setTextLineThrough(String textLineThrough) { label.setTextLineThrough(textLineThrough); } /** * Sets the underline style of the text. * * @param textUnderline The textUnderline to set. */ public void setTextUnderline(String textUnderline) { label.setTextUnderline(textUnderline); } /** * Sets the horizontal text alignment style. * * @param textAlign The textAlign to set. */ public void setTextAlign(String textAlign) { label.setTextAlign(textAlign); } /** * Gets the horizontal text alignment style. * * @return The textAlign. */ public String getTextAlign() { return label.getTextAlign(); } /** * Sets the vertical text alignment style. * * @param verticalAlign The verticalAlign to set. */ public void setVerticalAlign(String verticalAlign) { label.setVerticalAlign(verticalAlign); } /** * Sets the toolTip text for this figure. * * @param toolTip */ public void setToolTipText(String toolTip) { if (toolTip != null) { setToolTip( ReportFigureUtilities.createToolTipFigure( toolTip, this.getDirection(), this.getTextAlign())); } else { setToolTip(null); } } /* * (non-Javadoc) * * @see org.eclipse.draw2d.Figure#setFont(org.eclipse.swt.graphics.Font) */ public void setFont(Font f) { super.setFont(f); label.setFont(f); } /** @param specialPREFIX */ public void setSpecialPREFIX(String specialPREFIX) { label.setSpecialPREFIX(specialPREFIX); } /** * Gets the direction property of the Label. * * @return the Label direction. * @author bidi_hcg */ public String getDirection() { return label.getDirection(); } /** * Sets the direction property of the Label. * * @param direction the direction property. this should be one of the following: * DesignChoiceConstants.BIDI_DIRECTION_LTR | DesignChoiceConstants.BIDI_DIRECTION_RTL * @author bidi_hcg */ public void setDirection(String direction) { label.setDirection(direction); } @Override public Dimension getFixPreferredSize(int w, int h) { int width = 0; int height = 0; if (recommendSize.width > 0) { width = recommendSize.width; } else { if (recommendSize.height > 0) { width = getPreferredSize(w, recommendSize.height, true, false, true).width; } else { width = getPreferredSize(w, h, true, false, false).width; } } if (recommendSize.height > 0) { height = recommendSize.height; } else { if (recommendSize.width > 0) { int maxWidth = calcMaxSegment(); height = getPreferredSize(Math.max(maxWidth, recommendSize.width), h, true, true, false).height; } else { height = getPreferredSize(w, h, true, false, false).height; } } return new Dimension(width, height); } @Override public Dimension getFixMinimumSize(int w, int h) { int width = 0; int height = 0; if (recommendSize.width > 0) { width = recommendSize.width; } else { if (recommendSize.height > 0) { width = getMinimumSize(w, recommendSize.height, true, false, true).width; } else { width = getMinimumSize(w, h, true, false, false).width; } } if (recommendSize.height > 0) { height = recommendSize.height; } else { if (recommendSize.width > 0) { int maxWidth = calcMaxSegment(); height = getMinimumSize(Math.max(maxWidth, recommendSize.width), h, true, true, false).height; } else { height = getMinimumSize(w, h, true, false, false).height; } } return new Dimension(width, height); } public boolean isFixLayout() { return isFixLayout; } public void setFixLayout(boolean isFixLayout) { this.isFixLayout = isFixLayout; } }
public void TestThaiDictionaryBreakIterator() { int position; int index; int result[] = {1, 2, 5, 10, 11, 12, 11, 10, 5, 2, 1, 0}; char ctext[] = { 0x0041, 0x0020, 0x0E01, 0x0E32, 0x0E23, 0x0E17, 0x0E14, 0x0E25, 0x0E2D, 0x0E07, 0x0020, 0x0041 }; String text = new String(ctext); ULocale locale = ULocale.createCanonical("th"); BreakIterator b = BreakIterator.getWordInstance(locale); b.setText(text); index = 0; // Test forward iteration while ((position = b.next()) != BreakIterator.DONE) { if (position != result[index++]) { errln( "Error with ThaiDictionaryBreakIterator forward iteration test at " + position + ".\nShould have been " + result[index - 1]); } } // Test backward iteration while ((position = b.previous()) != BreakIterator.DONE) { if (position != result[index++]) { errln( "Error with ThaiDictionaryBreakIterator backward iteration test at " + position + ".\nShould have been " + result[index - 1]); } } // Test invalid sequence and spaces char text2[] = { 0x0E01, 0x0E39, 0x0020, 0x0E01, 0x0E34, 0x0E19, 0x0E01, 0x0E38, 0x0E49, 0x0E07, 0x0020, 0x0E1B, 0x0E34, 0x0E49, 0x0E48, 0x0E07, 0x0E2D, 0x0E22, 0x0E39, 0x0E48, 0x0E43, 0x0E19, 0x0E16, 0x0E49, 0x0E33 }; int expectedWordResult[] = {2, 3, 6, 10, 11, 15, 17, 20, 22}; int expectedLineResult[] = {3, 6, 11, 15, 17, 20, 22}; BreakIterator brk = BreakIterator.getWordInstance(new ULocale("th")); brk.setText(new String(text2)); position = index = 0; while ((position = brk.next()) != BreakIterator.DONE && position < text2.length) { if (position != expectedWordResult[index++]) { errln( "Incorrect break given by thai word break iterator. Expected: " + expectedWordResult[index - 1] + " Got: " + position); } } brk = BreakIterator.getLineInstance(new ULocale("th")); brk.setText(new String(text2)); position = index = 0; while ((position = brk.next()) != BreakIterator.DONE && position < text2.length) { if (position != expectedLineResult[index++]) { errln( "Incorrect break given by thai line break iterator. Expected: " + expectedLineResult[index - 1] + " Got: " + position); } } // Improve code coverage if (brk.preceding(expectedLineResult[1]) != expectedLineResult[0]) { errln("Incorrect preceding position."); } if (brk.following(expectedLineResult[1]) != expectedLineResult[2]) { errln("Incorrect following position."); } int[] fillInArray = new int[2]; if (((RuleBasedBreakIterator) brk).getRuleStatusVec(fillInArray) != 1 || fillInArray[0] != 0) { errln( "Error: Since getRuleStatusVec is not supported in DictionaryBasedBreakIterator, it should return 1 and fillInArray[0] == 0."); } }