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.FormTextModel;
|
|
14
|
|
15 import dwtx.ui.internal.forms.widgets.Paragraph;
|
|
16 import dwtx.ui.internal.forms.widgets.IFocusSelectable;
|
|
17 import dwtx.ui.internal.forms.widgets.ParagraphSegment;
|
|
18 import dwtx.ui.internal.forms.widgets.IHyperlinkSegment;
|
|
19 import dwtx.ui.internal.forms.widgets.ControlSegment;
|
|
20 import dwtx.ui.internal.forms.widgets.ImageSegment;
|
|
21 import dwtx.ui.internal.forms.widgets.ObjectSegment;
|
|
22
|
|
23 import dwt.DWT;
|
|
24 import dwtx.ui.forms.HyperlinkSettings;
|
|
25
|
|
26 import dwt.dwthelper.utils;
|
|
27 import dwt.dwthelper.InputStream;
|
|
28 pragma(msg,"FIXME temp type "~__FILE__);
|
|
29 public class FormTextModel {
|
|
30 public static const String BOLD_FONT_ID = "f.____bold"; //$NON-NLS-1$
|
|
31 public this() ;
|
|
32 public Paragraph[] getParagraphs() ;
|
|
33 public String getAccessibleText() ;
|
|
34 public void parseTaggedText(String taggedText, bool expandURLs) ;
|
|
35 public void parseInputStream(InputStream is_, bool expandURLs) ;
|
|
36 public void parseRegularText(String regularText, bool convertURLs) ;
|
|
37 public HyperlinkSettings getHyperlinkSettings() ;
|
|
38 public void setHyperlinkSettings(HyperlinkSettings settings) ;
|
|
39 IFocusSelectable[] getFocusSelectableSegments() ;
|
|
40 public IHyperlinkSegment getHyperlink(int index) ;
|
|
41 public IHyperlinkSegment findHyperlinkAt(int x, int y) ;
|
|
42 public int getHyperlinkCount() ;
|
|
43 public int indexOf(IHyperlinkSegment link) ;
|
|
44 public ParagraphSegment findSegmentAt(int x, int y) ;
|
|
45 public void clearCache(String fontId) ;
|
|
46 public IFocusSelectable getSelectedSegment() ;
|
|
47 public int getSelectedSegmentIndex() ;
|
|
48 public bool linkExists(IHyperlinkSegment link) ;
|
|
49 public bool traverseFocusSelectableObjects(bool next) ;
|
|
50 public IFocusSelectable getNextFocusSegment(bool next) ;
|
|
51 public bool restoreSavedLink() ;
|
|
52 public void selectLink(IHyperlinkSegment link) ;
|
|
53 public void select(IFocusSelectable selectable) ;
|
|
54 public bool hasFocusSegments() ;
|
|
55 public void dispose() ;
|
|
56 public bool isWhitespaceNormalized() ;
|
|
57 public void setWhitespaceNormalized(bool whitespaceNormalized) ;
|
|
58 }
|
|
59
|
|
60 /++
|
|
61 static import tango.text.xml.Document;
|
|
62 import tango.util.collection.ArraySeq;
|
|
63 public class FormTextModel {
|
|
64 // private static const DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
|
|
65 // .newInstance();
|
|
66
|
|
67 alias tango.text.xml.Document.Document!(char) Document;
|
|
68 alias Document.NodeImpl Node;
|
|
69
|
|
70 private bool whitespaceNormalized = true;
|
|
71
|
|
72 private alias ArraySeq!(Paragraph) TArraySeqParagraph;
|
|
73 private TArraySeqParagraph paragraphs;
|
|
74
|
|
75 private IFocusSelectable[] selectableSegments;
|
|
76
|
|
77 private int selectedSegmentIndex = -1;
|
|
78
|
|
79 private int savedSelectedLinkIndex = -1;
|
|
80
|
|
81 private HyperlinkSettings hyperlinkSettings;
|
|
82
|
|
83 public static const String BOLD_FONT_ID = "f.____bold"; //$NON-NLS-1$
|
|
84
|
|
85 //private static final int TEXT_ONLY_LINK = 1;
|
|
86
|
|
87 //private static final int IMG_ONLY_LINK = 2;
|
|
88
|
|
89 //private static final int TEXT_AND_IMAGES_LINK = 3;
|
|
90
|
|
91 public this() {
|
|
92 reset();
|
|
93 }
|
|
94
|
|
95 /*
|
|
96 * @see ITextModel#getParagraphs()
|
|
97 */
|
|
98 public Paragraph[] getParagraphs() {
|
|
99 if (paragraphs is null)
|
|
100 return new Paragraph[0];
|
|
101 return paragraphs
|
|
102 .toArray();
|
|
103 }
|
|
104
|
|
105 public String getAccessibleText() {
|
|
106 if (paragraphs is null)
|
|
107 return ""; //$NON-NLS-1$
|
|
108 StringBuffer sbuf = new StringBuffer();
|
|
109 for (int i = 0; i < paragraphs.size(); i++) {
|
|
110 Paragraph paragraph = cast(Paragraph) paragraphs.get(i);
|
|
111 String text = paragraph.getAccessibleText();
|
|
112 sbuf.append(text);
|
|
113 }
|
|
114 return sbuf.toString();
|
|
115 }
|
|
116
|
|
117 /*
|
|
118 * @see ITextModel#parse(String)
|
|
119 */
|
|
120 public void parseTaggedText(String taggedText, bool expandURLs) {
|
|
121 if (taggedText is null) {
|
|
122 reset();
|
|
123 return;
|
|
124 }
|
|
125 try {
|
|
126 InputStream stream = new ByteArrayInputStream(taggedText
|
|
127 .getBytes("UTF8")); //$NON-NLS-1$
|
|
128 parseInputStream(stream, expandURLs);
|
|
129 } catch (UnsupportedEncodingException e) {
|
|
130 DWT.error(DWT.ERROR_UNSUPPORTED_FORMAT, e);
|
|
131 }
|
|
132 }
|
|
133
|
|
134 public void parseInputStream(InputStream is_, bool expandURLs) {
|
|
135
|
|
136 documentBuilderFactory.setNamespaceAware(true);
|
|
137 documentBuilderFactory.setIgnoringComments(true);
|
|
138
|
|
139 reset();
|
|
140 try {
|
|
141 DocumentBuilder parser = documentBuilderFactory
|
|
142 .newDocumentBuilder();
|
|
143 InputSource source = new InputSource(is_);
|
|
144 Document doc = parser.parse(source);
|
|
145 processDocument(doc, expandURLs);
|
|
146 } catch (ParserConfigurationException e) {
|
|
147 DWT.error(DWT.ERROR_INVALID_ARGUMENT, e);
|
|
148 } catch (SAXException e) {
|
|
149 DWT.error(DWT.ERROR_INVALID_ARGUMENT, e);
|
|
150 } catch (IOException e) {
|
|
151 DWT.error(DWT.ERROR_IO, e);
|
|
152 }
|
|
153 }
|
|
154
|
|
155 private void processDocument(Document doc, bool expandURLs) {
|
|
156 Node root = doc.getDocumentElement();
|
|
157 NodeList children = root.getChildNodes();
|
|
158 processSubnodes(paragraphs, children, expandURLs);
|
|
159 }
|
|
160
|
|
161 private void processSubnodes(TArraySeqParagraph plist, NodeList children, bool expandURLs) {
|
|
162 for (int i = 0; i < children.getLength(); i++) {
|
|
163 Node child = children.item(i);
|
|
164 if (child.getNodeType() is Node.TEXT_NODE) {
|
|
165 // Make an implicit paragraph
|
|
166 String text = getSingleNodeText(child);
|
|
167 if (text !is null && !isIgnorableWhiteSpace(text, true)) {
|
|
168 Paragraph p = new Paragraph(true);
|
|
169 p.parseRegularText(text, expandURLs, true,
|
|
170 getHyperlinkSettings(), null);
|
|
171 plist.add(p);
|
|
172 }
|
|
173 } else if (child.getNodeType() is Node.ELEMENT_NODE) {
|
|
174 String tag = child.getNodeName().toLowerCase();
|
|
175 if (tag.equals("p")) { //$NON-NLS-1$
|
|
176 Paragraph p = processParagraph(child, expandURLs);
|
|
177 if (p !is null)
|
|
178 plist.add(p);
|
|
179 } else if (tag.equals("li")) { //$NON-NLS-1$
|
|
180 Paragraph p = processListItem(child, expandURLs);
|
|
181 if (p !is null)
|
|
182 plist.add(p);
|
|
183 }
|
|
184 }
|
|
185 }
|
|
186 }
|
|
187
|
|
188 private Paragraph processParagraph(Node paragraph, bool expandURLs) {
|
|
189 NodeList children = paragraph.getChildNodes();
|
|
190 NamedNodeMap atts = paragraph.getAttributes();
|
|
191 Node addSpaceAtt = atts.getNamedItem("addVerticalSpace"); //$NON-NLS-1$
|
|
192 bool addSpace = true;
|
|
193
|
|
194 if (addSpaceAtt is null)
|
|
195 addSpaceAtt = atts.getNamedItem("vspace"); //$NON-NLS-1$
|
|
196
|
|
197 if (addSpaceAtt !is null) {
|
|
198 String value = addSpaceAtt.getNodeValue();
|
|
199 addSpace = value.equalsIgnoreCase("true"); //$NON-NLS-1$
|
|
200 }
|
|
201 Paragraph p = new Paragraph(addSpace);
|
|
202
|
|
203 processSegments(p, children, expandURLs);
|
|
204 return p;
|
|
205 }
|
|
206
|
|
207 private Paragraph processListItem(Node listItem, bool expandURLs) {
|
|
208 NodeList children = listItem.getChildNodes();
|
|
209 NamedNodeMap atts = listItem.getAttributes();
|
|
210 Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");//$NON-NLS-1$
|
|
211 Node styleAtt = atts.getNamedItem("style");//$NON-NLS-1$
|
|
212 Node valueAtt = atts.getNamedItem("value");//$NON-NLS-1$
|
|
213 Node indentAtt = atts.getNamedItem("indent");//$NON-NLS-1$
|
|
214 Node bindentAtt = atts.getNamedItem("bindent");//$NON-NLS-1$
|
|
215 int style = BulletParagraph.CIRCLE;
|
|
216 int indent = -1;
|
|
217 int bindent = -1;
|
|
218 String text = null;
|
|
219 bool addSpace = true;
|
|
220
|
|
221 if (addSpaceAtt !is null) {
|
|
222 String value = addSpaceAtt.getNodeValue();
|
|
223 addSpace = value.equalsIgnoreCase("true"); //$NON-NLS-1$
|
|
224 }
|
|
225 if (styleAtt !is null) {
|
|
226 String value = styleAtt.getNodeValue();
|
|
227 if (value.equalsIgnoreCase("text")) { //$NON-NLS-1$
|
|
228 style = BulletParagraph.TEXT;
|
|
229 } else if (value.equalsIgnoreCase("image")) { //$NON-NLS-1$
|
|
230 style = BulletParagraph.IMAGE;
|
|
231 } else if (value.equalsIgnoreCase("bullet")) { //$NON-NLS-1$
|
|
232 style = BulletParagraph.CIRCLE;
|
|
233 }
|
|
234 }
|
|
235 if (valueAtt !is null) {
|
|
236 text = valueAtt.getNodeValue();
|
|
237 if (style is BulletParagraph.IMAGE)
|
|
238 text = "i." + text; //$NON-NLS-1$
|
|
239 }
|
|
240 if (indentAtt !is null) {
|
|
241 String value = indentAtt.getNodeValue();
|
|
242 try {
|
|
243 indent = Integer.parseInt(value);
|
|
244 } catch (NumberFormatException e) {
|
|
245 }
|
|
246 }
|
|
247 if (bindentAtt !is null) {
|
|
248 String value = bindentAtt.getNodeValue();
|
|
249 try {
|
|
250 bindent = Integer.parseInt(value);
|
|
251 } catch (NumberFormatException e) {
|
|
252 }
|
|
253 }
|
|
254
|
|
255 BulletParagraph p = new BulletParagraph(addSpace);
|
|
256 p.setIndent(indent);
|
|
257 p.setBulletIndent(bindent);
|
|
258 p.setBulletStyle(style);
|
|
259 p.setBulletText(text);
|
|
260
|
|
261 processSegments(p, children, expandURLs);
|
|
262 return p;
|
|
263 }
|
|
264
|
|
265 private void processSegments(Paragraph p, NodeList children,
|
|
266 bool expandURLs) {
|
|
267 for (int i = 0; i < children.getLength(); i++) {
|
|
268 Node child = children.item(i);
|
|
269 ParagraphSegment segment = null;
|
|
270
|
|
271 if (child.getNodeType() is Node.TEXT_NODE) {
|
|
272 String value = getSingleNodeText(child);
|
|
273
|
|
274 if (value !is null && !isIgnorableWhiteSpace(value, false)) {
|
|
275 p.parseRegularText(value, expandURLs, true,
|
|
276 getHyperlinkSettings(), null);
|
|
277 }
|
|
278 } else if (child.getNodeType() is Node.ELEMENT_NODE) {
|
|
279 String name = child.getNodeName();
|
|
280 if (name.equalsIgnoreCase("img")) { //$NON-NLS-1$
|
|
281 segment = processImageSegment(child);
|
|
282 } else if (name.equalsIgnoreCase("a")) { //$NON-NLS-1$
|
|
283 segment = processHyperlinkSegment(child,
|
|
284 getHyperlinkSettings());
|
|
285 } else if (name.equalsIgnoreCase("span")) { //$NON-NLS-1$
|
|
286 processTextSegment(p, expandURLs, child);
|
|
287 } else if (name.equalsIgnoreCase("b")) { //$NON-NLS-1$
|
|
288 String text = getNodeText(child);
|
|
289 String fontId = BOLD_FONT_ID;
|
|
290 p.parseRegularText(text, expandURLs, true,
|
|
291 getHyperlinkSettings(), fontId);
|
|
292 } else if (name.equalsIgnoreCase("br")) { //$NON-NLS-1$
|
|
293 segment = new BreakSegment();
|
|
294 } else if (name.equalsIgnoreCase("control")) { //$NON-NLS-1$
|
|
295 segment = processControlSegment(child);
|
|
296 }
|
|
297 }
|
|
298 if (segment !is null) {
|
|
299 p.addSegment(segment);
|
|
300 }
|
|
301 }
|
|
302 }
|
|
303
|
|
304 private bool isIgnorableWhiteSpace(String text, bool ignoreSpaces) {
|
|
305 for (int i = 0; i < text.length(); i++) {
|
|
306 char c = text.charAt(i);
|
|
307 if (ignoreSpaces && c is ' ')
|
|
308 continue;
|
|
309 if (c is '\n' || c is '\r' || c is '\f')
|
|
310 continue;
|
|
311 return false;
|
|
312 }
|
|
313 return true;
|
|
314 }
|
|
315
|
|
316 private ImageSegment processImageSegment(Node image) {
|
|
317 ImageSegment segment = new ImageSegment();
|
|
318 processObjectSegment(segment, image, "i."); //$NON-NLS-1$
|
|
319 return segment;
|
|
320 }
|
|
321
|
|
322 private ControlSegment processControlSegment(Node control) {
|
|
323 ControlSegment segment = new ControlSegment();
|
|
324 processObjectSegment(segment, control, "o."); //$NON-NLS-1$
|
|
325 Node fill = control.getAttributes().getNamedItem("fill"); //$NON-NLS-1$
|
|
326 if (fill !is null) {
|
|
327 String value = fill.getNodeValue();
|
|
328 bool doFill = value.equalsIgnoreCase("true"); //$NON-NLS-1$
|
|
329 segment.setFill(doFill);
|
|
330 }
|
|
331 try {
|
|
332 Node width = control.getAttributes().getNamedItem("width"); //$NON-NLS-1$
|
|
333 if (width !is null) {
|
|
334 String value = width.getNodeValue();
|
|
335 int doWidth = Integer.parseInt(value);
|
|
336 segment.setWidth(doWidth);
|
|
337 }
|
|
338 Node height = control.getAttributes().getNamedItem("height"); //$NON-NLS-1$
|
|
339 if (height !is null) {
|
|
340 String value = height.getNodeValue();
|
|
341 int doHeight = Integer.parseInt(value);
|
|
342 segment.setHeight(doHeight);
|
|
343 }
|
|
344 }
|
|
345 catch (NumberFormatException e) {
|
|
346 // ignore invalid width or height
|
|
347 }
|
|
348 return segment;
|
|
349 }
|
|
350
|
|
351 private void processObjectSegment(ObjectSegment segment, Node object, String prefix) {
|
|
352 NamedNodeMap atts = object.getAttributes();
|
|
353 Node id = atts.getNamedItem("href"); //$NON-NLS-1$
|
|
354 Node align_ = atts.getNamedItem("align"); //$NON-NLS-1$
|
|
355 if (id !is null) {
|
|
356 String value = id.getNodeValue();
|
|
357 segment.setObjectId(prefix + value);
|
|
358 }
|
|
359 if (align_ !is null) {
|
|
360 String value = align_.getNodeValue().toLowerCase();
|
|
361 if (value.equals("top")) //$NON-NLS-1$
|
|
362 segment.setVerticalAlignment(ImageSegment.TOP);
|
|
363 else if (value.equals("middle")) //$NON-NLS-1$
|
|
364 segment.setVerticalAlignment(ImageSegment.MIDDLE);
|
|
365 else if (value.equals("bottom")) //$NON-NLS-1$
|
|
366 segment.setVerticalAlignment(ImageSegment.BOTTOM);
|
|
367 }
|
|
368 }
|
|
369
|
|
370 private void appendText(String value, StringBuffer buf, int[] spaceCounter) {
|
|
371 if (!whitespaceNormalized)
|
|
372 buf.append(value);
|
|
373 else {
|
|
374 for (int j = 0; j < value.length(); j++) {
|
|
375 char c = value.charAt(j);
|
|
376 if (c is ' ' || c is '\t') {
|
|
377 // space
|
|
378 if (++spaceCounter[0] is 1) {
|
|
379 buf.append(c);
|
|
380 }
|
|
381 } else if (c is '\n' || c is '\r' || c is '\f') {
|
|
382 // new line
|
|
383 if (++spaceCounter[0] is 1) {
|
|
384 buf.append(' ');
|
|
385 }
|
|
386 } else {
|
|
387 // other characters
|
|
388 spaceCounter[0] = 0;
|
|
389 buf.append(c);
|
|
390 }
|
|
391 }
|
|
392 }
|
|
393 }
|
|
394
|
|
395 private String getNormalizedText(String text) {
|
|
396 int[] spaceCounter = new int[1];
|
|
397 StringBuffer buf = new StringBuffer();
|
|
398
|
|
399 if (text is null)
|
|
400 return null;
|
|
401 appendText(text, buf, spaceCounter);
|
|
402 return buf.toString();
|
|
403 }
|
|
404
|
|
405 private String getSingleNodeText(Node node) {
|
|
406 return getNormalizedText(node.getNodeValue());
|
|
407 }
|
|
408
|
|
409 private String getNodeText(Node node) {
|
|
410 NodeList children = node.getChildNodes();
|
|
411 StringBuffer buf = new StringBuffer();
|
|
412 int[] spaceCounter = new int[1];
|
|
413
|
|
414 for (int i = 0; i < children.getLength(); i++) {
|
|
415 Node child = children.item(i);
|
|
416 if (child.getNodeType() is Node.TEXT_NODE) {
|
|
417 String value = child.getNodeValue();
|
|
418 appendText(value, buf, spaceCounter);
|
|
419 }
|
|
420 }
|
|
421 return buf.toString().trim();
|
|
422 }
|
|
423
|
|
424 private ParagraphSegment processHyperlinkSegment(Node link,
|
|
425 HyperlinkSettings settings) {
|
|
426 NamedNodeMap atts = link.getAttributes();
|
|
427 String href = null;
|
|
428 bool wrapAllowed = true;
|
|
429 String boldFontId = null;
|
|
430
|
|
431 Node hrefAtt = atts.getNamedItem("href"); //$NON-NLS-1$
|
|
432 if (hrefAtt !is null) {
|
|
433 href = hrefAtt.getNodeValue();
|
|
434 }
|
|
435 Node boldAtt = atts.getNamedItem("bold"); //$NON-NLS-1$
|
|
436 if (boldAtt !is null) {
|
|
437 boldFontId = BOLD_FONT_ID;
|
|
438 }
|
|
439 Node nowrap = atts.getNamedItem("nowrap"); //$NON-NLS-1$
|
|
440 if (nowrap !is null) {
|
|
441 String value = nowrap.getNodeValue();
|
|
442 if (value !is null && value.equalsIgnoreCase("true")) //$NON-NLS-1$
|
|
443 wrapAllowed = false;
|
|
444 }
|
|
445 Object status = checkChildren(link);
|
|
446 if ( auto child = cast(Node)status ) {
|
|
447 ImageHyperlinkSegment segment = new ImageHyperlinkSegment();
|
|
448 segment.setHref(href);
|
|
449 segment.setWordWrapAllowed(wrapAllowed);
|
|
450 Node alt = child.getAttributes().getNamedItem("alt"); //$NON-NLS-1$
|
|
451 if (alt !is null)
|
|
452 segment.setTooltipText(alt.getNodeValue());
|
|
453 Node text = child.getAttributes().getNamedItem("text"); //$NON-NLS-1$
|
|
454 if (text !is null)
|
|
455 segment.setText(text.getNodeValue());
|
|
456 processObjectSegment(segment, child, "i."); //$NON-NLS-1$
|
|
457 return segment;
|
|
458 } else if ( auto textObj = cast(ArrayWrapperString)status ) {
|
|
459 String text = textObj.array;
|
|
460 TextHyperlinkSegment segment = new TextHyperlinkSegment(text,
|
|
461 settings, null);
|
|
462 segment.setHref(href);
|
|
463 segment.setFontId(boldFontId);
|
|
464 Node alt = atts.getNamedItem("alt"); //$NON-NLS-1$
|
|
465 if (alt !is null)
|
|
466 segment.setTooltipText(alt.getNodeValue());
|
|
467 segment.setWordWrapAllowed(wrapAllowed);
|
|
468 return segment;
|
|
469 } else {
|
|
470 AggregateHyperlinkSegment parent = new AggregateHyperlinkSegment();
|
|
471 parent.setHref(href);
|
|
472 NodeList children = link.getChildNodes();
|
|
473 for (int i = 0; i < children.getLength(); i++) {
|
|
474 Node child = children.item(i);
|
|
475 if (child.getNodeType() is Node.TEXT_NODE) {
|
|
476 String value = child.getNodeValue();
|
|
477 TextHyperlinkSegment ts = new TextHyperlinkSegment(
|
|
478 getNormalizedText(value), settings, null);
|
|
479 Node alt = atts.getNamedItem("alt"); //$NON-NLS-1$
|
|
480 if (alt !is null)
|
|
481 ts.setTooltipText(alt.getNodeValue());
|
|
482 ts.setWordWrapAllowed(wrapAllowed);
|
|
483 parent.add(ts);
|
|
484 } else if (child.getNodeType() is Node.ELEMENT_NODE) {
|
|
485 String name = child.getNodeName();
|
|
486 if (name.equalsIgnoreCase("img")) { //$NON-NLS-1$
|
|
487 ImageHyperlinkSegment is_ = new ImageHyperlinkSegment();
|
|
488 processObjectSegment(is_, child, "i."); //$NON-NLS-1$
|
|
489 Node alt = child.getAttributes().getNamedItem("alt"); //$NON-NLS-1$
|
|
490 if (alt !is null)
|
|
491 is_.setTooltipText(alt.getNodeValue());
|
|
492 parent.add(is_);
|
|
493 is_.setWordWrapAllowed(wrapAllowed);
|
|
494 }
|
|
495 }
|
|
496 }
|
|
497 return parent;
|
|
498 }
|
|
499 }
|
|
500
|
|
501 private Object checkChildren(Node node) {
|
|
502 bool text = false;
|
|
503 Node imgNode = null;
|
|
504 //int status = 0;
|
|
505
|
|
506 NodeList children = node.getChildNodes();
|
|
507 for (int i = 0; i < children.getLength(); i++) {
|
|
508 Node child = children.item(i);
|
|
509 if (child.getNodeType() is Node.TEXT_NODE)
|
|
510 text = true;
|
|
511 else if (child.getNodeType() is Node.ELEMENT_NODE
|
|
512 && child.getNodeName().equalsIgnoreCase("img")) { //$NON-NLS-1$
|
|
513 imgNode = child;
|
|
514 }
|
|
515 }
|
|
516 if (text && imgNode is null)
|
|
517 return getNodeText(node);
|
|
518 else if (!text && imgNode !is null)
|
|
519 return imgNode;
|
|
520 else return null;
|
|
521 }
|
|
522
|
|
523 private void processTextSegment(Paragraph p, bool expandURLs,
|
|
524 Node textNode) {
|
|
525 String text = getNodeText(textNode);
|
|
526
|
|
527 NamedNodeMap atts = textNode.getAttributes();
|
|
528 Node font = atts.getNamedItem("font"); //$NON-NLS-1$
|
|
529 Node color = atts.getNamedItem("color"); //$NON-NLS-1$
|
|
530 bool wrapAllowed=true;
|
|
531 Node nowrap = atts.getNamedItem("nowrap"); //$NON-NLS-1$
|
|
532 if (nowrap !is null) {
|
|
533 String value = nowrap.getNodeValue();
|
|
534 if (value !is null && value.equalsIgnoreCase("true")) //$NON-NLS-1$
|
|
535 wrapAllowed = false;
|
|
536 }
|
|
537 String fontId = null;
|
|
538 String colorId = null;
|
|
539 if (font !is null) {
|
|
540 fontId = "f." + font.getNodeValue(); //$NON-NLS-1$
|
|
541 }
|
|
542 if (color !is null) {
|
|
543 colorId = "c." + color.getNodeValue(); //$NON-NLS-1$
|
|
544 }
|
|
545 p.parseRegularText(text, expandURLs, wrapAllowed, getHyperlinkSettings(), fontId,
|
|
546 colorId);
|
|
547 }
|
|
548
|
|
549 public void parseRegularText(String regularText, bool convertURLs) {
|
|
550 reset();
|
|
551
|
|
552 if (regularText is null)
|
|
553 return;
|
|
554
|
|
555 regularText = getNormalizedText(regularText);
|
|
556
|
|
557 Paragraph p = new Paragraph(true);
|
|
558 paragraphs.append(p);
|
|
559 int pstart = 0;
|
|
560
|
|
561 for (int i = 0; i < regularText.length(); i++) {
|
|
562 char c = regularText.charAt(i);
|
|
563 if (p is null) {
|
|
564 p = new Paragraph(true);
|
|
565 paragraphs.append(p);
|
|
566 }
|
|
567 if (c is '\n') {
|
|
568 String text = regularText.substring(pstart, i);
|
|
569 pstart = i + 1;
|
|
570 p.parseRegularText(text, convertURLs, true, getHyperlinkSettings(),
|
|
571 null);
|
|
572 p = null;
|
|
573 }
|
|
574 }
|
|
575 if (p !is null) {
|
|
576 // no new line
|
|
577 String text = regularText.substring(pstart);
|
|
578 p.parseRegularText(text, convertURLs, true, getHyperlinkSettings(), null);
|
|
579 }
|
|
580 }
|
|
581
|
|
582 public HyperlinkSettings getHyperlinkSettings() {
|
|
583 // #132723 cannot have null settings
|
|
584 if (hyperlinkSettingsisnull)
|
|
585 hyperlinkSettings = new HyperlinkSettings(SWTUtil.getStandardDisplay());
|
|
586 return hyperlinkSettings;
|
|
587 }
|
|
588
|
|
589 public void setHyperlinkSettings(HyperlinkSettings settings) {
|
|
590 this.hyperlinkSettings = settings;
|
|
591 }
|
|
592
|
|
593 private void reset() {
|
|
594 if (paragraphs is null)
|
|
595 paragraphs = new TArraySeqParagraph;
|
|
596 paragraphs.clear();
|
|
597 selectedSegmentIndex = -1;
|
|
598 savedSelectedLinkIndex = -1;
|
|
599 selectableSegments = null;
|
|
600 }
|
|
601
|
|
602 IFocusSelectable[] getFocusSelectableSegments() {
|
|
603 if (selectableSegments !is null || paragraphs is null)
|
|
604 return selectableSegments;
|
|
605 IFocusSelectable[] result;
|
|
606 for (int i = 0; i < paragraphs.size(); i++) {
|
|
607 Paragraph p = cast(Paragraph) paragraphs.get(i);
|
|
608 ParagraphSegment[] segments = p.getSegments();
|
|
609 for (int j = 0; j < segments.length; j++) {
|
|
610 if (null !is cast(IFocusSelectable)segments[j] )
|
|
611 result ~= segments[j];
|
|
612 }
|
|
613 }
|
|
614 selectableSegments = result;
|
|
615 return selectableSegments;
|
|
616 }
|
|
617
|
|
618 public IHyperlinkSegment getHyperlink(int index) {
|
|
619 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
620 if (selectables.length>index) {
|
|
621 IFocusSelectable link = selectables[index];
|
|
622 if (auto l = cast(IHyperlinkSegment)link )
|
|
623 return l;
|
|
624 }
|
|
625 return null;
|
|
626 }
|
|
627
|
|
628 public IHyperlinkSegment findHyperlinkAt(int x, int y) {
|
|
629 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
630 for (int i = 0; i < selectables.length; i++) {
|
|
631 IFocusSelectable segment = selectables[i];
|
|
632 if ( auto link = cast(IHyperlinkSegment)segment ) {
|
|
633 if (link.contains(x, y))
|
|
634 return link;
|
|
635 }
|
|
636 }
|
|
637 return null;
|
|
638 }
|
|
639
|
|
640 public int getHyperlinkCount() {
|
|
641 return getFocusSelectableSegments().length;
|
|
642 }
|
|
643
|
|
644 public int indexOf(IHyperlinkSegment link) {
|
|
645 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
646 for (int i = 0; i < selectables.length; i++) {
|
|
647 IFocusSelectable segment = selectables[i];
|
|
648 if (auto l = cast(IHyperlinkSegment)segment ) {
|
|
649 if (link is l)
|
|
650 return i;
|
|
651 }
|
|
652 }
|
|
653 return -1;
|
|
654 }
|
|
655
|
|
656 public ParagraphSegment findSegmentAt(int x, int y) {
|
|
657 for (int i = 0; i < paragraphs.size(); i++) {
|
|
658 Paragraph p = cast(Paragraph) paragraphs.get(i);
|
|
659 ParagraphSegment segment = p.findSegmentAt(x, y);
|
|
660 if (segment !is null)
|
|
661 return segment;
|
|
662 }
|
|
663 return null;
|
|
664 }
|
|
665
|
|
666 public void clearCache(String fontId) {
|
|
667 for (int i = 0; i < paragraphs.size(); i++) {
|
|
668 Paragraph p = cast(Paragraph) paragraphs.get(i);
|
|
669 p.clearCache(fontId);
|
|
670 }
|
|
671 }
|
|
672
|
|
673 public IFocusSelectable getSelectedSegment() {
|
|
674 if (selectableSegments is null || selectedSegmentIndex is -1)
|
|
675 return null;
|
|
676 return selectableSegments[selectedSegmentIndex];
|
|
677 }
|
|
678
|
|
679 public int getSelectedSegmentIndex() {
|
|
680 return selectedSegmentIndex;
|
|
681 }
|
|
682
|
|
683 public bool linkExists(IHyperlinkSegment link) {
|
|
684 if (selectableSegmentsisnull)
|
|
685 return false;
|
|
686 for (int i=0; i<selectableSegments.length; i++) {
|
|
687 if (selectableSegments[i] is link)
|
|
688 return true;
|
|
689 }
|
|
690 return false;
|
|
691 }
|
|
692
|
|
693 public bool traverseFocusSelectableObjects(bool next) {
|
|
694 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
695 if (selectables is null)
|
|
696 return false;
|
|
697 int size = selectables.length;
|
|
698 if (next) {
|
|
699 selectedSegmentIndex++;
|
|
700 } else
|
|
701 selectedSegmentIndex--;
|
|
702
|
|
703 if (selectedSegmentIndex < 0 || selectedSegmentIndex > size - 1) {
|
|
704 selectedSegmentIndex = -1;
|
|
705 }
|
|
706 return selectedSegmentIndex !is -1;
|
|
707 }
|
|
708
|
|
709 public IFocusSelectable getNextFocusSegment(bool next) {
|
|
710 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
711 if (selectables is null)
|
|
712 return null;
|
|
713 int nextIndex = next?selectedSegmentIndex+1:selectedSegmentIndex-1;
|
|
714
|
|
715 if (nextIndex < 0 || nextIndex > selectables.length - 1) {
|
|
716 return null;
|
|
717 }
|
|
718 return selectables[nextIndex];
|
|
719 }
|
|
720
|
|
721 public bool restoreSavedLink() {
|
|
722 if (savedSelectedLinkIndex!is -1) {
|
|
723 selectedSegmentIndex = savedSelectedLinkIndex;
|
|
724 return true;
|
|
725 }
|
|
726 return false;
|
|
727 }
|
|
728
|
|
729 public void selectLink(IHyperlinkSegment link) {
|
|
730 if (link is null) {
|
|
731 savedSelectedLinkIndex = selectedSegmentIndex;
|
|
732 selectedSegmentIndex = -1;
|
|
733 }
|
|
734 else {
|
|
735 select(link);
|
|
736
|
|
737 }
|
|
738 }
|
|
739
|
|
740 public void select(IFocusSelectable selectable) {
|
|
741 IFocusSelectable[] selectables = getFocusSelectableSegments();
|
|
742 selectedSegmentIndex = -1;
|
|
743 if (selectables is null)
|
|
744 return;
|
|
745 for (int i = 0; i < selectables.length; i++) {
|
|
746 if (selectables[i].equals(selectable)) {
|
|
747 selectedSegmentIndex = i;
|
|
748 break;
|
|
749 }
|
|
750 }
|
|
751 }
|
|
752
|
|
753 public bool hasFocusSegments() {
|
|
754 IFocusSelectable[] segments = getFocusSelectableSegments();
|
|
755 if (segments.length > 0)
|
|
756 return true;
|
|
757 return false;
|
|
758 }
|
|
759
|
|
760 public void dispose() {
|
|
761 paragraphs = null;
|
|
762 selectedSegmentIndex = -1;
|
|
763 savedSelectedLinkIndex = -1;
|
|
764 selectableSegments = null;
|
|
765 }
|
|
766
|
|
767 /**
|
|
768 * @return Returns the whitespaceNormalized.
|
|
769 */
|
|
770 public bool isWhitespaceNormalized() {
|
|
771 return whitespaceNormalized;
|
|
772 }
|
|
773
|
|
774 /**
|
|
775 * @param whitespaceNormalized
|
|
776 * The whitespaceNormalized to set.
|
|
777 */
|
|
778 public void setWhitespaceNormalized(bool whitespaceNormalized) {
|
|
779 this.whitespaceNormalized = whitespaceNormalized;
|
|
780 }
|
|
781 }
|
|
782 ++/ |