1 11 package org.eclipse.help.ui.internal; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 16 import org.eclipse.swt.SWT; 17 import org.eclipse.swt.custom.StyleRange; 18 import org.eclipse.swt.custom.StyledTextContent; 19 import org.eclipse.swt.custom.TextChangeListener; 20 import org.eclipse.swt.graphics.Drawable; 21 import org.eclipse.swt.graphics.GC; 22 23 import com.ibm.icu.text.BreakIterator; 24 25 public class StyledLineWrapper implements StyledTextContent { 26 27 30 public static final String BOLD_CLOSE_TAG = "</@#$b>"; 34 public static final String BOLD_TAG = "<@#$b>"; 36 private Drawable drawable; 37 38 39 private ArrayList lines = new ArrayList (); 40 41 42 private ArrayList lineStyleRanges = new ArrayList (); 43 44 45 private int charCount = -1; 46 47 48 private static BreakIterator lineBreaker = BreakIterator.getLineInstance(); 49 50 51 public final static int DEFAULT_WIDTH = 350; 52 53 public int maxWidth; 54 55 58 public StyledLineWrapper(String text, Drawable drawable, int minWidth) { 59 this.drawable = drawable; 60 maxWidth = Math.max(DEFAULT_WIDTH, minWidth); 61 if (text == null || text.length() == 0) 62 text = " "; setText(text); 64 } 65 66 69 public void addTextChangeListener(TextChangeListener l) { 70 } 72 73 76 public int getCharCount() { 77 if (charCount != -1) 78 return charCount; 79 charCount = 0; 80 for (Iterator i = lines.iterator(); i.hasNext();) 81 charCount += ((String ) i.next()).length(); 82 return charCount; 83 } 84 85 88 public String getLine(int i) { 89 if ((i >= lines.size()) || (i < 0)) 90 SWT.error(SWT.ERROR_INVALID_ARGUMENT); 91 return (String ) lines.get(i); 92 } 93 94 97 public int getLineAtOffset(int offset) { 98 if (offset >= getCharCount()) 99 return getLineCount() - 1; 100 int count = 0; 101 int line = -1; 102 while (count <= offset) { 103 count += getLine(++line).length(); 104 } 105 return line; 106 } 107 108 111 public int getLineCount() { 112 if (lines.size() == 0) 113 return 1; 114 return lines.size(); 115 } 116 117 120 public String getLineDelimiter() { 121 return null; 122 } 123 124 127 public int getOffsetAtLine(int line) { 128 if (lines.size() == 0) 129 return 0; 130 int offset = 0; 131 for (int i = 0; i < line; i++) 132 offset += getLine(i).length(); 133 return offset; 134 } 135 136 139 public String getTextRange(int start, int end) { 140 int l1 = getLineAtOffset(start); 141 int l2 = getLineAtOffset(end); 142 if (l1 == l2) 143 return getLine(l1).substring(start - getOffsetAtLine(l1), 144 end - start); 145 StringBuffer range = new StringBuffer (getLine(l1).substring( 146 start - getOffsetAtLine(l1))); 147 for (int i = l1 + 1; i < l2; i++) 148 range.append(getLine(i)); 149 range.append(getLine(l2).substring(0, end - getOffsetAtLine(l2))); 150 return range.toString(); 151 } 152 153 156 public void removeTextChangeListener(TextChangeListener arg0) { 157 } 159 160 163 public void replaceTextRange(int arg0, int arg1, String arg2) { 164 } 166 167 170 public void setText(String text) { 171 if (text == null) 172 text = " "; processLineBreaks(text); 174 processStyles(text); 175 } 176 177 180 public StyleRange[] getStyles() { 181 StyleRange[] array = new StyleRange[lineStyleRanges.size()]; 182 lineStyleRanges.toArray(array); 183 return array; 184 } 185 186 190 private void processLineBreaks(String text) { 191 lines = new ArrayList (); 193 char[] textChars = getUnstyledText(text).toCharArray(); 194 int start = 0; 195 for (int i = start; i < textChars.length; i++) { 196 char ch = textChars[i]; 197 if (ch == SWT.CR) { 198 lines.add(new String (textChars, start, i - start)); 199 start = i + 1; 200 if (start >= textChars.length) 202 break; 203 { ch = textChars[start]; 205 if (ch == SWT.LF) { 206 start++; 207 i++; 208 if (start >= textChars.length) 209 break; 210 } 211 } 212 } else if (ch == SWT.LF) { 213 lines.add(new String (textChars, start, i - start)); 214 start = i + 1; 215 if (start >= textChars.length) 216 break; 217 } else if (i == textChars.length - 1) { 218 lines.add(new String (textChars, start, i - start + 1)); 219 } 220 } 221 GC gc = new GC(drawable); 223 for (int i = 0; i < lines.size(); i++) { 224 String line = (String ) lines.get(i); 225 while (line.length() > 0) { 226 int linebreak = getLineBreak(line, gc); 227 if (linebreak == 0 || linebreak == line.length()) 228 break; 229 String newline = line.substring(0, linebreak); 230 lines.remove(i); 231 lines.add(i, newline); 232 line = line.substring(linebreak); 233 lines.add(++i, line); 234 } 235 } 236 gc.dispose(); 237 } 238 239 242 private static String getUnstyledText(String styledText) { 243 return styledText.replaceAll("</?@#\\$b>", ""); } 245 246 249 private int getLineBreak(String line, GC gc) { 250 lineBreaker.setText(line); 251 int lastGoodIndex = 0; 252 int currentIndex = lineBreaker.first(); 253 int width = gc.textExtent(line.substring(0, currentIndex)).x; 254 while (width < maxWidth && currentIndex != BreakIterator.DONE) { 255 lastGoodIndex = currentIndex; 256 currentIndex = lineBreaker.next(); 257 if (currentIndex == BreakIterator.DONE) { 258 break; 259 } 260 width = gc.textExtent(line.substring(0, currentIndex)).x; 261 } 262 return lastGoodIndex; 263 } 264 265 269 private void processStyles(String text) { 270 lineStyleRanges = new ArrayList (); 272 text = text.replaceAll("\n|\r", ""); int offset = 0; 275 do { 276 StyleRange style = new StyleRange(); 278 style.fontStyle = SWT.BOLD; 279 int start = text.indexOf(BOLD_TAG, offset); 281 if (start == -1) 282 break; 283 String prefix = getUnstyledText(text.substring(0, start)); 284 style.start = prefix.length(); 285 offset = start + 1; 287 int end = text.indexOf(BOLD_CLOSE_TAG, offset); 288 if (end == -1) 289 break; 290 prefix = getUnstyledText(text.substring(0, end)); 291 style.length = prefix.length() - style.start; 292 lineStyleRanges.add(style); 293 offset = end + 1; 294 } while (offset < text.length()); 295 } 296 } 297 | Popular Tags |