diff options
author | Felipe Heidrich <fheidric> | 2006-02-13 19:30:14 +0000 |
---|---|---|
committer | Felipe Heidrich <fheidric> | 2006-02-13 19:30:14 +0000 |
commit | caefa6ee44d118fcdfc9a890470791a160f9ad68 (patch) | |
tree | 0276bbabb7028f91d5f443c733b2373a07b6bab0 | |
parent | b59b2c9c83dff7d247f5293493520244610ab7b3 (diff) | |
download | eclipse.platform.swt-caefa6ee44d118fcdfc9a890470791a160f9ad68.tar.gz eclipse.platform.swt-caefa6ee44d118fcdfc9a890470791a160f9ad68.tar.xz eclipse.platform.swt-caefa6ee44d118fcdfc9a890470791a160f9ad68.zip |
bullet list support added - part of bug 54426
8 files changed, 422 insertions, 68 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/Bullet.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/Bullet.java index b70b4b04d2..76bc907f03 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/Bullet.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/Bullet.java @@ -10,12 +10,125 @@ *******************************************************************************/ package org.eclipse.swt.custom; -import org.eclipse.swt.graphics.*; +import org.eclipse.swt.*; -class Bullet { - GlyphMetrics metrics; - - public Bullet(GlyphMetrics metrics) { - this.metrics = metrics; +/** + * Instances of this class represent bullet in the <code>StyledText</code>. + * <p> + * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + * </p> + * <p> + * Application code does <em>not</em> need to explicitly release the + * resources managed by each instance when those instances are no longer + * required, and thus no <code>dispose()</code> method is provided. + * </p> + * + * @see StyledText#setLineBullet(int, int, Bullet) + * + * @since 3.2 + */ +public class Bullet { + public int type; + public StyleRange style; + public String text; + int[] linesIndices; + int count; + +/** + * Create a new bullet the specified style, the type is set to ST.BULLET_DOT. + * The style must have a glyph metrics set. + * + * @param style the style + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT when the style or the glyph metrics are null</li> + * </ul> + */ +public Bullet(StyleRange style) { + this(ST.BULLET_DOT, style); +} +/** + * Create a new bullet the specified style and type. + * The style must have a glyph metrics set. + * + * @param style the style + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT when the style or the glyph metrics are null</li> + * </ul> + */ +public Bullet(int type, StyleRange style) { + if (style == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (style.metrics == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.type = type; + this.style = style; +} +void addIndices (int startLine, int lineCount) { + if (linesIndices == null) { + linesIndices = new int[lineCount]; + count = lineCount; + for (int i = 0; i < lineCount; i++) linesIndices[i] = startLine + i; + } else { + int modifyStart = 0; + while (modifyStart < count) { + if (startLine <= linesIndices[modifyStart]) break; + modifyStart++; + } + int modifyEnd = modifyStart; + while (modifyEnd < count) { + if (startLine + lineCount <= linesIndices[modifyEnd]) break; + modifyEnd++; + } + int newSize = modifyStart + lineCount + count - modifyEnd; + if (newSize > linesIndices.length) { + int[] newLinesIndices = new int[newSize]; + System.arraycopy(linesIndices, 0, newLinesIndices, 0, count); + linesIndices = newLinesIndices; + } + System.arraycopy(linesIndices, modifyEnd, linesIndices, modifyStart + lineCount, count - modifyEnd); + for (int i = 0; i < lineCount; i++) linesIndices[modifyStart + i] = startLine + i; + count = newSize; + } +} +int indexOf (int lineIndex) { + for (int i = 0; i < count; i++) { + if (linesIndices[i] == lineIndex) return i; } + return -1; +} +public int hashCode() { + return style.hashCode() ^ type; +} +int[] removeIndices (int startLine, int replaceLineCount, int newLineCount, boolean update) { + if (count == 0) return null; + if (startLine > linesIndices[count - 1]) return null; + int endLine = startLine + replaceLineCount; + int delta = newLineCount - replaceLineCount; + for (int i = 0; i < count; i++) { + int index = linesIndices[i]; + if (startLine <= index) { + int j = i; + while (j < count) { + if (linesIndices[j] >= endLine) break; + j++; + } + if (update) { + for (int k = j; k < count; k++) linesIndices[k] += delta; + } + int[] redrawLines = new int[count - j]; + System.arraycopy(linesIndices, j, redrawLines, 0, count - j); + System.arraycopy(linesIndices, j, linesIndices, i, count - j); + count -= (j - i); + return redrawLines; + } + } + for (int i = 0; i < count; i++) linesIndices[i] += delta; + return null; +} +int size() { + return count; +} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/LineStyleEvent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/LineStyleEvent.java index 42d3d84523..a4f27a6e39 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/LineStyleEvent.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/LineStyleEvent.java @@ -68,8 +68,15 @@ public class LineStyleEvent extends TypedEvent { /** * line bullet (output) + * @since 3.2 + */ + public Bullet bullet; + + /** + * line bullet index (output) + * @since 3.2 */ - Bullet bullet; + public int bulletIndex; static final long serialVersionUID = 3906081274027192884L; @@ -80,5 +87,7 @@ public LineStyleEvent(StyledTextEvent e) { alignment = e.alignment; justify = e.justify; indent = e.indent; + bullet = e.bullet; + bulletIndex = e.bulletIndex; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PaintObjectEvent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PaintObjectEvent.java index 1e766dcbfd..f84500a1a5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PaintObjectEvent.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PaintObjectEvent.java @@ -41,7 +41,7 @@ public class PaintObjectEvent extends TypedEvent { public int ascent; /** - * the descent location + * the line descent */ public int descent; @@ -50,7 +50,15 @@ public class PaintObjectEvent extends TypedEvent { */ public StyleRange style; -// public Bullet bullet; + /** + * the Bullet + */ + public Bullet bullet; + + /** + * the bullet index + */ + public int bulletIndex; static final long serialVersionUID = 3906081274027192855L; @@ -62,6 +70,7 @@ public PaintObjectEvent(StyledTextEvent e) { ascent = e.ascent; descent = e.descent; style = e.style; -// bullet = e.bullet; + bullet = e.bullet; + bulletIndex = e.bulletIndex; } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ST.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ST.java index ededac9cb9..01d01b7476 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ST.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ST.java @@ -15,12 +15,13 @@ package org.eclipse.swt.custom; * This class provides access to the public constants provided by <code>StyledText</code>. */ public class ST { - - /* StyledText key action constants. Key bindings for the actions are set - * by the StyledText widget. @see StyledText#createKeyBindings() - */ - /* Navigation Key Actions */ + /** + * Navigation Key Actions. Key bindings for the actions are set + * by the StyledText widget. + * + * @see StyledText#createKeyBindings() + */ public static final int LINE_UP = 16777217; // binding = SWT.ARROW_UP public static final int LINE_DOWN = 16777218; // binding = SWT.ARROW_DOWN public static final int LINE_START = 16777223; // binding = SWT.HOME @@ -36,7 +37,9 @@ public class ST { public static final int WINDOW_START = 17039365; // binding = SWT.MOD1 + SWT.PAGE_UP public static final int WINDOW_END = 17039366; // binding = SWT.MOD1 + SWT.PAGE_DOWN - /* Selection Key Actions */ + /** + * Selection Key Actions + */ public static final int SELECT_ALL = 262209; // binding = SWT.MOD1 + 'A' public static final int SELECT_LINE_UP = 16908289; // binding = SWT.MOD2 + SWT.ARROW_UP public static final int SELECT_LINE_DOWN = 16908290; // binding = SWT.MOD2 + SWT.ARROW_DOWN @@ -53,7 +56,9 @@ public class ST { public static final int SELECT_WINDOW_START = 17170437; // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_UP public static final int SELECT_WINDOW_END = 17170438; // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_DOWN - /* Modification Key Actions */ + /** + * Modification Key Actions + */ public static final int CUT = 131199; // binding = SWT.MOD2 + SWT.DEL public static final int COPY = 17039369; // binding = SWT.MOD1 + SWT.INSERT; public static final int PASTE = 16908297; // binding = SWT.MOD2 + SWT.INSERT ; @@ -62,6 +67,21 @@ public class ST { public static final int DELETE_WORD_PREVIOUS = 262152; // binding = SWT.BS | SWT.MOD1; public static final int DELETE_WORD_NEXT = 262271; // binding = SWT.DEL | SWT.MOD1; - /* Miscellaneous Key Actions */ + /** + * Miscellaneous Key Actions + */ public static final int TOGGLE_OVERWRITE = 16777225; // binding = SWT.INSERT; + + /** + * Bullets styles + * + * @since 3.2 + */ + public static final int BULLET_DOT = 1 << 0; + public static final int BULLET_NUMBER = 1 << 1; + public static final int BULLET_LETTER_LOWER = 1 << 2; + public static final int BULLET_LETTER_UPPER = 1 << 3; + public static final int BULLET_TEXT = 1 << 4; + public static final int BULLET_CUSTOM = 1 << 5; + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index a15c635faa..f890720002 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -3385,7 +3385,7 @@ public Color getLineBackground(int index) { * * @since 3.2 */ -Bullet getLineBullet(int index) { +public Bullet getLineBullet(int index) { checkWidget(); if (index < 0 || index > content.getLineCount()) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); @@ -4726,8 +4726,8 @@ Point getPointAtOffset(int offset) { } } Point point; + TextLayout layout = renderer.getTextLayout(lineIndex); if (lineLength != 0 && offsetInLine <= lineLength) { - TextLayout layout = renderer.getTextLayout(lineIndex); switch (caretAlignment) { case OFFSET_LEADING: point = layout.getLocation(offsetInLine, false); @@ -4741,10 +4741,10 @@ Point getPointAtOffset(int offset) { } break; } - renderer.disposeTextLayout(layout); } else { - point = new Point(0, 0); + point = new Point(layout.getIndent(), 0); } + renderer.disposeTextLayout(layout); point.x += leftMargin - horizontalScrollOffset; point.y += getLinePixel(lineIndex); return point; @@ -5293,6 +5293,8 @@ void handleTextChanged(TextChangedEvent event) { int newLastLineBottom = getLinePixel(lastLine + 1); scrollText(lastLineBottom, newLastLineBottom); super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); + redrawLinesBullet(renderer.redrawLines); + renderer.redrawLines = null; // update selection/caret location after styles have been changed. // otherwise any text measuring could be incorrect // @@ -5764,7 +5766,7 @@ void modifyContent(Event event, boolean updateCaret) { } } } -void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style) { +void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) { if (isListening(PaintObject)) { StyledTextEvent event = new StyledTextEvent (content) ; event.gc = gc; @@ -5773,7 +5775,8 @@ void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style) event.ascent = ascent; event.descent = descent; event.style = style; -// event.bullet = bullet; + event.bullet = bullet; + event.bulletIndex = bulletIndex; notifyListeners(PaintObject, event); } } @@ -5956,6 +5959,26 @@ void redrawLines(int startLine, int lineCount) { int redrawWidth = clientAreaWidth - leftMargin - rightMargin; super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); } +void redrawLinesBullet (int[] redrawLines) { + if (redrawLines == null) return; + int topIndex = getPartialTopIndex(); + int bottomIndex = getPartialBottomIndex(); + for (int i = 0; i < redrawLines.length; i++) { + int lineIndex = redrawLines[i]; + if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue; + int width = -1; + Bullet bullet = renderer.getLineBullet(lineIndex, null); + if (bullet != null) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + width = metrics.width; + } + if (width == -1) width = getClientArea().width; + int height = renderer.getLineHeight(lineIndex); + int y = getLinePixel(lineIndex); + super.redraw(0, y, width, height, false); + } +} /** * Redraws the specified text range. * <p> @@ -7101,7 +7124,7 @@ public void setLineBackground(int startLine, int lineCount, Color background) { * </ul> * @since 3.2 */ -void setLineBullet(int startLine, int lineCount, Bullet bullet) { +public void setLineBullet(int startLine, int lineCount, Bullet bullet) { checkWidget(); if (isListening(LineGetStyle)) return; if (startLine < 0 || startLine + lineCount > content.getLineCount()) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextEvent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextEvent.java index 1d1f313422..7065608683 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextEvent.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextEvent.java @@ -23,7 +23,8 @@ class StyledTextEvent extends Event { int alignment; int indent; boolean justify; - Bullet bullet; + Bullet bullet; + int bulletIndex; // used by LineBackgroundEvent Color lineBackground; // used by BidiSegmentEvent diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextListener.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextListener.java index 7ffef5cd3e..01826ad960 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextListener.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextListener.java @@ -50,6 +50,7 @@ public void handleEvent(Event e) { ((StyledTextEvent) e).indent = lineStyleEvent.indent; ((StyledTextEvent) e).justify = lineStyleEvent.justify; ((StyledTextEvent) e).bullet = lineStyleEvent.bullet; + ((StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex; break; case StyledText.PaintObject: PaintObjectEvent paintObjectEvent = new PaintObjectEvent((StyledTextEvent) e); diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index 766b18527e..476a9897b4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -42,12 +42,18 @@ class StyledTextRenderer { int maxWidthLineIndex; boolean idleRunning; + /* Bullet */ + Bullet[] bullets; + int[] bulletsIndices; + int[] redrawLines; + /* Style data */ int[] ranges; int styleCount; StyleRange[] styles; StyleRange[] stylesSet; int stylesSetCount = 0; + final static int BULLET_MARGIN = 8; final static boolean COMPACT_STYLES = true; final static boolean MERGE_STYLES = true; @@ -60,7 +66,6 @@ class StyledTextRenderer { final static int ALIGNMENT = 1 << 1; final static int INDENT = 1 << 2; final static int JUSTIFY = 1 << 3; - final static int BULLET = 1 << 4; final static int SEGMENTS = 1 << 5; static class LineInfo { @@ -69,18 +74,16 @@ class StyledTextRenderer { int alignment; int indent; boolean justify; - Bullet bullet; int[] segments; - - public LineInfo() { + + public LineInfo() { } public LineInfo(LineInfo info) { flags = info.flags; - background = info.background; + background = info.background; alignment = info.alignment; indent = info.indent; justify = info.justify; - bullet = info.bullet; segments = info.segments; } } @@ -262,8 +265,7 @@ void clearLineStyle(int startLine, int count) { for (int i = startLine; i < startLine + count; i++) { LineInfo info = lines[i]; if (info != null) { - info.flags &= ~(ALIGNMENT | INDENT | BULLET | JUSTIFY); - info.bullet = null; + info.flags &= ~(ALIGNMENT | INDENT | JUSTIFY); if (info.flags == 0) lines[i] = null; } } @@ -306,6 +308,47 @@ void disposeTextLayout (TextLayout layout) { } layout.dispose(); } +void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + Color color = style.foreground; + if (color != null) gc.setForeground(color); + if ((bullet.type & ST.BULLET_DOT) != 0 && StyledText.IS_MOTIF) { + int size = Math.max(4, (lineAscent + lineDescent) / 4); + if ((size & 1) == 0) size++; + if (color == null) { + Display display = styledText.getDisplay(); + color = display.getSystemColor(SWT.COLOR_BLACK); + } + gc.setBackground(color); + int x = paintX + Math.max(0, metrics.width - size - BULLET_MARGIN); + gc.fillArc(x, paintY + size, size + 1, size + 1, 0, 360); + return; + } + Font font = style.font; + if (font != null) gc.setFont(font); + String string = ""; + int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER); + switch (type) { + case ST.BULLET_DOT: string = "\u2022"; break; + case ST.BULLET_NUMBER: string = String.valueOf(index); break; + case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break; + case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break; + } + if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text; + Display display = styledText.getDisplay(); + TextLayout layout = new TextLayout(display); + layout.setText(string); + layout.setAscent(lineAscent); + layout.setDescent(lineDescent); + style = (StyleRange)style.clone(); + style.metrics = null; + if (style.font == null) style.font = getFont(style.fontStyle); + layout.setStyle(style, 0, string.length()); + int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN); + layout.draw(gc, x, paintY); + layout.dispose(); +} int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackground, Color widgetForeground) { TextLayout layout = getTextLayout(lineIndex); String line = content.getLine(lineIndex); @@ -366,13 +409,34 @@ int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackgroun } // draw objects -// Bullet bullet = null; -// if (lines != null) { -// LineInfo info = lines[lineIndex]; -// if (info != null) { -// if ((info.flags & BULLET) != 0) bullet = info.bullet; -// } -// } + Bullet bullet = null; + int bulletIndex = -1; + if (bullets != null) { + if (bulletsIndices != null) { + int index = lineIndex - topIndex; + if (0 <= index && index < CACHE_SIZE) { + bullet = bullets[index]; + bulletIndex = bulletsIndices[index]; + } + } else { + for (int i = 0; i < bullets.length; i++) { + bullet = bullets[i]; + bulletIndex = bullet.indexOf(lineIndex); + if (bulletIndex != -1) break; + } + } + } + if (bulletIndex != -1 && bullet != null) { + FontMetrics metrics = layout.getLineMetrics(0); + int lineAscent = metrics.getAscent() + metrics.getLeading(); + if (bullet.type == ST.BULLET_CUSTOM) { + bullet.style.start = lineOffset; + styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex); + } else { + drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent()); + } + } + TextStyle[] styles = layout.getStyles(); int[] ranges = null; for (int i = 0; i < styles.length; i++) { @@ -386,7 +450,7 @@ int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackgroun style.start = start + lineOffset; style.length = length; int lineAscent = metrics.getAscent() + metrics.getLeading(); - styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style); + styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0); } } int height = layout.getBounds().height; @@ -455,11 +519,12 @@ Color getLineBackground(int index, Color defaultBackground) { } return defaultBackground; } -Bullet getLineBullet(int index, Bullet defaultBullet) { - if (lines == null) return defaultBullet; - LineInfo info = lines[index]; - if (info != null && (info.flags & BULLET) != 0) { - return info.bullet; +Bullet getLineBullet (int index, Bullet defaultBullet) { + if (bullets == null) return defaultBullet; + if (bulletsIndices != null) return defaultBullet; + for (int i = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + if (bullet.indexOf(index) != -1) return bullet; } return defaultBullet; } @@ -614,7 +679,7 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac if (layouts == null || topIndex != this.topIndex) { TextLayout[] newLayouts = new TextLayout[CACHE_SIZE]; if (layouts != null) { - for(int i = 0; i < layouts.length; i++) { + for (int i = 0; i < layouts.length; i++) { if (layouts[i] != null) { int layoutIndex = (i + this.topIndex) - topIndex; if (0 <= layoutIndex && layoutIndex < newLayouts.length) { @@ -625,6 +690,24 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac } } } + if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) { + int delta = topIndex - this.topIndex; + if (delta > 0) { + if (delta < bullets.length) { + System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta); + System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta); + } + int startIndex = Math.max(0, bullets.length - delta); + for (int i = startIndex; i < bullets.length; i++) bullets[i] = null; + } else { + if (-delta < bullets.length) { + System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta); + System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta); + } + int endIndex = Math.min(bullets.length, -delta); + for (int i = 0; i < endIndex; i++) bullets[i] = null; + } + } this.topIndex = topIndex; layouts = newLayouts; } @@ -679,6 +762,15 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac } } } + if (bullets == null || bulletsIndices == null) { + bullets = new Bullet[CACHE_SIZE]; + bulletsIndices = new int[CACHE_SIZE]; + } + int index = lineIndex - topIndex; + if (0 <= index && index < CACHE_SIZE) { + bullets[index] = bullet; + bulletsIndices[index] = event.bulletIndex; + } } else { if (lines != null) { LineInfo info = lines[lineIndex]; @@ -686,10 +778,21 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac if ((info.flags & INDENT) != 0) indent = info.indent; if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment; if ((info.flags & JUSTIFY) != 0) justify = info.justify; - if ((info.flags & BULLET) != 0) bullet = info.bullet; if ((info.flags & SEGMENTS) != 0) segments = info.segments; } } + if (bulletsIndices != null) { + bullets = null; + bulletsIndices = null; + } + if (bullets != null) { + for (int i = 0; i < bullets.length; i++) { + if (bullets[i].indexOf(lineIndex) != -1) { + bullet = bullets[i]; + break; + } + } + } ranges = this.ranges; styles = this.styles; styleCount = this.styleCount; @@ -699,8 +802,11 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac rangeStart = getRangeIndex(lineOffset, -1, styleCount); } } - if (bullet != null) indent += bullet.metrics.width; - + if (bullet != null) { + StyleRange style = bullet.style; + GlyphMetrics metrics = style.metrics; + indent += metrics.width; + } layout.setFont(regularFont); layout.setAscent(ascent); layout.setDescent(descent); @@ -776,6 +882,9 @@ void reset() { lines = null; lineWidth = null; lineHeight = null; + bullets = null; + bulletsIndices = null; + redrawLines = null; } void reset(int startLine, int lineCount) { int endLine = startLine + lineCount; @@ -858,13 +967,32 @@ void setLineBackground(int startLine, int count, Color background) { } } void setLineBullet(int startLine, int count, Bullet bullet) { - if (lines == null) lines = new LineInfo[lineCount]; - for (int i = startLine; i < startLine + count; i++) { - if (lines[i] == null) { - lines[i] = new LineInfo(); + if (bulletsIndices != null) { + bulletsIndices = null; + bullets = null; + } + if (bullets == null) { + if (bullet == null) return; + bullets = new Bullet[1]; + bullets[0] = bullet; + } + int index = 0; + while (index < bullets.length) { + if (bullet == bullets[index]) break; + index++; + } + if (bullet != null) { + if (index == bullets.length) { + Bullet[] newBulletsList = new Bullet[bullets.length + 1]; + System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length); + newBulletsList[index] = bullet; + bullets = newBulletsList; } - lines[i].flags |= BULLET; - lines[i].bullet = bullet; + bullet.addIndices(startLine, count); + } else { + updateBullets(startLine, count, 0, false); + styledText.redrawLinesBullet(redrawLines); + redrawLines = null; } } void setLineIndent(int startLine, int count, int indent) { @@ -1097,6 +1225,7 @@ void textChanging(TextChangingEvent event) { if (0 <= i && i < layouts.length) { if (layouts[i] != null) layouts[i].dispose(); layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; } } if (delta > 0) { @@ -1106,9 +1235,15 @@ void textChanging(TextChangingEvent event) { if (0 <= endIndex && endIndex < layouts.length) { layouts[endIndex] = layouts[i]; layouts[i] = null; + if (bullets != null && bulletsIndices != null) { + bullets[endIndex] = bullets[i]; + bulletsIndices[endIndex] = bulletsIndices[i]; + bullets[i] = null; + } } else { if (layouts[i] != null) layouts[i].dispose(); layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; } } } @@ -1119,28 +1254,37 @@ void textChanging(TextChangingEvent event) { if (0 <= endIndex && endIndex < layouts.length) { layouts[endIndex] = layouts[i]; layouts[i] = null; + if (bullets != null && bulletsIndices != null) { + bullets[endIndex] = bullets[i]; + bulletsIndices[endIndex] = bulletsIndices[i]; + bullets[i] = null; + } } else { if (layouts[i] != null) layouts[i].dispose(); layouts[i] = null; + if (bullets != null && bulletsIndices != null) bullets[i] = null; } } } } } - if (lines != null && !(replaceLineCount == 0 && newLineCount == 0)) { + if (replaceLineCount != 0 || newLineCount != 0) { int startLineOffset = content.getOffsetAtLine(startLine); if (startLineOffset != start) startLine++; - startIndex = startLine + replaceLineCount; - endIndex = startLine + newLineCount; - System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex); - for (int i = startLine; i < endIndex; i++) { - lines[i] = null; - } - for (int i = lineCount + delta; i < lineCount; i++) { - lines[i] = null; + updateBullets(startLine, replaceLineCount, newLineCount, true); + if (lines != null) { + startIndex = startLine + replaceLineCount; + endIndex = startLine + newLineCount; + System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex); + for (int i = startLine; i < endIndex; i++) { + lines[i] = null; + } + for (int i = lineCount + delta; i < lineCount; i++) { + lines[i] = null; + } } } - lineCount += delta; + lineCount += delta; if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) { maxWidth = 0; maxWidthLineIndex = -1; @@ -1151,7 +1295,41 @@ void textChanging(TextChangingEvent event) { } } } - } + } +} +void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) { + if (bullets == null) return; + if (bulletsIndices != null) return; + for (int i = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update); + if (lines != null) { + if (redrawLines == null) { + redrawLines = lines; + } else { + int[] newRedrawBullets = new int[redrawLines.length + lines.length]; + System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length); + System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length); + redrawLines = newRedrawBullets; + } + } + } + int removed = 0; + for (int i = 0; i < bullets.length; i++) { + if (bullets[i].size() == 0) removed++; + } + if (removed > 0) { + if (removed == bullets.length) { + bullets = null; + } else { + Bullet[] newBulletsList = new Bullet[bullets.length - removed]; + for (int i = 0, j = 0; i < bullets.length; i++) { + Bullet bullet = bullets[i]; + if (bullet.size() > 0) newBulletsList[j++] = bullet; + } + bullets = newBulletsList; + } + } } void updateRanges(int start, int replaceCharCount, int newCharCount) { if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return; |