Mercurial > projects > dwt-addons
annotate dwtx/ui/internal/forms/widgets/TextSegment.d @ 77:26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 24 May 2008 06:59:31 +0200 |
parents | 5d489b9f966c |
children | 7ffeace6c47f |
rev | line source |
---|---|
75 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.ui.internal.forms.widgets.TextSegment; | |
14 | |
15 import dwtx.ui.internal.forms.widgets.ParagraphSegment; | |
16 import dwtx.ui.internal.forms.widgets.Locator; | |
17 import dwtx.ui.internal.forms.widgets.SelectionData; | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
18 import dwtx.ui.internal.forms.widgets.FormTextModel; |
75 | 19 |
20 import dwt.DWT; | |
21 import dwt.graphics.Color; | |
22 import dwt.graphics.Font; | |
23 import dwt.graphics.FontMetrics; | |
24 import dwt.graphics.GC; | |
25 import dwt.graphics.Point; | |
26 import dwt.graphics.Rectangle; | |
27 | |
28 import dwt.dwthelper.utils; | |
29 import tango.util.collection.ArraySeq; | |
30 | |
31 /** | |
32 * @version 1.0 | |
33 * @author | |
34 */ | |
35 public class TextSegment : ParagraphSegment { | |
36 | |
37 //DWT_TODO temp type | |
38 static class BreakIterator{ | |
39 | |
40 public static const int DONE = 0; | |
41 | |
42 public static BreakIterator getLineInstance() { | |
43 // TODO Auto-generated method stub | |
44 return null; | |
45 } | |
46 | |
47 public void setText(String text) { | |
48 // TODO Auto-generated method stub | |
49 | |
50 } | |
51 | |
52 public int first() { | |
53 // TODO Auto-generated method stub | |
54 return 0; | |
55 } | |
56 | |
57 public int next() { | |
58 // TODO Auto-generated method stub | |
59 return 0; | |
60 } | |
61 | |
62 } | |
63 private String colorId; | |
64 | |
65 private String fontId; | |
66 | |
67 private String text; | |
68 | |
69 protected bool underline; | |
70 | |
71 private bool wrapAllowed = true; | |
72 | |
73 protected ArraySeq!(Object) areaRectangles; | |
74 | |
75 private TextFragment[] textFragments; | |
76 | |
77 class AreaRectangle { | |
78 Rectangle rect; | |
79 | |
80 int from, to; | |
81 | |
82 public this(Rectangle rect, int from, int to) { | |
83 this.rect = rect; | |
84 this.from = from; | |
85 this.to = to; | |
86 } | |
87 | |
88 public bool contains(int x, int y) { | |
89 return rect.contains(x, y); | |
90 } | |
91 | |
92 public bool intersects(Rectangle region) { | |
93 return rect.intersects(region); | |
94 } | |
95 | |
96 public String getText() { | |
97 if (from is 0 && to is -1) | |
98 return this.outer.getText(); | |
99 if (from > 0 && to is -1) | |
100 return this.outer.getText().substring(from); | |
101 return this.outer.getText().substring(from, to); | |
102 } | |
103 } | |
104 | |
105 static class SelectionRange { | |
106 public int start; | |
107 | |
108 public int stop; | |
109 | |
110 public this() { | |
111 reset(); | |
112 } | |
113 | |
114 public void reset() { | |
115 start = -1; | |
116 stop = -1; | |
117 } | |
118 } | |
119 | |
120 static class TextFragment { | |
121 short index; | |
122 | |
123 short length; | |
124 | |
125 public this(short index, short length) { | |
126 this.index = index; | |
127 this.length = length; | |
128 } | |
129 } | |
130 | |
131 public this(String text, String fontId) { | |
132 this(text, fontId, null, true); | |
133 } | |
134 | |
135 public this(String text, String fontId, String colorId) { | |
136 this(text, fontId, colorId, true); | |
137 } | |
138 | |
139 public this(String text, String fontId, String colorId, bool wrapAllowed) { | |
140 areaRectangles = new ArraySeq!(Object); | |
141 this.text = cleanup(text); | |
142 this.fontId = fontId; | |
143 this.colorId = colorId; | |
144 this.wrapAllowed = wrapAllowed; | |
145 } | |
146 | |
147 private String cleanup(String text) { | |
148 StringBuffer buf = new StringBuffer(); | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
149 for (int i = 0; i < text.length; i++) { |
75 | 150 char c = text.charAt(i); |
151 if (c is '\n' || c is '\r' || c is '\f') { | |
152 if (i > 0) | |
153 buf.append(' '); | |
154 } else | |
155 buf.append(c); | |
156 } | |
157 return buf.toString(); | |
158 } | |
159 | |
160 public void setWordWrapAllowed(bool value) { | |
161 wrapAllowed = value; | |
162 } | |
163 | |
164 public bool isWordWrapAllowed() { | |
165 return wrapAllowed; | |
166 } | |
167 | |
168 public bool isSelectable() { | |
169 return false; | |
170 } | |
171 | |
172 public String getColorId() { | |
173 return colorId; | |
174 } | |
175 | |
176 public String getText() { | |
177 return text; | |
178 } | |
179 | |
180 void setText(String text) { | |
181 this.text = cleanup(text); | |
182 textFragments = null; | |
183 } | |
184 | |
185 void setColorId(String colorId) { | |
186 this.colorId = colorId; | |
187 } | |
188 | |
189 void setFontId(String fontId) { | |
190 this.fontId = fontId; | |
191 textFragments = null; | |
192 } | |
193 | |
194 public bool contains(int x, int y) { | |
195 for (int i = 0; i < areaRectangles.size(); i++) { | |
196 AreaRectangle ar = cast(AreaRectangle) areaRectangles.get(i); | |
197 if (ar.contains(x, y)) | |
198 return true; | |
199 if (i<areaRectangles.size()-1) { | |
200 // test the gap | |
201 Rectangle top = ar.rect; | |
202 Rectangle bot = (cast(AreaRectangle)areaRectangles.get(i+1)).rect; | |
203 if (y >= top.y+top.height && y < bot.y) { | |
204 // in the gap | |
205 int left = Math.max(top.x, bot.x); | |
206 int right = Math.min(top.x+top.width, bot.x+bot.width); | |
207 if (x>=left && x<=right) { | |
208 return true; | |
209 } | |
210 } | |
211 } | |
212 } | |
213 return false; | |
214 } | |
215 | |
216 public bool intersects(Rectangle rect) { | |
217 for (int i = 0; i < areaRectangles.size(); i++) { | |
218 AreaRectangle ar = cast(AreaRectangle) areaRectangles.get(i); | |
219 if (ar.intersects(rect)) | |
220 return true; | |
221 if (i<areaRectangles.size()-1) { | |
222 // test the gap | |
223 Rectangle top = ar.rect; | |
224 Rectangle bot = (cast(AreaRectangle)areaRectangles.get(i+1)).rect; | |
225 if (top.y+top.height < bot.y) { | |
226 int y = top.y+top.height; | |
227 int height = bot.y-y; | |
228 int left = Math.max(top.x, bot.x); | |
229 int right = Math.min(top.x+top.width, bot.x+bot.width); | |
230 Rectangle gap = new Rectangle(left, y, right-left, height); | |
231 if (gap.intersects(rect)) | |
232 return true; | |
233 } | |
234 } | |
235 } | |
236 return false; | |
237 } | |
238 | |
239 public Rectangle getBounds() { | |
240 int x = 0, y = 0; | |
241 int width = 0, height = 0; | |
242 | |
243 for (int i = 0; i < areaRectangles.size(); i++) { | |
244 AreaRectangle ar = cast(AreaRectangle) areaRectangles.get(i); | |
245 if (i is 0) { | |
246 x = ar.rect.x; | |
247 y = ar.rect.y; | |
248 } else | |
249 x = Math.min(ar.rect.x, x); | |
250 width = Math.max(ar.rect.width, width); | |
251 height += ar.rect.height; | |
252 } | |
253 return new Rectangle(x, y, width, height); | |
254 } | |
255 | |
256 public bool advanceLocator(GC gc, int wHint, Locator locator, | |
257 Hashtable objectTable, bool computeHeightOnly) { | |
258 Font oldFont = null; | |
259 if (fontId !is null) { | |
260 oldFont = gc.getFont(); | |
261 Font newFont = cast(Font) objectTable.get(fontId); | |
262 if (newFont !is null) | |
263 gc.setFont(newFont); | |
264 } | |
265 FontMetrics fm = gc.getFontMetrics(); | |
266 int lineHeight = fm.getHeight(); | |
267 bool newLine = false; | |
268 | |
269 if (wHint is DWT.DEFAULT || !wrapAllowed) { | |
270 Point extent = gc.textExtent(text); | |
271 int totalExtent = locator.x+extent.x; | |
272 if (isSelectable()) | |
273 totalExtent+=1; | |
274 | |
275 if (wHint !is DWT.DEFAULT && totalExtent > wHint) { | |
276 // new line | |
277 locator.x = locator.indent; | |
278 locator.y += locator.rowHeight; | |
279 if (computeHeightOnly) | |
280 locator.collectHeights(); | |
281 locator.rowHeight = 0; | |
282 locator.leading = 0; | |
283 newLine = true; | |
284 } | |
285 int width = extent.x; | |
286 if (isSelectable()) | |
287 width += 1; | |
288 locator.x += width; | |
289 locator.width = locator.indent + width; | |
290 locator.rowHeight = Math.max(locator.rowHeight, extent.y); | |
291 locator.leading = Math.max(locator.leading, fm.getLeading()); | |
292 return newLine; | |
293 } | |
294 | |
295 computeTextFragments(gc); | |
296 | |
297 int width = 0; | |
298 Point lineExtent = new Point(0, 0); | |
299 | |
300 for (int i = 0; i < textFragments.length; i++) { | |
301 TextFragment textFragment = textFragments[i]; | |
302 int currentExtent = locator.x + lineExtent.x; | |
303 | |
304 if (isSelectable()) | |
305 currentExtent += 1; | |
306 | |
307 if (i !is 0 && currentExtent + textFragment.length > wHint) { | |
308 // overflow | |
309 int lineWidth = currentExtent; | |
310 locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y); | |
311 locator.leading = Math.max(locator.leading, fm.getLeading()); | |
312 if (computeHeightOnly) | |
313 locator.collectHeights(); | |
314 locator.x = locator.indent; | |
315 locator.y += locator.rowHeight; | |
316 locator.rowHeight = 0; | |
317 locator.leading = 0; | |
318 lineExtent.x = 0; | |
319 lineExtent.y = 0; | |
320 width = Math.max(width, lineWidth); | |
321 newLine = true; | |
322 } | |
323 lineExtent.x += textFragment.length; | |
324 lineExtent.y = Math.max(lineHeight, lineExtent.y); | |
325 } | |
326 int lineWidth = lineExtent.x; | |
327 if (isSelectable()) | |
328 lineWidth += 1; | |
329 locator.x += lineWidth; | |
330 locator.width = width; | |
331 locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y); | |
332 locator.leading = Math.max(locator.leading, fm.getLeading()); | |
333 if (oldFont !is null) { | |
334 gc.setFont(oldFont); | |
335 } | |
336 return newLine; | |
337 } | |
338 | |
339 /** | |
340 * @param gc | |
341 * @param width | |
342 * @param locator | |
343 * @param selected | |
344 * @param selData | |
345 * @param color | |
346 * @param fm | |
347 * @param lineHeight | |
348 * @param descent | |
349 */ | |
350 private void layoutWithoutWrapping(GC gc, int width, Locator locator, | |
351 bool selected, FontMetrics fm, int lineHeight, int descent) { | |
352 Point extent = gc.textExtent(text); | |
353 int ewidth = extent.x; | |
354 if (isSelectable()) | |
355 ewidth += 1; | |
356 if (locator.x + ewidth > width-locator.marginWidth) { | |
357 // new line | |
358 locator.resetCaret(); | |
359 locator.y += locator.rowHeight; | |
360 locator.rowHeight = 0; | |
361 locator.rowCounter++; | |
362 } | |
363 int ly = locator.getBaseline(fm.getHeight() - fm.getLeading()); | |
364 //int lineY = ly + lineHeight - descent + 1; | |
365 Rectangle br = new Rectangle(locator.x, ly, ewidth, | |
366 lineHeight - descent + 3); | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
367 areaRectangles.append(new AreaRectangle(br, 0, -1)); |
75 | 368 locator.x += ewidth; |
369 locator.width = ewidth; | |
370 locator.rowHeight = Math.max(locator.rowHeight, extent.y); | |
371 } | |
372 | |
373 protected int convertOffsetToStringIndex(GC gc, String s, int x, | |
374 int swidth, int selOffset) { | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
375 int index = s.length; |
75 | 376 while (index > 0 && x + swidth > selOffset) { |
377 index--; | |
378 String ss = s.substring(0, index); | |
379 swidth = gc.textExtent(ss).x; | |
380 } | |
381 return index; | |
382 } | |
383 | |
384 public void paintFocus(GC gc, Color bg, Color fg, bool selected, | |
385 Rectangle repaintRegion) { | |
386 if (areaRectangles is null) | |
387 return; | |
388 for (int i = 0; i < areaRectangles.size(); i++) { | |
389 AreaRectangle areaRectangle = cast(AreaRectangle) areaRectangles.get(i); | |
390 Rectangle br = areaRectangle.rect; | |
391 int bx = br.x; | |
392 int by = br.y; | |
393 if (repaintRegion !is null) { | |
394 bx -= repaintRegion.x; | |
395 by -= repaintRegion.y; | |
396 } | |
397 if (selected) { | |
398 gc.setBackground(bg); | |
399 gc.setForeground(fg); | |
400 gc.drawFocus(bx, by, br.width, br.height); | |
401 } else { | |
402 gc.setForeground(bg); | |
403 gc.drawRectangle(bx, by, br.width - 1, br.height - 1); | |
404 } | |
405 } | |
406 } | |
407 | |
408 public void paint(GC gc, bool hover, Hashtable resourceTable, | |
409 bool selected, SelectionData selData, Rectangle repaintRegion) { | |
410 this.paint(gc, hover, resourceTable, selected, false, selData, | |
411 repaintRegion); | |
412 } | |
413 | |
414 protected void paint(GC gc, bool hover, Hashtable resourceTable, | |
415 bool selected, bool rollover, SelectionData selData, | |
416 Rectangle repaintRegion) { | |
417 Font oldFont = null; | |
418 Color oldColor = null; | |
419 Color oldBg = null; | |
420 | |
421 // apply segment-specific font, color and background | |
422 if (fontId !is null) { | |
423 oldFont = gc.getFont(); | |
424 Font newFont = cast(Font) resourceTable.get(fontId); | |
425 if (newFont !is null) | |
426 gc.setFont(newFont); | |
427 } | |
428 if (!hover && colorId !is null) { | |
429 oldColor = gc.getForeground(); | |
430 Color newColor = cast(Color) resourceTable.get(colorId); | |
431 if (newColor !is null) | |
432 gc.setForeground(newColor); | |
433 } | |
434 oldBg = gc.getBackground(); | |
435 | |
436 FontMetrics fm = gc.getFontMetrics(); | |
437 int lineHeight = fm.getHeight(); | |
438 int descent = fm.getDescent(); | |
439 | |
440 // paint area rectangles of the segment | |
441 for (int i = 0; i < areaRectangles.size(); i++) { | |
442 AreaRectangle areaRectangle = cast(AreaRectangle) areaRectangles.get(i); | |
443 Rectangle rect = areaRectangle.rect; | |
444 String text = areaRectangle.getText(); | |
445 Point extent = gc.textExtent(text); | |
446 int textX = rect.x + (isSelectable()?1:0); | |
447 int lineY = rect.y + lineHeight - descent + 1; | |
448 paintString(gc, text, extent.x, textX, rect.y, lineY, selData, | |
449 rect, hover, rollover, repaintRegion); | |
450 if (selected) { | |
451 int fx = rect.x; | |
452 int fy = rect.y; | |
453 if (repaintRegion !is null) { | |
454 fx -= repaintRegion.x; | |
455 fy -= repaintRegion.y; | |
456 } | |
457 //To avoid partially cancelling the focus by painting over | |
458 //X-ORed pixels, first cancel it yourself | |
459 Color fg = gc.getForeground(); | |
460 gc.setForeground(oldBg); | |
461 gc.drawRectangle(fx, fy, rect.width - 1, rect.height - 1); | |
462 gc.setForeground(fg); | |
463 gc.drawFocus(fx, fy, rect.width, rect.height); | |
464 } | |
465 } | |
466 // restore GC resources | |
467 if (oldFont !is null) { | |
468 gc.setFont(oldFont); | |
469 } | |
470 if (oldColor !is null) { | |
471 gc.setForeground(oldColor); | |
472 } | |
473 if (oldBg !is null) { | |
474 gc.setBackground(oldBg); | |
475 } | |
476 } | |
477 | |
478 public void computeSelection(GC gc, Hashtable resourceTable, SelectionData selData) { | |
479 Font oldFont = null; | |
480 | |
481 if (fontId !is null) { | |
482 oldFont = gc.getFont(); | |
483 Font newFont = cast(Font) resourceTable.get(fontId); | |
484 if (newFont !is null) | |
485 gc.setFont(newFont); | |
486 } | |
487 | |
488 for (int i = 0; i < areaRectangles.size(); i++) { | |
489 AreaRectangle areaRectangle = cast(AreaRectangle) areaRectangles.get(i); | |
490 Rectangle rect = areaRectangle.rect; | |
491 String text = areaRectangle.getText(); | |
492 Point extent = gc.textExtent(text); | |
493 computeSelection(gc, text, extent.x, selData, | |
494 rect); | |
495 } | |
496 // restore GC resources | |
497 if (oldFont !is null) { | |
498 gc.setFont(oldFont); | |
499 } | |
500 } | |
501 | |
502 private void paintString(GC gc, String s, int swidth, int x, int y, | |
503 int lineY, SelectionData selData, Rectangle bounds, bool hover, | |
504 bool rolloverMode, Rectangle repaintRegion) { | |
505 // repaints one area rectangle | |
506 if (selData !is null && selData.isEnclosed()) { | |
507 Color savedBg = gc.getBackground(); | |
508 Color savedFg = gc.getForeground(); | |
509 int leftOffset = selData.getLeftOffset(bounds.height); | |
510 int rightOffset = selData.getRightOffset(bounds.height); | |
511 bool firstRow = selData.isFirstSelectionRow(bounds.y, | |
512 bounds.height); | |
513 bool lastRow = selData.isLastSelectionRow(bounds.y, | |
514 bounds.height); | |
515 bool selectedRow = selData | |
516 .isSelectedRow(bounds.y, bounds.height); | |
517 | |
518 int sstart = -1; | |
519 int sstop = -1; | |
520 | |
521 if ((firstRow && x + swidth < leftOffset) | |
522 || (lastRow && x > rightOffset)) { | |
523 paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY, | |
524 hover, rolloverMode, repaintRegion); | |
525 return; | |
526 } | |
527 | |
528 if (firstRow && bounds.x + swidth > leftOffset) { | |
529 sstart = convertOffsetToStringIndex(gc, s, bounds.x, swidth, | |
530 leftOffset); | |
531 } | |
532 if (lastRow && bounds.x + swidth > rightOffset) { | |
533 sstop = convertOffsetToStringIndex(gc, s, bounds.x, swidth, | |
534 rightOffset); | |
535 } | |
536 | |
537 if (firstRow && sstart !is -1) { | |
538 String left = s.substring(0, sstart); | |
539 int width = gc.textExtent(left).x; | |
540 paintStringSegment(gc, left, width, x, y, lineY, hover, | |
541 rolloverMode, repaintRegion); | |
542 x += width; | |
543 } | |
544 if (selectedRow) { | |
545 int lindex = sstart !is -1 ? sstart : 0; | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
546 int rindex = sstop !is -1 ? sstop : s.length; |
75 | 547 String mid = s.substring(lindex, rindex); |
548 Point extent = gc.textExtent(mid); | |
549 gc.setForeground(selData.fg); | |
550 gc.setBackground(selData.bg); | |
551 gc.fillRectangle(x, y, extent.x, extent.y); | |
552 paintStringSegment(gc, mid, extent.x, x, y, lineY, hover, | |
553 rolloverMode, repaintRegion); | |
554 x += extent.x; | |
555 gc.setForeground(savedFg); | |
556 gc.setBackground(savedBg); | |
557 } else { | |
558 paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY, | |
559 hover, rolloverMode, repaintRegion); | |
560 } | |
561 if (lastRow && sstop !is -1) { | |
562 String right = s.substring(sstop); | |
563 paintStringSegment(gc, right, gc.textExtent(right).x, x, y, | |
564 lineY, hover, rolloverMode, repaintRegion); | |
565 } | |
566 } else { | |
567 paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY, hover, | |
568 rolloverMode, repaintRegion); | |
569 } | |
570 } | |
571 | |
572 private void computeSelection(GC gc, String s, int swidth, SelectionData selData, Rectangle bounds) { | |
573 int leftOffset = selData.getLeftOffset(bounds.height); | |
574 int rightOffset = selData.getRightOffset(bounds.height); | |
575 bool firstRow = selData.isFirstSelectionRow(bounds.y, bounds.height); | |
576 bool lastRow = selData.isLastSelectionRow(bounds.y, bounds.height); | |
577 bool selectedRow = selData.isSelectedRow(bounds.y, bounds.height); | |
578 | |
579 int sstart = -1; | |
580 int sstop = -1; | |
581 | |
582 if (firstRow && bounds.x + swidth > leftOffset) { | |
583 sstart = convertOffsetToStringIndex(gc, s, bounds.x, swidth, | |
584 leftOffset); | |
585 } | |
586 if (lastRow && bounds.x + swidth > rightOffset) { | |
587 sstop = convertOffsetToStringIndex(gc, s, bounds.x, swidth, | |
588 rightOffset); | |
589 } | |
590 | |
591 if (selectedRow) { | |
592 int lindex = sstart !is -1 ? sstart : 0; | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
593 int rindex = sstop !is -1 ? sstop : s.length; |
75 | 594 String mid = s.substring(lindex, rindex); |
595 selData.addSegment(mid); | |
596 } | |
597 } | |
598 | |
599 /** | |
600 * @param gc | |
601 * @param s | |
602 * @param x | |
603 * @param y | |
604 * @param lineY | |
605 * @param hover | |
606 * @param rolloverMode | |
607 */ | |
608 private void paintStringSegment(GC gc, String s, int swidth, int x, int y, | |
609 int lineY, bool hover, bool rolloverMode, | |
610 Rectangle repaintRegion) { | |
611 bool reverse = false; | |
612 int clipX = x; | |
613 int clipY = y; | |
614 int clipLineY = lineY; | |
615 if (repaintRegion !is null) { | |
616 clipX -= repaintRegion.x; | |
617 clipY -= repaintRegion.y; | |
618 clipLineY -= repaintRegion.y; | |
619 } | |
620 if (underline || hover || rolloverMode) { | |
621 if (rolloverMode && !hover) | |
622 reverse = true; | |
623 } | |
624 if (reverse) { | |
625 drawUnderline(gc, swidth, clipX, clipLineY, hover, rolloverMode); | |
626 gc.drawString(s, clipX, clipY, false); | |
627 } else { | |
628 gc.drawString(s, clipX, clipY, false); | |
629 drawUnderline(gc, swidth, clipX, clipLineY, hover, rolloverMode); | |
630 } | |
631 } | |
632 | |
633 private void drawUnderline(GC gc, int swidth, int x, int y, bool hover, | |
634 bool rolloverMode) { | |
635 if (underline || hover || rolloverMode) { | |
636 Color saved = null; | |
637 if (rolloverMode && !hover) { | |
638 saved = gc.getForeground(); | |
639 gc.setForeground(gc.getBackground()); | |
640 } | |
641 gc.drawLine(x, y, x + swidth-1, y); | |
642 if (saved !is null) | |
643 gc.setForeground(saved); | |
644 } | |
645 } | |
646 | |
647 /* | |
648 * (non-Javadoc) | |
649 * | |
650 * @see dwtx.ui.internal.forms.widgets.ParagraphSegment#layout(dwt.graphics.GC, | |
651 * int, dwtx.ui.internal.forms.widgets.Locator, | |
652 * java.util.Hashtable, bool, | |
653 * dwtx.ui.internal.forms.widgets.SelectionData) | |
654 */ | |
655 public void layout(GC gc, int width, Locator locator, | |
656 Hashtable resourceTable, bool selected) { | |
657 Font oldFont = null; | |
658 | |
659 areaRectangles.clear(); | |
660 | |
661 if (fontId !is null) { | |
662 oldFont = gc.getFont(); | |
663 Font newFont = cast(Font) resourceTable.get(fontId); | |
664 if (newFont !is null) | |
665 gc.setFont(newFont); | |
666 } | |
667 FontMetrics fm = gc.getFontMetrics(); | |
668 int lineHeight = fm.getHeight(); | |
669 int descent = fm.getDescent(); | |
670 | |
671 if (!wrapAllowed) { | |
672 layoutWithoutWrapping(gc, width, locator, selected, fm, lineHeight, | |
673 descent); | |
674 } else { | |
675 int lineStart = 0; | |
676 int lastLoc = 0; | |
677 Point lineExtent = new Point(0, 0); | |
678 computeTextFragments(gc); | |
679 int rightEdge = width-locator.marginWidth; | |
680 for (int i = 0; i < textFragments.length; i++) { | |
681 TextFragment fragment = textFragments[i]; | |
682 int breakLoc = fragment.index; | |
683 if (breakLoc is 0) | |
684 continue; | |
685 if (i !is 0 && locator.x + lineExtent.x + fragment.length > rightEdge) { | |
686 // overflow | |
687 int lineWidth = locator.x + lineExtent.x; | |
688 if (isSelectable()) | |
689 lineWidth += 1; | |
690 int ly = locator.getBaseline(lineHeight - fm.getLeading()); | |
691 Rectangle br = new Rectangle(isSelectable()? | |
692 locator.x - 1:locator.x, ly, | |
693 isSelectable()?lineExtent.x + 1:lineExtent.x, lineHeight - descent + 3); | |
694 areaRectangles | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
695 .append(new AreaRectangle(br, lineStart, lastLoc)); |
75 | 696 |
697 locator.rowHeight = Math.max(locator.rowHeight, | |
698 lineExtent.y); | |
699 locator.resetCaret(); | |
700 if (isSelectable()) | |
701 locator.x += 1; | |
702 locator.y += locator.rowHeight; | |
703 locator.rowCounter++; | |
704 locator.rowHeight = 0; | |
705 lineStart = lastLoc; | |
706 lineExtent.x = 0; | |
707 lineExtent.y = 0; | |
708 } | |
709 lastLoc = breakLoc; | |
710 lineExtent.x += fragment.length; | |
711 lineExtent.y = Math.max(lineHeight, lineExtent.y); | |
712 } | |
713 //String lastLine = text.substring(lineStart, lastLoc); | |
714 int ly = locator.getBaseline(lineHeight - fm.getLeading()); | |
715 int lastWidth = lineExtent.x; | |
716 if (isSelectable()) | |
717 lastWidth += 1; | |
718 Rectangle br = new Rectangle(isSelectable()?locator.x - 1:locator.x, ly, | |
719 isSelectable()?lineExtent.x + 1:lineExtent.x, | |
720 lineHeight - descent + 3); | |
721 //int lineY = ly + lineHeight - descent + 1; | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
722 areaRectangles.append(new AreaRectangle(br, lineStart, lastLoc)); |
75 | 723 locator.x += lastWidth; |
724 locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y); | |
725 } | |
726 if (oldFont !is null) { | |
727 gc.setFont(oldFont); | |
728 } | |
729 } | |
730 | |
731 private void computeTextFragments(GC gc) { | |
732 if (textFragments !is null) | |
733 return; | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
734 ArraySeq!(Object) list = new ArraySeq!(Object); |
75 | 735 BreakIterator wb = BreakIterator.getLineInstance(); |
736 wb.setText(getText()); | |
737 int cursor = 0; | |
738 for (int loc = wb.first(); loc !is BreakIterator.DONE; loc = wb.next()) { | |
739 if (loc is 0) | |
740 continue; | |
741 String word = text.substring(cursor, loc); | |
742 Point extent = gc.textExtent(word); | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
743 list.append(new TextFragment(cast(short) loc, cast(short) extent.x)); |
75 | 744 cursor = loc; |
745 } | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
746 textFragments = arraycast!(TextFragment)(list.toArray()); |
75 | 747 } |
748 | |
749 public void clearCache(String fontId) { | |
77
26c6c9dfd13c
ui.forms compile, just FormTextModel with xml reimpl left todo
Frank Benoit <benoit@tionex.de>
parents:
75
diff
changeset
|
750 if (fontId is null && (this.fontId is null||this.fontId.equals(FormTextModel.BOLD_FONT_ID))) |
75 | 751 textFragments = null; |
752 else if (fontId !is null && this.fontId !is null && fontId.equals(this.fontId)) | |
753 textFragments = null; | |
754 } | |
755 } |