Mercurial > projects > dwt-addons
annotate dwtx/ui/forms/widgets/FormText.d @ 192:c3583c6ec027
Added missing default cases for switch statements
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 03 Nov 2008 22:52:26 +0100 |
parents | 04b47443bb01 |
children |
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.forms.widgets.FormText; | |
14 | |
15 import dwtx.ui.forms.widgets.ILayoutExtension; | |
16 import dwtx.ui.forms.widgets.Form; | |
17 | |
18 import dwt.DWT; | |
19 import dwt.DWTException; | |
20 import dwt.accessibility.ACC; | |
21 import dwt.accessibility.Accessible; | |
22 import dwt.accessibility.AccessibleAdapter; | |
23 import dwt.accessibility.AccessibleControlAdapter; | |
24 import dwt.accessibility.AccessibleControlEvent; | |
25 import dwt.accessibility.AccessibleEvent; | |
26 import dwt.custom.ScrolledComposite; | |
27 import dwt.dnd.Clipboard; | |
28 import dwt.dnd.TextTransfer; | |
29 import dwt.dnd.Transfer; | |
30 import dwt.events.DisposeEvent; | |
31 import dwt.events.DisposeListener; | |
32 import dwt.events.FocusEvent; | |
33 import dwt.events.FocusListener; | |
34 import dwt.events.MenuEvent; | |
35 import dwt.events.MenuListener; | |
36 import dwt.events.MouseEvent; | |
37 import dwt.events.MouseListener; | |
38 import dwt.events.MouseMoveListener; | |
39 import dwt.events.MouseTrackListener; | |
40 import dwt.events.PaintEvent; | |
41 import dwt.events.PaintListener; | |
42 import dwt.events.SelectionAdapter; | |
43 import dwt.events.SelectionEvent; | |
44 import dwt.events.SelectionListener; | |
45 import dwt.graphics.Color; | |
46 import dwt.graphics.Font; | |
47 import dwt.graphics.FontMetrics; | |
48 import dwt.graphics.GC; | |
49 import dwt.graphics.Image; | |
50 import dwt.graphics.Point; | |
51 import dwt.graphics.Rectangle; | |
52 import dwt.widgets.Canvas; | |
53 import dwt.widgets.Composite; | |
54 import dwt.widgets.Control; | |
55 import dwt.widgets.Event; | |
56 import dwt.widgets.Layout; | |
57 import dwt.widgets.Listener; | |
58 import dwt.widgets.Menu; | |
59 import dwt.widgets.MenuItem; | |
60 import dwt.widgets.TypedListener; | |
61 import dwtx.core.runtime.ListenerList; | |
62 import dwtx.ui.forms.HyperlinkSettings; | |
63 import dwtx.ui.forms.events.HyperlinkEvent; | |
64 import dwtx.ui.forms.events.IHyperlinkListener; | |
65 import dwtx.ui.internal.forms.Messages; | |
66 import dwtx.ui.internal.forms.widgets.ControlSegment; | |
67 import dwtx.ui.internal.forms.widgets.FormFonts; | |
68 import dwtx.ui.internal.forms.widgets.FormTextModel; | |
69 import dwtx.ui.internal.forms.widgets.FormUtil; | |
70 import dwtx.ui.internal.forms.widgets.IFocusSelectable; | |
71 import dwtx.ui.internal.forms.widgets.IHyperlinkSegment; | |
72 import dwtx.ui.internal.forms.widgets.ImageSegment; | |
73 import dwtx.ui.internal.forms.widgets.Locator; | |
74 import dwtx.ui.internal.forms.widgets.Paragraph; | |
75 import dwtx.ui.internal.forms.widgets.ParagraphSegment; | |
76 import dwtx.ui.internal.forms.widgets.SelectionData; | |
77 import dwtx.ui.internal.forms.widgets.TextSegment; | |
78 | |
79 import dwt.dwthelper.utils; | |
80 import dwt.dwthelper.InputStream; | |
81 import tango.io.Stdout; | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
82 import dwtx.dwtxhelper.Collection; |
75 | 83 |
84 /** | |
85 * This class is a read-only text control that is capable of rendering wrapped | |
86 * text. Text can be rendered as-is or by parsing the formatting XML tags. | |
87 * Independently, words that start with http:// can be converted into hyperlinks | |
88 * on the fly. | |
89 * <p> | |
90 * When configured to use formatting XML, the control requires the root element | |
91 * <code>form</code> to be used. The following tags can be children of the | |
92 * <code>form</code> element: | |
93 * </p> | |
94 * <ul> | |
95 * <li><b>p </b>- for defining paragraphs. The following attributes are | |
96 * allowed: | |
97 * <ul> | |
98 * <li><b>vspace </b>- if set to 'false', no vertical space will be added | |
99 * (default is 'true')</li> | |
100 * </ul> | |
101 * </li> | |
102 * <li><b>li </b>- for defining list items. The following attributes are | |
103 * allowed: | |
104 * <ul> | |
105 * <li><b>vspace </b>- the same as with the <b>p </b> tag</li> | |
106 * <li><b>style </b>- could be 'bullet' (default), 'text' and 'image'</li> | |
107 * <li><b>value </b>- not used for 'bullet'. For text, it is the value of the | |
108 * text that is rendered as a bullet. For image, it is the href of the image to | |
109 * be rendered as a bullet.</li> | |
110 * <li><b>indent </b>- the number of pixels to indent the text in the list item | |
111 * </li> | |
112 * <li><b>bindent </b>- the number of pixels to indent the bullet itself</li> | |
113 * </ul> | |
114 * </li> | |
115 * </ul> | |
116 * <p> | |
117 * Text in paragraphs and list items will be wrapped according to the width of | |
118 * the control. The following tags can appear as children of either <b>p </b> or | |
119 * <b>li </b> elements: | |
120 * <ul> | |
121 * <li><b>img </b>- to render an image. Element accepts attribute 'href' that | |
122 * is a key to the <code>Image</code> set using 'setImage' method. Vertical | |
123 * position of image relative to surrounding text is optionally controlled by | |
124 * the attribute <b>align</b> that can have values <b>top</b>, <b>middle</b> | |
125 * and <b>bottom</b></li> | |
126 * <li><b>a </b>- to render a hyperlink. Element accepts attribute 'href' that | |
127 * will be provided to the hyperlink listeners via HyperlinkEvent object. The | |
128 * element also accepts 'nowrap' attribute (default is false). When set to | |
129 * 'true', the hyperlink will not be wrapped. Hyperlinks automatically created | |
130 * when 'http://' is encountered in text are not wrapped.</li> | |
131 * <li><b>b </b>- the enclosed text will use bold font.</li> | |
132 * <li><b>br </b>- forced line break (no attributes).</li> | |
133 * <li><b>span </b>- the enclosed text will have the color and font specified | |
134 * in the element attributes. Color is provided using 'color' attribute and is a | |
135 * key to the Color object set by 'setColor' method. Font is provided using | |
136 * 'font' attribute and is a key to the Font object set by 'setFont' method. As with | |
137 * hyperlinks, it is possible to block wrapping by setting 'nowrap' to true | |
138 * (false by default). | |
139 * </li> | |
140 * <li><b>control (new in 3.1)</b> - to place a control that is a child of the | |
141 * text control. Element accepts attribute 'href' that is a key to the Control | |
142 * object set using 'setControl' method. Optionally, attribute 'fill' can be set | |
143 * to <code>true</code> to make the control fill the entire width of the text. | |
144 * Form text is not responsible for creating or disposing controls, it only | |
145 * places them relative to the surrounding text. Similar to <b>img</b>, | |
146 * vertical position of the control can be set using the <b>align</b> | |
147 * attribute. In addition, <b>width</b> and <b>height</b> attributes can | |
148 * be used to force the dimensions of the control. If not used, | |
149 * the preferred control size will be used. | |
150 * </ul> | |
151 * <p> | |
152 * None of the elements can nest. For example, you cannot have <b>b </b> inside | |
153 * a <b>span </b>. This was done to keep everything simple and transparent. | |
154 * Since 3.1, an exception to this rule has been added to support nesting images | |
155 * and text inside the hyperlink tag (<b>a</b>). Image enclosed in the | |
156 * hyperlink tag acts as a hyperlink, can be clicked on and can accept and | |
157 * render selection focus. When both text and image is enclosed, selection and | |
158 * rendering will affect both as a single hyperlink. | |
159 * </p> | |
160 * <p> | |
161 * Since 3.1, it is possible to select text. Text selection can be | |
162 * programmatically accessed and also copied to clipboard. Non-textual objects | |
163 * (images, controls etc.) in the selection range are ignored. | |
164 * <p> | |
165 * Care should be taken when using this control. Form text is not an HTML | |
166 * browser and should not be treated as such. If you need complex formatting | |
167 * capabilities, use Browser widget. If you need editing capabilities and | |
168 * font/color styles of text segments is all you need, use StyleText widget. | |
169 * Finally, if all you need is to wrap text, use DWT Label widget and create it | |
170 * with DWT.WRAP style. | |
171 * | |
172 * @see FormToolkit | |
173 * @see TableWrapLayout | |
174 * @since 3.0 | |
175 */ | |
176 public class FormText : Canvas { | |
177 /** | |
178 * The object ID to be used when registering action to handle URL hyperlinks | |
179 * (those that should result in opening the web browser). Value is | |
180 * "urlHandler". | |
181 */ | |
182 public static const String URL_HANDLER_ID = "urlHandler"; //$NON-NLS-1$ | |
183 | |
184 /** | |
185 * Value of the horizontal margin (default is 0). | |
186 */ | |
187 public int marginWidth = 0; | |
188 | |
189 /** | |
190 * Value of tue vertical margin (default is 1). | |
191 */ | |
192 public int marginHeight = 1; | |
193 | |
194 // private fields | |
195 private static const bool DEBUG_TEXT = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_TEXT)); | |
196 private static const bool DEBUG_TEXTSIZE = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_TEXTSIZE)); | |
197 | |
198 private static const bool DEBUG_FOCUS = false;//"true".equalsIgnoreCase(Platform.getDebugOption(FormUtil.DEBUG_FOCUS)); | |
199 | |
200 private bool hasFocus; | |
201 | |
202 private bool paragraphsSeparated = true; | |
203 | |
204 private FormTextModel model; | |
205 | |
206 private ListenerList listeners; | |
207 | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
208 private Hashtable resourceTable; |
75 | 209 |
210 private IHyperlinkSegment entered; | |
211 | |
212 private IHyperlinkSegment armed; | |
213 | |
214 private bool mouseFocus = false; | |
215 | |
216 private bool controlFocusTransfer = false; | |
217 | |
218 private bool inSelection = false; | |
219 | |
220 private SelectionData selData; | |
221 | |
222 private static const String INTERNAL_MENU = "__internal_menu__"; //$NON-NLS-1$ | |
223 | |
224 private static const String CONTROL_KEY = "__segment__"; //$NON-NLS-1$ | |
225 | |
226 private class FormTextLayout : Layout, ILayoutExtension { | |
227 public this() { | |
228 } | |
229 | |
230 public int computeMaximumWidth(Composite parent, bool changed) { | |
231 return computeSize(parent, DWT.DEFAULT, DWT.DEFAULT, changed).x; | |
232 } | |
233 | |
234 public int computeMinimumWidth(Composite parent, bool changed) { | |
235 return computeSize(parent, 5, DWT.DEFAULT, true).x; | |
236 } | |
237 | |
238 /* | |
239 * @see Layout#computeSize(Composite, int, int, bool) | |
240 */ | |
241 public Point computeSize(Composite composite, int wHint, int hHint, | |
242 bool changed) { | |
243 long start = 0; | |
244 | |
245 if (DEBUG_TEXT) | |
246 start = System.currentTimeMillis(); | |
247 int innerWidth = wHint; | |
248 if (innerWidth !is DWT.DEFAULT) | |
249 innerWidth -= marginWidth * 2; | |
250 Point textSize = computeTextSize(innerWidth); | |
251 int textWidth = textSize.x + 2 * marginWidth; | |
252 int textHeight = textSize.y + 2 * marginHeight; | |
253 Point result = new Point(textWidth, textHeight); | |
254 if (DEBUG_TEXT) { | |
255 long stop = System.currentTimeMillis(); | |
256 Stdout.formatln("FormText computeSize: {}ms", (stop - start)); //$NON-NLS-1$ | |
257 } | |
258 if (DEBUG_TEXTSIZE) { | |
259 Stdout.formatln("FormText ({}), computeSize: wHint={}, result={}", model.getAccessibleText(), wHint, result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
260 } | |
261 return result; | |
262 } | |
263 | |
264 private Point computeTextSize(int wHint) { | |
265 Paragraph[] paragraphs = model.getParagraphs(); | |
266 GC gc = new GC(this.outer); | |
267 gc.setFont(getFont()); | |
268 Locator loc = new Locator(); | |
269 int width = wHint !is DWT.DEFAULT ? wHint : 0; | |
270 FontMetrics fm = gc.getFontMetrics(); | |
271 int lineHeight = fm.getHeight(); | |
272 bool selectableInTheLastRow = false; | |
273 for (int i = 0; i < paragraphs.length; i++) { | |
274 Paragraph p = paragraphs[i]; | |
275 if (i > 0 && getParagraphsSeparated() | |
276 && p.getAddVerticalSpace()) | |
277 loc.y += getParagraphSpacing(lineHeight); | |
278 loc.rowHeight = 0; | |
279 loc.indent = p.getIndent(); | |
280 loc.x = p.getIndent(); | |
281 ParagraphSegment[] segments = p.getSegments(); | |
282 if (segments.length > 0) { | |
283 selectableInTheLastRow = false; | |
284 int pwidth = 0; | |
285 for (int j = 0; j < segments.length; j++) { | |
286 ParagraphSegment segment = segments[j]; | |
287 segment.advanceLocator(gc, wHint, loc, resourceTable, | |
288 false); | |
289 if (wHint !is DWT.DEFAULT) { | |
290 width = Math.max(width, loc.width); | |
291 } else { | |
292 pwidth += loc.width; | |
293 } | |
294 if (null !is cast(IFocusSelectable)segment ) | |
295 selectableInTheLastRow = true; | |
296 } | |
297 if (wHint is DWT.DEFAULT) | |
298 width = Math.max(width, pwidth); | |
299 loc.y += loc.rowHeight; | |
300 } else { | |
301 // empty new line | |
302 loc.y += lineHeight; | |
303 } | |
304 } | |
305 gc.dispose(); | |
306 if (selectableInTheLastRow) | |
307 loc.y += 1; | |
308 return new Point(width, loc.y); | |
309 } | |
310 | |
311 protected void layout(Composite composite, bool flushCache) { | |
312 long start = 0; | |
313 | |
314 if (DEBUG_TEXT) { | |
315 start = System.currentTimeMillis(); | |
316 } | |
317 selData = null; | |
318 Rectangle carea = composite.getClientArea(); | |
319 if (DEBUG_TEXTSIZE) { | |
320 Stdout.formatln("FormText layout ({}), carea={}",model.getAccessibleText(),carea); //$NON-NLS-1$ //$NON-NLS-2$ | |
321 } | |
322 GC gc = new GC(composite); | |
323 gc.setFont(getFont()); | |
324 ensureBoldFontPresent(getFont()); | |
325 gc.setForeground(getForeground()); | |
326 gc.setBackground(getBackground()); | |
327 | |
328 Locator loc = new Locator(); | |
329 loc.marginWidth = marginWidth; | |
330 loc.marginHeight = marginHeight; | |
331 loc.x = marginWidth; | |
332 loc.y = marginHeight; | |
333 FontMetrics fm = gc.getFontMetrics(); | |
334 int lineHeight = fm.getHeight(); | |
335 | |
336 Paragraph[] paragraphs = model.getParagraphs(); | |
337 IHyperlinkSegment selectedLink = getSelectedLink(); | |
338 for (int i = 0; i < paragraphs.length; i++) { | |
339 Paragraph p = paragraphs[i]; | |
340 if (i > 0 && paragraphsSeparated && p.getAddVerticalSpace()) | |
341 loc.y += getParagraphSpacing(lineHeight); | |
342 loc.indent = p.getIndent(); | |
343 loc.resetCaret(); | |
344 loc.rowHeight = 0; | |
345 p.layout(gc, carea.width, loc, lineHeight, resourceTable, | |
346 selectedLink); | |
347 } | |
348 gc.dispose(); | |
349 if (DEBUG_TEXT) { | |
350 long stop = System.currentTimeMillis(); | |
351 Stdout.formatln("FormText.layout: {}ms", (stop - start)); //$NON-NLS-1$ //$NON-NLS-2$ | |
352 } | |
353 } | |
354 } | |
355 | |
356 /** | |
357 * Contructs a new form text widget in the provided parent and using the | |
358 * styles. | |
359 * | |
360 * @param parent | |
361 * form text parent control | |
362 * @param style | |
363 * the widget style | |
364 */ | |
365 public this(Composite parent, int style) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
366 resourceTable = new Hashtable(); |
75 | 367 super(parent, DWT.NO_BACKGROUND | DWT.WRAP | style); |
368 setLayout(new FormTextLayout()); | |
369 model = new FormTextModel(); | |
370 addDisposeListener(new class DisposeListener { | |
371 public void widgetDisposed(DisposeEvent e) { | |
372 model.dispose(); | |
373 disposeResourceTable(true); | |
374 } | |
375 }); | |
376 addPaintListener(new class PaintListener { | |
377 public void paintControl(PaintEvent e) { | |
378 paint(e); | |
379 } | |
380 }); | |
381 addListener(DWT.KeyDown, new class Listener { | |
382 public void handleEvent(Event e) { | |
383 if (e.character is '\r') { | |
384 activateSelectedLink(); | |
385 return; | |
386 } | |
387 } | |
388 }); | |
389 addListener(DWT.Traverse, new class Listener { | |
390 public void handleEvent(Event e) { | |
391 if (DEBUG_FOCUS) | |
392 Stdout.formatln("Traversal: {}", e); //$NON-NLS-1$ | |
393 switch (e.detail) { | |
394 case DWT.TRAVERSE_PAGE_NEXT: | |
395 case DWT.TRAVERSE_PAGE_PREVIOUS: | |
396 case DWT.TRAVERSE_ARROW_NEXT: | |
397 case DWT.TRAVERSE_ARROW_PREVIOUS: | |
398 e.doit = false; | |
399 return; | |
192
c3583c6ec027
Added missing default cases for switch statements
Frank Benoit <benoit@tionex.de>
parents:
104
diff
changeset
|
400 default: |
75 | 401 } |
402 if (!model.hasFocusSegments()) { | |
403 e.doit = true; | |
404 return; | |
405 } | |
406 if (e.detail is DWT.TRAVERSE_TAB_NEXT) | |
407 e.doit = advance(true); | |
408 else if (e.detail is DWT.TRAVERSE_TAB_PREVIOUS) | |
409 e.doit = advance(false); | |
410 else if (e.detail !is DWT.TRAVERSE_RETURN) | |
411 e.doit = true; | |
412 } | |
413 }); | |
414 addFocusListener(new class FocusListener { | |
415 public void focusGained(FocusEvent e) { | |
416 if (!hasFocus) { | |
417 hasFocus = true; | |
418 if (DEBUG_FOCUS) { | |
419 Stdout.formatln("FormText: focus gained"); //$NON-NLS-1$ | |
420 } | |
421 if (!mouseFocus && !controlFocusTransfer) { | |
422 handleFocusChange(); | |
423 } | |
424 } | |
425 } | |
426 | |
427 public void focusLost(FocusEvent e) { | |
428 if (DEBUG_FOCUS) { | |
429 Stdout.formatln("FormText: focus lost"); //$NON-NLS-1$ | |
430 } | |
431 if (hasFocus) { | |
432 hasFocus = false; | |
433 if (!controlFocusTransfer) | |
434 handleFocusChange(); | |
435 } | |
436 } | |
437 }); | |
438 addMouseListener(new class MouseListener { | |
439 public void mouseDoubleClick(MouseEvent e) { | |
440 } | |
441 | |
442 public void mouseDown(MouseEvent e) { | |
443 // select a link | |
444 handleMouseClick(e, true); | |
445 } | |
446 | |
447 public void mouseUp(MouseEvent e) { | |
448 // activate a link | |
449 handleMouseClick(e, false); | |
450 } | |
451 }); | |
452 addMouseTrackListener(new class MouseTrackListener { | |
453 public void mouseEnter(MouseEvent e) { | |
454 handleMouseMove(e); | |
455 } | |
456 | |
457 public void mouseExit(MouseEvent e) { | |
458 if (entered !is null) { | |
459 exitLink(entered, e.stateMask); | |
460 paintLinkHover(entered, false); | |
461 entered = null; | |
462 setCursor(null); | |
463 } | |
464 } | |
465 | |
466 public void mouseHover(MouseEvent e) { | |
467 handleMouseHover(e); | |
468 } | |
469 }); | |
470 addMouseMoveListener(new class MouseMoveListener { | |
471 public void mouseMove(MouseEvent e) { | |
472 handleMouseMove(e); | |
473 } | |
474 }); | |
475 initAccessible(); | |
476 ensureBoldFontPresent(getFont()); | |
477 createMenu(); | |
478 // we will handle traversal of controls, if any | |
479 setTabList(cast(Control[])null); | |
480 } | |
481 | |
482 /** | |
483 * Test for focus. | |
484 * | |
485 * @return <samp>true </samp> if the widget has focus. | |
486 */ | |
487 public bool getFocus() { | |
488 return hasFocus; | |
489 } | |
490 | |
491 /** | |
492 * Test if the widget is currently processing the text it is about to | |
493 * render. | |
494 * | |
495 * @return <samp>true </samp> if the widget is still loading the text, | |
496 * <samp>false </samp> otherwise. | |
497 * @deprecated not used any more - returns <code>false</code> | |
498 */ | |
499 public bool isLoading() { | |
500 return false; | |
501 } | |
502 | |
503 /** | |
504 * Returns the text that will be shown in the control while the real content | |
505 * is loading. | |
506 * | |
507 * @return loading text message | |
508 * @deprecated loading text is not used since 3.1 | |
509 */ | |
510 public String getLoadingText() { | |
511 return null; | |
512 } | |
513 | |
514 /** | |
515 * Sets the text that will be shown in the control while the real content is | |
516 * loading. This is significant when content to render is loaded from the | |
517 * input stream that was created from a remote URL, and the time to load the | |
518 * entire content is nontrivial. | |
519 * | |
520 * @param loadingText | |
521 * loading text message | |
522 * @deprecated use setText(loadingText, false, false); | |
523 */ | |
524 public void setLoadingText(String loadingText) { | |
525 setText(loadingText, false, false); | |
526 } | |
527 | |
528 /** | |
529 * If paragraphs are separated, spacing will be added between them. | |
530 * Otherwise, new paragraphs will simply start on a new line with no | |
531 * spacing. | |
532 * | |
533 * @param value | |
534 * <samp>true </samp> if paragraphs are separated, </samp> false | |
535 * </samp> otherwise. | |
536 */ | |
537 public void setParagraphsSeparated(bool value) { | |
538 paragraphsSeparated = value; | |
539 } | |
540 | |
541 /** | |
542 * Tests if there is some inter-paragraph spacing. | |
543 * | |
544 * @return <samp>true </samp> if paragraphs are separated, <samp>false | |
545 * </samp> otherwise. | |
546 */ | |
547 public bool getParagraphsSeparated() { | |
548 return paragraphsSeparated; | |
549 } | |
550 | |
551 /** | |
552 * Registers the image referenced by the provided key. | |
553 * <p> | |
554 * For <samp>img </samp> tags, an object of a type <samp>Image </samp> must | |
555 * be registered using the key equivalent to the value of the <samp>href | |
556 * </samp> attribute used in the tag. | |
557 * | |
558 * @param key | |
559 * unique key that matches the value of the <samp>href </samp> | |
560 * attribute. | |
561 * @param image | |
562 * an object of a type <samp>Image </samp>. | |
563 */ | |
564 public void setImage(String key, Image image) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
565 resourceTable.put("i." ~ key, image); //$NON-NLS-1$ |
75 | 566 } |
567 | |
568 /** | |
569 * Registers the color referenced by the provided key. | |
570 * <p> | |
571 * For <samp>span </samp> tags, an object of a type <samp>Color </samp> must | |
572 * be registered using the key equivalent to the value of the <samp>color | |
573 * </samp> attribute. | |
574 * | |
575 * @param key | |
576 * unique key that matches the value of the <samp>color </samp> | |
577 * attribute. | |
578 * @param color | |
579 * an object of the type <samp>Color </samp> or <samp>null</samp> | |
580 * if the key needs to be cleared. | |
581 */ | |
582 public void setColor(String key, Color color) { | |
583 String fullKey = "c." ~ key; //$NON-NLS-1$ | |
584 if (color is null) | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
585 resourceTable.remove(fullKey); |
75 | 586 else |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
587 resourceTable.put(fullKey, color); |
75 | 588 } |
589 | |
590 /** | |
591 * Registers the font referenced by the provided key. | |
592 * <p> | |
593 * For <samp>span </samp> tags, an object of a type <samp>Font </samp> must | |
594 * be registered using the key equivalent to the value of the <samp>font | |
595 * </samp> attribute. | |
596 * | |
597 * @param key | |
598 * unique key that matches the value of the <samp>font </samp> | |
599 * attribute. | |
600 * @param font | |
601 * an object of the type <samp>Font </samp> or <samp>null</samp> | |
602 * if the key needs to be cleared. | |
603 */ | |
604 public void setFont(String key, Font font) { | |
605 String fullKey = "f." ~ key; //$NON-NLS-1$ | |
606 if (font is null) | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
607 resourceTable.remove(fullKey); |
75 | 608 else |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
609 resourceTable.put(fullKey, font); |
75 | 610 model.clearCache(fullKey); |
611 } | |
612 | |
613 /** | |
614 * Registers the control referenced by the provided key. | |
615 * <p> | |
616 * For <samp>control</samp> tags, an object of a type <samp>Control</samp> | |
617 * must be registered using the key equivalent to the value of the | |
618 * <samp>control</samp> attribute. | |
619 * | |
620 * @param key | |
621 * unique key that matches the value of the <samp>control</samp> | |
622 * attribute. | |
623 * @param control | |
624 * an object of the type <samp>Control</samp> or <samp>null</samp> | |
625 * if the existing control at the specified key needs to be | |
626 * removed. | |
627 * @since 3.1 | |
628 */ | |
629 public void setControl(String key, Control control) { | |
630 String fullKey = "o." ~ key; //$NON-NLS-1$ | |
631 if (control is null) | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
632 resourceTable.remove(fullKey); |
75 | 633 else |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
634 resourceTable.put(fullKey, control); |
75 | 635 } |
636 | |
637 /** | |
638 * Sets the font to use to render the default text (text that does not have | |
639 * special font property assigned). Bold font will be constructed from this | |
640 * font. | |
641 * | |
642 * @param font | |
643 * the default font to use | |
644 */ | |
645 public void setFont(Font font) { | |
646 super.setFont(font); | |
647 model.clearCache(null); | |
648 Font boldFont = cast(Font) resourceTable.get(FormTextModel.BOLD_FONT_ID); | |
649 if (boldFont !is null) { | |
650 FormFonts.getInstance().markFinished(boldFont); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
651 resourceTable.remove(FormTextModel.BOLD_FONT_ID); |
75 | 652 } |
653 ensureBoldFontPresent(getFont()); | |
654 } | |
655 | |
656 /** | |
657 * Sets the provided text. Text can be rendered as-is, or by parsing the | |
658 * formatting tags. Optionally, sections of text starting with http:// will | |
659 * be converted to hyperlinks. | |
660 * | |
661 * @param text | |
662 * the text to render | |
663 * @param parseTags | |
664 * if <samp>true </samp>, formatting tags will be parsed. | |
665 * Otherwise, text will be rendered as-is. | |
666 * @param expandURLs | |
667 * if <samp>true </samp>, URLs found in the untagged text will be | |
668 * converted into hyperlinks. | |
669 */ | |
670 public void setText(String text, bool parseTags, bool expandURLs) { | |
671 disposeResourceTable(false); | |
672 entered = null; | |
673 if (parseTags) | |
674 model.parseTaggedText(text, expandURLs); | |
675 else | |
676 model.parseRegularText(text, expandURLs); | |
677 hookControlSegmentFocus(); | |
678 layout(); | |
679 redraw(); | |
680 } | |
681 | |
682 /** | |
683 * Sets the contents of the stream. Optionally, URLs in untagged text can be | |
684 * converted into hyperlinks. The caller is responsible for closing the | |
685 * stream. | |
686 * | |
687 * @param is | |
688 * stream to render | |
689 * @param expandURLs | |
690 * if <samp>true </samp>, URLs found in untagged text will be | |
691 * converted into hyperlinks. | |
692 */ | |
693 public void setContents(InputStream is_, bool expandURLs) { | |
694 entered = null; | |
695 disposeResourceTable(false); | |
696 model.parseInputStream(is_, expandURLs); | |
697 hookControlSegmentFocus(); | |
698 layout(); | |
699 redraw(); | |
700 } | |
701 | |
702 private void hookControlSegmentFocus() { | |
703 Paragraph[] paragraphs = model.getParagraphs(); | |
704 if (paragraphs is null) | |
705 return; | |
706 Listener listener = new class Listener { | |
707 public void handleEvent(Event e) { | |
708 switch (e.type) { | |
709 case DWT.FocusIn: | |
710 if (!controlFocusTransfer) | |
711 syncControlSegmentFocus(cast(Control) e.widget); | |
712 break; | |
713 case DWT.Traverse: | |
714 if (DEBUG_FOCUS) | |
715 Stdout.formatln("Control traversal: {}", e); //$NON-NLS-1$ | |
716 switch (e.detail) { | |
717 case DWT.TRAVERSE_PAGE_NEXT: | |
718 case DWT.TRAVERSE_PAGE_PREVIOUS: | |
719 case DWT.TRAVERSE_ARROW_NEXT: | |
720 case DWT.TRAVERSE_ARROW_PREVIOUS: | |
721 e.doit = false; | |
722 return; | |
192
c3583c6ec027
Added missing default cases for switch statements
Frank Benoit <benoit@tionex.de>
parents:
104
diff
changeset
|
723 default: |
75 | 724 } |
725 Control c = cast(Control) e.widget; | |
726 ControlSegment segment = cast(ControlSegment) c | |
727 .getData(CONTROL_KEY); | |
728 if (e.detail is DWT.TRAVERSE_TAB_NEXT) | |
729 e.doit = advanceControl(c, segment, true); | |
730 else if (e.detail is DWT.TRAVERSE_TAB_PREVIOUS) | |
731 e.doit = advanceControl(c, segment, false); | |
732 if (!e.doit) | |
733 e.detail = DWT.TRAVERSE_NONE; | |
734 break; | |
192
c3583c6ec027
Added missing default cases for switch statements
Frank Benoit <benoit@tionex.de>
parents:
104
diff
changeset
|
735 default: |
75 | 736 } |
737 } | |
738 }; | |
739 for (int i = 0; i < paragraphs.length; i++) { | |
740 Paragraph p = paragraphs[i]; | |
741 ParagraphSegment[] segments = p.getSegments(); | |
742 for (int j = 0; j < segments.length; j++) { | |
743 if (auto cs = cast(ControlSegment)segments[j] ) { | |
744 Control c = cs.getControl(resourceTable); | |
745 if (c !is null) { | |
746 if (c.getData(CONTROL_KEY) is null) { | |
747 // first time - hook | |
748 c.setData(CONTROL_KEY, cs); | |
749 attachTraverseListener(c, listener); | |
750 } | |
751 } | |
752 } | |
753 } | |
754 } | |
755 } | |
756 | |
757 private void attachTraverseListener(Control c, Listener listener) { | |
758 if ( auto parent = cast(Composite) c ) { | |
759 Control[] children = parent.getChildren(); | |
760 for (int i = 0; i < children.length; i++) { | |
761 attachTraverseListener(children[i], listener); | |
762 } | |
763 if (auto canv = cast(Canvas)c ) { | |
764 // If Canvas, the control iteself can accept | |
765 // traverse events and should be monitored | |
766 c.addListener(DWT.Traverse, listener); | |
767 c.addListener(DWT.FocusIn, listener); | |
768 } | |
769 } else { | |
770 c.addListener(DWT.Traverse, listener); | |
771 c.addListener(DWT.FocusIn, listener); | |
772 } | |
773 } | |
774 | |
775 /** | |
776 * If we click on the control randomly, our internal book-keeping will be | |
777 * off. We need to update the model and mark the control segment and | |
778 * currently selected. Hyperlink that may have had focus must also be | |
779 * exited. | |
780 * | |
781 * @param control | |
782 * the control that got focus | |
783 */ | |
784 private void syncControlSegmentFocus(Control control) { | |
785 ControlSegment cs = null; | |
786 | |
787 while (control !is null) { | |
788 cs = cast(ControlSegment) control.getData(CONTROL_KEY); | |
789 if (cs !is null) | |
790 break; | |
791 control = control.getParent(); | |
792 } | |
793 if (cs is null) | |
794 return; | |
795 IFocusSelectable current = model.getSelectedSegment(); | |
796 // If the model and the control match, all is well | |
797 if (current is cs) | |
798 return; | |
799 IHyperlinkSegment oldLink = null; | |
800 if (current !is null && null !is cast(IHyperlinkSegment)current ) { | |
801 oldLink = cast(IHyperlinkSegment) current; | |
802 exitLink(oldLink, DWT.NULL); | |
803 } | |
804 if (DEBUG_FOCUS) | |
805 Stdout.formatln("Sync control: {}, oldLink={}", cs, oldLink); //$NON-NLS-1$ //$NON-NLS-2$ | |
806 model.select(cs); | |
807 if (oldLink !is null) | |
808 paintFocusTransfer(oldLink, null); | |
809 // getAccessible().setFocus(model.getSelectedSegmentIndex()); | |
810 } | |
811 | |
812 private bool advanceControl(Control c, ControlSegment segment, | |
813 bool next) { | |
814 Composite parent = c.getParent(); | |
815 if (parent is this) { | |
816 // segment-level control | |
817 IFocusSelectable nextSegment = model.getNextFocusSegment(next); | |
818 if (nextSegment !is null) { | |
819 controlFocusTransfer = true; | |
820 super.forceFocus(); | |
821 controlFocusTransfer = false; | |
822 model.select(segment); | |
823 return advance(next); | |
824 } | |
825 // nowhere to go | |
826 return setFocusToNextSibling(this, next); | |
827 } | |
828 if (setFocusToNextSibling(c, next)) | |
829 return true; | |
830 // still here - must go one level up | |
831 segment = cast(ControlSegment) parent.getData(CONTROL_KEY); | |
832 return advanceControl(parent, segment, next); | |
833 } | |
834 | |
835 private bool setFocusToNextSibling(Control c, bool next) { | |
836 Composite parent = c.getParent(); | |
837 Control[] children = parent.getTabList(); | |
838 for (int i = 0; i < children.length; i++) { | |
839 Control child = children[i]; | |
840 if (child is c) { | |
841 // here | |
842 if (next) { | |
843 for (int j = i + 1; j < children.length; j++) { | |
844 Control nc = children[j]; | |
845 if (nc.setFocus()) | |
846 return false; | |
847 } | |
848 } else { | |
849 for (int j = i - 1; j >= 0; j--) { | |
850 Control pc = children[j]; | |
851 if (pc.setFocus()) | |
852 return false; | |
853 } | |
854 } | |
855 } | |
856 } | |
857 return false; | |
858 } | |
859 | |
860 /** | |
861 * Controls whether whitespace inside paragraph and list items is | |
862 * normalized. Note that the new value will not affect the current text in | |
863 * the control, only subsequent calls to <code>setText</code> or | |
864 * <code>setContents</code>. | |
865 * <p> | |
866 * If normalized: | |
867 * <ul> | |
868 * <li>all white space characters will be condensed into at most one when | |
869 * between words.</li> | |
870 * <li>new line characters will be ignored and replaced with one white | |
871 * space character</li> | |
872 * <li>white space characters after the opening tags and before the closing | |
873 * tags will be trimmed</li> | |
874 * | |
875 * @param value | |
876 * <code>true</code> if whitespace is normalized, | |
877 * <code>false</code> otherwise. | |
878 */ | |
879 public void setWhitespaceNormalized(bool value) { | |
880 model.setWhitespaceNormalized(value); | |
881 } | |
882 | |
883 /** | |
884 * Tests whether whitespace inside paragraph and list item is normalized. | |
885 * | |
886 * @see #setWhitespaceNormalized(bool) | |
887 * @return <code>true</code> if whitespace is normalized, | |
888 * <code>false</code> otherwise. | |
889 */ | |
890 public bool isWhitespaceNormalized() { | |
891 return model.isWhitespaceNormalized(); | |
892 } | |
893 | |
894 /** | |
895 * Disposes the internal menu if created and sets the menu provided as a | |
896 * parameter. | |
897 * | |
898 * @param menu | |
899 * the menu to associate with this text control | |
900 */ | |
901 public void setMenu(Menu menu) { | |
902 Menu currentMenu = super.getMenu(); | |
903 if (currentMenu !is null && INTERNAL_MENU.equals(stringcast(currentMenu.getData()))) { | |
904 // internal menu set | |
905 if (menu !is null) { | |
906 currentMenu.dispose(); | |
907 super.setMenu(menu); | |
908 } | |
909 } else | |
910 super.setMenu(menu); | |
911 } | |
912 | |
913 private void createMenu() { | |
914 Menu menu = new Menu(this); | |
915 final MenuItem copyItem = new MenuItem(menu, DWT.PUSH); | |
916 copyItem.setText(Messages.FormText_copy); | |
917 | |
918 SelectionListener listener = new class SelectionAdapter { | |
919 public void widgetSelected(SelectionEvent e) { | |
920 if (e.widget is copyItem) { | |
921 copy(); | |
922 } | |
923 } | |
924 }; | |
925 copyItem.addSelectionListener(listener); | |
926 menu.addMenuListener(new class MenuListener { | |
927 public void menuShown(MenuEvent e) { | |
928 copyItem.setEnabled(canCopy()); | |
929 } | |
930 | |
931 public void menuHidden(MenuEvent e) { | |
932 } | |
933 }); | |
934 menu.setData(stringcast(INTERNAL_MENU)); | |
935 super.setMenu(menu); | |
936 } | |
937 | |
938 /** | |
939 * Returns the hyperlink settings that are in effect for this control. | |
940 * | |
941 * @return current hyperlinks settings | |
942 */ | |
943 public HyperlinkSettings getHyperlinkSettings() { | |
944 return model.getHyperlinkSettings(); | |
945 } | |
946 | |
947 /** | |
948 * Sets the hyperlink settings to be used for this control. Settings will | |
949 * affect things like hyperlink color, rendering style, cursor etc. | |
950 * | |
951 * @param settings | |
952 * hyperlink settings for this control | |
953 */ | |
954 public void setHyperlinkSettings(HyperlinkSettings settings) { | |
955 model.setHyperlinkSettings(settings); | |
956 } | |
957 | |
958 /** | |
959 * Adds a listener that will handle hyperlink events. | |
960 * | |
961 * @param listener | |
962 * the listener to add | |
963 */ | |
964 public void addHyperlinkListener(IHyperlinkListener listener) { | |
965 if (listeners is null) | |
966 listeners = new ListenerList(); | |
967 listeners.add(cast(Object)listener); | |
968 } | |
969 | |
970 /** | |
971 * Removes the hyperlink listener. | |
972 * | |
973 * @param listener | |
974 * the listener to remove | |
975 */ | |
976 public void removeHyperlinkListener(IHyperlinkListener listener) { | |
977 if (listeners is null) | |
978 return; | |
979 listeners.remove(cast(Object)listener); | |
980 } | |
981 | |
982 /** | |
983 * Adds a selection listener. A Selection event is sent by the widget when | |
984 * the selection has changed. | |
985 * <p> | |
986 * <code>widgetDefaultSelected</code> is not called for FormText. | |
987 * </p> | |
988 * | |
989 * @param listener | |
990 * the listener | |
991 * @exception DWTException | |
992 * <ul> | |
993 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been | |
994 * disposed</li> | |
995 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the | |
996 * thread that created the receiver</li> | |
997 * </ul> | |
998 * @exception IllegalArgumentException | |
999 * <ul> | |
1000 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | |
1001 * </ul> | |
1002 * @since 3.1 | |
1003 */ | |
1004 public void addSelectionListener(SelectionListener listener) { | |
1005 checkWidget(); | |
1006 if (listener is null) { | |
1007 DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
1008 } | |
1009 TypedListener typedListener = new TypedListener(listener); | |
1010 addListener(DWT.Selection, typedListener); | |
1011 } | |
1012 | |
1013 /** | |
1014 * Removes the specified selection listener. | |
1015 * <p> | |
1016 * | |
1017 * @param listener | |
1018 * the listener | |
1019 * @exception DWTException | |
1020 * <ul> | |
1021 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been | |
1022 * disposed</li> | |
1023 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the | |
1024 * thread that created the receiver</li> | |
1025 * </ul> | |
1026 * @exception IllegalArgumentException | |
1027 * <ul> | |
1028 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | |
1029 * </ul> | |
1030 * @since 3.1 | |
1031 */ | |
1032 public void removeSelectionListener(SelectionListener listener) { | |
1033 checkWidget(); | |
1034 if (listener is null) { | |
1035 DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
1036 } | |
1037 removeListener(DWT.Selection, listener); | |
1038 } | |
1039 | |
1040 /** | |
1041 * Returns the selected text. | |
1042 * <p> | |
1043 * | |
1044 * @return selected text, or an empty String if there is no selection. | |
1045 * @exception DWTException | |
1046 * <ul> | |
1047 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been | |
1048 * disposed</li> | |
1049 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the | |
1050 * thread that created the receiver</li> | |
1051 * </ul> | |
1052 * @since 3.1 | |
1053 */ | |
1054 | |
1055 public String getSelectionText() { | |
1056 checkWidget(); | |
1057 if (selData !is null) | |
1058 return selData.getSelectionText(); | |
1059 return ""; //$NON-NLS-1$ | |
1060 } | |
1061 | |
1062 /** | |
1063 * Tests if the text is selected and can be copied into the clipboard. | |
1064 * | |
1065 * @return <code>true</code> if the selected text can be copied into the | |
1066 * clipboard, <code>false</code> otherwise. | |
1067 * @since 3.1 | |
1068 */ | |
1069 public bool canCopy() { | |
1070 return selData !is null && selData.canCopy(); | |
1071 } | |
1072 | |
1073 /** | |
1074 * Copies the selected text into the clipboard. Does nothing if no text is | |
1075 * selected or the text cannot be copied for any other reason. | |
1076 * | |
1077 * @since 3.1 | |
1078 */ | |
1079 | |
1080 public void copy() { | |
1081 if (!canCopy()) | |
1082 return; | |
1083 Clipboard clipboard = new Clipboard(getDisplay()); | |
1084 Object[] o = [ stringcast(getSelectionText()) ]; | |
1085 Transfer[] t = [ TextTransfer.getInstance() ]; | |
1086 clipboard.setContents(o, t); | |
1087 clipboard.dispose(); | |
1088 } | |
1089 | |
1090 /** | |
1091 * Returns the reference of the hyperlink that currently has keyboard focus, | |
1092 * or <code>null</code> if there are no hyperlinks in the receiver or no | |
1093 * hyperlink has focus at the moment. | |
1094 * | |
1095 * @return href of the selected hyperlink or <code>null</code> if none | |
1096 * selected. | |
1097 * @since 3.1 | |
1098 */ | |
1099 public Object getSelectedLinkHref() { | |
1100 IHyperlinkSegment link = getSelectedLink(); | |
1101 return link !is null ? stringcast(link.getHref()) : null; | |
1102 } | |
1103 | |
1104 /** | |
1105 * Returns the text of the hyperlink that currently has keyboard focus, or | |
1106 * <code>null</code> if there are no hyperlinks in the receiver or no | |
1107 * hyperlink has focus at the moment. | |
1108 * | |
1109 * @return text of the selected hyperlink or <code>null</code> if none | |
1110 * selected. | |
1111 * @since 3.1 | |
1112 */ | |
1113 public String getSelectedLinkText() { | |
1114 IHyperlinkSegment link = getSelectedLink(); | |
1115 return link !is null ? link.getText() : null; | |
1116 } | |
1117 | |
1118 private IHyperlinkSegment getSelectedLink() { | |
1119 IFocusSelectable segment = model.getSelectedSegment(); | |
1120 if (segment !is null && null !is cast(IHyperlinkSegment)segment ) | |
1121 return cast(IHyperlinkSegment) segment; | |
1122 return null; | |
1123 } | |
1124 | |
1125 private void initAccessible() { | |
1126 Accessible accessible = getAccessible(); | |
1127 accessible.addAccessibleListener(new class AccessibleAdapter { | |
1128 public void getName(AccessibleEvent e) { | |
1129 if (e.childID is ACC.CHILDID_SELF) | |
1130 e.result = model.getAccessibleText(); | |
1131 else { | |
1132 int linkCount = model.getHyperlinkCount(); | |
1133 if (e.childID >= 0 && e.childID < linkCount) { | |
1134 IHyperlinkSegment link = model.getHyperlink(e.childID); | |
1135 e.result = link.getText(); | |
1136 } | |
1137 } | |
1138 } | |
1139 | |
1140 public void getHelp(AccessibleEvent e) { | |
1141 e.result = getToolTipText(); | |
1142 int linkCount = model.getHyperlinkCount(); | |
1143 if (e.result is null && e.childID >= 0 && e.childID < linkCount) { | |
1144 IHyperlinkSegment link = model.getHyperlink(e.childID); | |
1145 e.result = link.getText(); | |
1146 } | |
1147 } | |
1148 }); | |
1149 accessible.addAccessibleControlListener(new class AccessibleControlAdapter { | |
1150 public void getChildAtPoint(AccessibleControlEvent e) { | |
1151 Point pt = toControl(new Point(e.x, e.y)); | |
1152 IHyperlinkSegment link = model.findHyperlinkAt(pt.x, pt.y); | |
1153 if (link !is null) | |
1154 e.childID = model.indexOf(link); | |
1155 else | |
1156 e.childID = ACC.CHILDID_SELF; | |
1157 } | |
1158 | |
1159 public void getLocation(AccessibleControlEvent e) { | |
1160 Rectangle location = null; | |
1161 if (e.childID !is ACC.CHILDID_SELF | |
1162 && e.childID !is ACC.CHILDID_NONE) { | |
1163 int index = e.childID; | |
1164 IHyperlinkSegment link = model.getHyperlink(index); | |
1165 if (link !is null) { | |
1166 location = link.getBounds(); | |
1167 } | |
1168 } | |
1169 if (location is null) { | |
1170 location = getBounds(); | |
1171 } | |
1172 Point pt = toDisplay(new Point(location.x, location.y)); | |
1173 e.x = pt.x; | |
1174 e.y = pt.y; | |
1175 e.width = location.width; | |
1176 e.height = location.height; | |
1177 } | |
1178 | |
1179 public void getFocus(AccessibleControlEvent e) { | |
1180 int childID = ACC.CHILDID_NONE; | |
1181 | |
1182 if (model.hasFocusSegments()) { | |
1183 int selectedIndex = model.getSelectedSegmentIndex(); | |
1184 if (selectedIndex !is -1) { | |
1185 childID = selectedIndex; | |
1186 } | |
1187 } | |
1188 e.childID = childID; | |
1189 } | |
1190 | |
1191 public void getDefaultAction (AccessibleControlEvent e) { | |
1192 if (model.getHyperlinkCount() > 0) { | |
1193 e.result = DWT.getMessage ("SWT_Press"); //$NON-NLS-1$ | |
1194 } | |
1195 } | |
1196 | |
1197 public void getChildCount(AccessibleControlEvent e) { | |
1198 e.detail = model.getHyperlinkCount(); | |
1199 } | |
1200 | |
1201 public void getRole(AccessibleControlEvent e) { | |
1202 int role = 0; | |
1203 int childID = e.childID; | |
1204 int linkCount = model.getHyperlinkCount(); | |
1205 if (childID is ACC.CHILDID_SELF) { | |
1206 if (linkCount > 0) { | |
1207 role = ACC.ROLE_LINK; | |
1208 } else { | |
1209 role = ACC.ROLE_TEXT; | |
1210 } | |
1211 } else if (childID >= 0 && childID < linkCount) { | |
1212 role = ACC.ROLE_LINK; | |
1213 } | |
1214 e.detail = role; | |
1215 } | |
1216 | |
1217 public void getSelection(AccessibleControlEvent e) { | |
1218 int selectedIndex = model.getSelectedSegmentIndex(); | |
1219 e.childID = (selectedIndex is -1) ? ACC.CHILDID_NONE | |
1220 : selectedIndex; | |
1221 } | |
1222 | |
1223 public void getState(AccessibleControlEvent e) { | |
1224 int linkCount = model.getHyperlinkCount(); | |
1225 int selectedIndex = model.getSelectedSegmentIndex(); | |
1226 int state = 0; | |
1227 int childID = e.childID; | |
1228 if (childID is ACC.CHILDID_SELF) { | |
1229 state = ACC.STATE_NORMAL; | |
1230 } else if (childID >= 0 && childID < linkCount) { | |
1231 state = ACC.STATE_SELECTABLE; | |
1232 if (isFocusControl()) { | |
1233 state |= ACC.STATE_FOCUSABLE; | |
1234 } | |
1235 if (selectedIndex is childID) { | |
1236 state |= ACC.STATE_SELECTED; | |
1237 if (isFocusControl()) { | |
1238 state |= ACC.STATE_FOCUSED; | |
1239 } | |
1240 } | |
1241 } | |
1242 state |= ACC.STATE_READONLY; | |
1243 e.detail = state; | |
1244 } | |
1245 | |
1246 public void getChildren(AccessibleControlEvent e) { | |
1247 int linkCount = model.getHyperlinkCount(); | |
1248 Object[] children = new Object[linkCount]; | |
1249 for (int i = 0; i < linkCount; i++) { | |
1250 children[i] = new Integer(i); | |
1251 } | |
1252 e.children = children; | |
1253 } | |
1254 | |
1255 public void getValue(AccessibleControlEvent e) { | |
1256 // e.result = model.getAccessibleText(); | |
1257 } | |
1258 }); | |
1259 } | |
1260 | |
1261 private void startSelection(MouseEvent e) { | |
1262 inSelection = true; | |
1263 selData = new SelectionData(e); | |
1264 redraw(); | |
1265 Form form = FormUtil.getForm(this); | |
1266 if (form !is null) | |
1267 form.setSelectionText(this); | |
1268 } | |
1269 | |
1270 private void endSelection(MouseEvent e) { | |
1271 inSelection = false; | |
1272 if (selData !is null) { | |
1273 if (!selData.isEnclosed()) | |
1274 selData = null; | |
1275 else | |
1276 computeSelection(); | |
1277 } | |
1278 notifySelectionChanged(); | |
1279 } | |
1280 | |
1281 private void computeSelection() { | |
1282 GC gc = new GC(this); | |
1283 Paragraph[] paragraphs = model.getParagraphs(); | |
1284 IHyperlinkSegment selectedLink = getSelectedLink(); | |
1285 if (getDisplay().getFocusControl() !is this) | |
1286 selectedLink = null; | |
1287 for (int i = 0; i < paragraphs.length; i++) { | |
1288 Paragraph p = paragraphs[i]; | |
1289 if (i > 0) | |
1290 selData.markNewLine(); | |
1291 p.computeSelection(gc, resourceTable, selectedLink, selData); | |
1292 } | |
1293 gc.dispose(); | |
1294 } | |
1295 | |
1296 void clearSelection() { | |
1297 selData = null; | |
1298 if (!isDisposed()) { | |
1299 redraw(); | |
1300 notifySelectionChanged(); | |
1301 } | |
1302 } | |
1303 | |
1304 private void notifySelectionChanged() { | |
1305 Event event = new Event(); | |
1306 event.widget = this; | |
1307 event.display = this.getDisplay(); | |
1308 event.type = DWT.Selection; | |
1309 notifyListeners(DWT.Selection, event); | |
1310 getAccessible().selectionChanged(); | |
1311 } | |
1312 | |
1313 private void handleDrag(MouseEvent e) { | |
1314 if (selData !is null) { | |
1315 ScrolledComposite scomp = FormUtil.getScrolledComposite(this); | |
1316 if (scomp !is null) { | |
1317 FormUtil.ensureVisible(scomp, this, e); | |
1318 } | |
1319 selData.update(e); | |
1320 redraw(); | |
1321 } | |
1322 } | |
1323 | |
1324 private void handleMouseClick(MouseEvent e, bool down) { | |
1325 if (DEBUG_FOCUS) | |
1326 Stdout.formatln("FormText: mouse click({})", down ); //$NON-NLS-1$ //$NON-NLS-2$ | |
1327 if (down) { | |
1328 // select a hyperlink | |
1329 mouseFocus = true; | |
1330 IHyperlinkSegment segmentUnder = model.findHyperlinkAt(e.x, e.y); | |
1331 if (segmentUnder !is null) { | |
1332 IHyperlinkSegment oldLink = getSelectedLink(); | |
1333 if (getDisplay().getFocusControl() !is this) { | |
1334 setFocus(); | |
1335 } | |
1336 model.selectLink(segmentUnder); | |
1337 enterLink(segmentUnder, e.stateMask); | |
1338 paintFocusTransfer(oldLink, segmentUnder); | |
1339 } | |
1340 if (e.button is 1) { | |
1341 startSelection(e); | |
1342 armed = segmentUnder; | |
1343 } | |
1344 else { | |
1345 } | |
1346 } else { | |
1347 if (e.button is 1) { | |
1348 endSelection(e); | |
1349 IHyperlinkSegment segmentUnder = model | |
1350 .findHyperlinkAt(e.x, e.y); | |
1351 if (segmentUnder !is null && armed is segmentUnder && selData is null) { | |
1352 activateLink(segmentUnder, e.stateMask); | |
1353 armed = null; | |
1354 } | |
1355 } | |
1356 mouseFocus = false; | |
1357 } | |
1358 } | |
1359 | |
1360 private void handleMouseHover(MouseEvent e) { | |
1361 } | |
1362 | |
1363 private void updateTooltipText(ParagraphSegment segment) { | |
1364 String tooltipText = null; | |
1365 if (segment !is null) { | |
1366 tooltipText = segment.getTooltipText(); | |
1367 } | |
1368 String currentTooltipText = getToolTipText(); | |
1369 | |
1370 if ((currentTooltipText !is null && tooltipText is null) | |
1371 || (currentTooltipText is null && tooltipText !is null)) | |
1372 setToolTipText(tooltipText); | |
1373 } | |
1374 | |
1375 private void handleMouseMove(MouseEvent e) { | |
1376 if (inSelection) { | |
1377 handleDrag(e); | |
1378 return; | |
1379 } | |
1380 ParagraphSegment segmentUnder = model.findSegmentAt(e.x, e.y); | |
1381 updateTooltipText(segmentUnder); | |
1382 if (segmentUnder is null) { | |
1383 if (entered !is null) { | |
1384 exitLink(entered, e.stateMask); | |
1385 paintLinkHover(entered, false); | |
1386 entered = null; | |
1387 } | |
1388 setCursor(null); | |
1389 } else { | |
1390 if (auto linkUnder = cast(IHyperlinkSegment) segmentUnder ) { | |
1391 if (entered !is null && linkUnder !is entered) { | |
1392 // Special case: links are so close that there are 0 pixels between. | |
1393 // Must exit the link before entering the next one. | |
1394 exitLink(entered, e.stateMask); | |
1395 paintLinkHover(entered, false); | |
1396 entered = null; | |
1397 } | |
1398 if (entered is null) { | |
1399 entered = linkUnder; | |
1400 enterLink(linkUnder, e.stateMask); | |
1401 paintLinkHover(entered, true); | |
1402 setCursor(model.getHyperlinkSettings().getHyperlinkCursor()); | |
1403 } | |
1404 } else { | |
1405 if (entered !is null) { | |
1406 exitLink(entered, e.stateMask); | |
1407 paintLinkHover(entered, false); | |
1408 entered = null; | |
1409 } | |
1410 if (null !is cast(TextSegment)segmentUnder ) | |
1411 setCursor(model.getHyperlinkSettings().getTextCursor()); | |
1412 else | |
1413 setCursor(null); | |
1414 } | |
1415 } | |
1416 } | |
1417 | |
1418 private bool advance(bool next) { | |
1419 if (DEBUG_FOCUS) | |
1420 Stdout.formatln("Advance: next={}", next); //$NON-NLS-1$ | |
1421 IFocusSelectable current = model.getSelectedSegment(); | |
1422 if (current !is null && null !is cast(IHyperlinkSegment)current ) | |
1423 exitLink(cast(IHyperlinkSegment) current, DWT.NULL); | |
1424 IFocusSelectable newSegment = null; | |
1425 bool valid = false; | |
1426 // get the next segment that can accept focus. Links | |
1427 // can always accept focus but controls may not | |
1428 while (!valid) { | |
1429 if (!model.traverseFocusSelectableObjects(next)) | |
1430 break; | |
1431 newSegment = model.getSelectedSegment(); | |
1432 if (newSegment is null) | |
1433 break; | |
1434 valid = setControlFocus(next, newSegment); | |
1435 } | |
1436 IHyperlinkSegment newLink = null !is cast(IHyperlinkSegment)newSegment ? cast(IHyperlinkSegment) newSegment | |
1437 : null; | |
1438 if (valid) | |
1439 enterLink(newLink, DWT.NULL); | |
1440 IHyperlinkSegment oldLink = null !is cast(IHyperlinkSegment)current ? cast(IHyperlinkSegment) current | |
1441 : null; | |
1442 if (oldLink !is null || newLink !is null) | |
1443 paintFocusTransfer(oldLink, newLink); | |
1444 if (newLink !is null) | |
1445 ensureVisible(newLink); | |
1446 if (newLink !is null) | |
1447 getAccessible().setFocus(model.getSelectedSegmentIndex()); | |
1448 return !valid; | |
1449 } | |
1450 | |
1451 private bool setControlFocus(bool next, IFocusSelectable selectable) { | |
1452 controlFocusTransfer = true; | |
1453 bool result = selectable.setFocus(resourceTable, next); | |
1454 controlFocusTransfer = false; | |
1455 return result; | |
1456 } | |
1457 | |
1458 private void handleFocusChange() { | |
1459 if (DEBUG_FOCUS) { | |
1460 Stdout.formatln("Handle focus change: hasFocus={}, mouseFocus={}", hasFocus, //$NON-NLS-1$ | |
1461 mouseFocus); //$NON-NLS-1$ | |
1462 } | |
1463 if (hasFocus) { | |
1464 bool advance = true; | |
1465 if (!mouseFocus) { | |
1466 // if (model.restoreSavedLink() is false) | |
1467 bool valid = false; | |
1468 IFocusSelectable selectable = null; | |
1469 while (!valid) { | |
1470 if (!model.traverseFocusSelectableObjects(advance)) | |
1471 break; | |
1472 selectable = model.getSelectedSegment(); | |
1473 if (selectable is null) | |
1474 break; | |
1475 valid = setControlFocus(advance, selectable); | |
1476 } | |
1477 if (selectable is null) | |
1478 setFocusToNextSibling(this, true); | |
1479 else | |
1480 ensureVisible(selectable); | |
1481 if ( auto hls = cast(IHyperlinkSegment)selectable ) { | |
1482 enterLink(hls, DWT.NULL); | |
1483 paintFocusTransfer(null, hls); | |
1484 } | |
1485 } | |
1486 } else { | |
1487 paintFocusTransfer(getSelectedLink(), null); | |
1488 model.selectLink(null); | |
1489 } | |
1490 } | |
1491 | |
1492 private void enterLink(IHyperlinkSegment link, int stateMask) { | |
1493 if (link is null || listeners is null) | |
1494 return; | |
1495 int size = listeners.size(); | |
1496 HyperlinkEvent he = new HyperlinkEvent(this, stringcast(link.getHref()), link | |
1497 .getText(), stateMask); | |
1498 Object [] listenerList = listeners.getListeners(); | |
1499 for (int i = 0; i < size; i++) { | |
1500 IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i]; | |
1501 listener.linkEntered(he); | |
1502 } | |
1503 } | |
1504 | |
1505 private void exitLink(IHyperlinkSegment link, int stateMask) { | |
1506 if (link is null || listeners is null) | |
1507 return; | |
1508 int size = listeners.size(); | |
1509 HyperlinkEvent he = new HyperlinkEvent(this, stringcast(link.getHref()), link | |
1510 .getText(), stateMask); | |
1511 Object [] listenerList = listeners.getListeners(); | |
1512 for (int i = 0; i < size; i++) { | |
1513 IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i]; | |
1514 listener.linkExited(he); | |
1515 } | |
1516 } | |
1517 | |
1518 private void paintLinkHover(IHyperlinkSegment link, bool hover) { | |
1519 GC gc = new GC(this); | |
1520 HyperlinkSettings settings = getHyperlinkSettings(); | |
1521 Color newFg = hover ? settings.getActiveForeground() : settings | |
1522 .getForeground(); | |
1523 if (newFg !is null) | |
1524 gc.setForeground(newFg); | |
1525 gc.setBackground(getBackground()); | |
1526 gc.setFont(getFont()); | |
1527 bool selected = (link is getSelectedLink()); | |
1528 (cast(ParagraphSegment) link).paint(gc, hover, resourceTable, selected, | |
1529 selData, null); | |
1530 gc.dispose(); | |
1531 } | |
1532 | |
1533 private void activateSelectedLink() { | |
1534 IHyperlinkSegment link = getSelectedLink(); | |
1535 if (link !is null) | |
1536 activateLink(link, DWT.NULL); | |
1537 } | |
1538 | |
1539 private void activateLink(IHyperlinkSegment link, int stateMask) { | |
1540 setCursor(model.getHyperlinkSettings().getBusyCursor()); | |
1541 if (listeners !is null) { | |
1542 int size = listeners.size(); | |
1543 HyperlinkEvent e = new HyperlinkEvent(this, stringcast(link.getHref()), link | |
1544 .getText(), stateMask); | |
1545 Object [] listenerList = listeners.getListeners(); | |
1546 for (int i = 0; i < size; i++) { | |
1547 IHyperlinkListener listener = cast(IHyperlinkListener) listenerList[i]; | |
1548 listener.linkActivated(e); | |
1549 } | |
1550 } | |
1551 if (!isDisposed() && model.linkExists(link)) { | |
1552 setCursor(model.getHyperlinkSettings().getHyperlinkCursor()); | |
1553 } | |
1554 } | |
1555 | |
1556 private void ensureBoldFontPresent(Font regularFont) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1557 Font boldFont = cast(Font) resourceTable.get(FormTextModel.BOLD_FONT_ID); |
75 | 1558 if (boldFont !is null) |
1559 return; | |
1560 boldFont = FormFonts.getInstance().getBoldFont(getDisplay(), regularFont); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1561 resourceTable.put(FormTextModel.BOLD_FONT_ID, boldFont); |
75 | 1562 } |
1563 | |
1564 private void paint(PaintEvent e) { | |
1565 GC gc = e.gc; | |
1566 gc.setFont(getFont()); | |
1567 ensureBoldFontPresent(getFont()); | |
1568 gc.setForeground(getForeground()); | |
1569 gc.setBackground(getBackground()); | |
1570 repaint(gc, e.x, e.y, e.width, e.height); | |
1571 } | |
1572 | |
1573 private void repaint(GC gc, int x, int y, int width, int height) { | |
1574 Image textBuffer = new Image(getDisplay(), width, height); | |
1575 Color bg = getBackground(); | |
1576 Color fg = getForeground(); | |
1577 if (!getEnabled()) { | |
1578 bg = getDisplay().getSystemColor(DWT.COLOR_WIDGET_BACKGROUND); | |
1579 fg = getDisplay().getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); | |
1580 } | |
1581 GC textGC = new GC(textBuffer, gc.getStyle()); | |
1582 textGC.setForeground(fg); | |
1583 textGC.setBackground(bg); | |
1584 textGC.setFont(getFont()); | |
1585 textGC.fillRectangle(0, 0, width, height); | |
1586 Rectangle repaintRegion = new Rectangle(x, y, width, height); | |
1587 | |
1588 Paragraph[] paragraphs = model.getParagraphs(); | |
1589 IHyperlinkSegment selectedLink = getSelectedLink(); | |
1590 if (getDisplay().getFocusControl() !is this) | |
1591 selectedLink = null; | |
1592 for (int i = 0; i < paragraphs.length; i++) { | |
1593 Paragraph p = paragraphs[i]; | |
1594 p | |
1595 .paint(textGC, repaintRegion, resourceTable, selectedLink, | |
1596 selData); | |
1597 } | |
1598 textGC.dispose(); | |
1599 gc.drawImage(textBuffer, x, y); | |
1600 textBuffer.dispose(); | |
1601 } | |
1602 | |
1603 private int getParagraphSpacing(int lineHeight) { | |
1604 return lineHeight / 2; | |
1605 } | |
1606 | |
1607 private void paintFocusTransfer(IHyperlinkSegment oldLink, | |
1608 IHyperlinkSegment newLink) { | |
1609 GC gc = new GC(this); | |
1610 Color bg = getBackground(); | |
1611 Color fg = getForeground(); | |
1612 gc.setFont(getFont()); | |
1613 if (oldLink !is null) { | |
1614 gc.setBackground(bg); | |
1615 gc.setForeground(fg); | |
1616 oldLink.paintFocus(gc, bg, fg, false, null); | |
1617 } | |
1618 if (newLink !is null) { | |
1619 // ensureVisible(newLink); | |
1620 gc.setBackground(bg); | |
1621 gc.setForeground(fg); | |
1622 newLink.paintFocus(gc, bg, fg, true, null); | |
1623 } | |
1624 gc.dispose(); | |
1625 } | |
1626 | |
1627 private void ensureVisible(IFocusSelectable segment) { | |
1628 if (mouseFocus) { | |
1629 mouseFocus = false; | |
1630 return; | |
1631 } | |
1632 if (segment is null) | |
1633 return; | |
1634 Rectangle bounds = segment.getBounds(); | |
1635 ScrolledComposite scomp = FormUtil.getScrolledComposite(this); | |
1636 if (scomp is null) | |
1637 return; | |
1638 Point origin = FormUtil.getControlLocation(scomp, this); | |
1639 origin.x += bounds.x; | |
1640 origin.y += bounds.y; | |
1641 FormUtil.ensureVisible(scomp, origin, new Point(bounds.width, | |
1642 bounds.height)); | |
1643 } | |
1644 | |
1645 /** | |
1646 * Overrides the method by fully trusting the layout manager (computed width | |
1647 * or height may be larger than the provider width or height hints). Callers | |
1648 * should be prepared that the computed width is larger than the provided | |
1649 * wHint. | |
1650 * | |
1651 * @see dwt.widgets.Composite#computeSize(int, int, bool) | |
1652 */ | |
1653 public Point computeSize(int wHint, int hHint, bool changed) { | |
1654 checkWidget(); | |
1655 Point size; | |
1656 FormTextLayout layout = cast(FormTextLayout) getLayout(); | |
1657 if (wHint is DWT.DEFAULT || hHint is DWT.DEFAULT) { | |
1658 size = layout.computeSize(this, wHint, hHint, changed); | |
1659 } else { | |
1660 size = new Point(wHint, hHint); | |
1661 } | |
1662 Rectangle trim = computeTrim(0, 0, size.x, size.y); | |
1663 if (DEBUG_TEXTSIZE) | |
1664 Stdout.formatln("FormText Computed size: {}",trim); //$NON-NLS-1$ | |
1665 return new Point(trim.width, trim.height); | |
1666 } | |
1667 | |
1668 private void disposeResourceTable(bool disposeBoldFont) { | |
1669 if (disposeBoldFont) { | |
1670 Font boldFont = cast(Font) resourceTable | |
1671 .get(FormTextModel.BOLD_FONT_ID); | |
1672 if (boldFont !is null) { | |
1673 FormFonts.getInstance().markFinished(boldFont); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1674 resourceTable.remove(FormTextModel.BOLD_FONT_ID); |
75 | 1675 } |
1676 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1677 ArrayList imagesToRemove = new ArrayList(); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1678 for (Enumeration enm = resourceTable.keys(); enm.hasMoreElements();) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1679 String key = stringcast( enm.nextElement()); |
75 | 1680 if (key.startsWith(ImageSegment.SEL_IMAGE_PREFIX)) { |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1681 Object obj = resourceTable.get(key); |
75 | 1682 if (auto image = cast(Image)obj ) { |
1683 if (!image.isDisposed()) { | |
1684 image.dispose(); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1685 imagesToRemove.add(key); |
75 | 1686 } |
1687 } | |
1688 } | |
1689 } | |
1690 for (int i = 0; i < imagesToRemove.size(); i++) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
85
diff
changeset
|
1691 resourceTable.remove(imagesToRemove.get(i)); |
75 | 1692 } |
1693 } | |
1694 | |
1695 /* | |
1696 * (non-Javadoc) | |
1697 * | |
1698 * @see dwt.widgets.Control#setEnabled(bool) | |
1699 */ | |
1700 public void setEnabled(bool enabled) { | |
1701 super.setEnabled(enabled); | |
1702 redraw(); | |
1703 } | |
1704 | |
1705 /* (non-Javadoc) | |
1706 * @see dwt.widgets.Control#setFocus() | |
1707 */ | |
1708 public bool setFocus() { | |
1709 FormUtil.setFocusScrollingEnabled(this, false); | |
1710 bool result = super.setFocus(); | |
1711 FormUtil.setFocusScrollingEnabled(this, true); | |
1712 return result; | |
1713 } | |
1714 } |