Mercurial > projects > dwt-mac
comparison dwt/custom/StyledText.d @ 41:6337764516f1
Sync dwt/custom with dwt-linux (took copy of complete folder)
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 07 Oct 2008 16:29:55 +0200 |
parents | db5a898b2119 |
children | 07399639c0c8 |
comparison
equal
deleted
inserted
replaced
40:fbe68c33eeee | 41:6337764516f1 |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
8 * Contributors: | 8 * Contributors: |
9 * IBM Corporation - initial API and implementation | 9 * IBM Corporation - initial API and implementation |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
10 *******************************************************************************/ | 12 *******************************************************************************/ |
11 module dwt.custom; | 13 module dwt.custom.StyledText; |
12 | 14 |
13 | 15 |
14 import java.util.*; | 16 import dwt.DWT; |
17 import dwt.DWTError; | |
18 import dwt.DWTException; | |
19 import dwt.accessibility.ACC; | |
20 import dwt.accessibility.Accessible; | |
21 import dwt.accessibility.AccessibleAdapter; | |
22 import dwt.accessibility.AccessibleControlAdapter; | |
23 import dwt.accessibility.AccessibleControlEvent; | |
24 import dwt.accessibility.AccessibleEvent; | |
25 import dwt.accessibility.AccessibleTextAdapter; | |
26 import dwt.accessibility.AccessibleTextEvent; | |
27 import dwt.dnd.Clipboard; | |
28 import dwt.dnd.DND; | |
29 import dwt.dnd.RTFTransfer; | |
30 import dwt.dnd.TextTransfer; | |
31 import dwt.dnd.Transfer; | |
32 import dwt.events.ModifyListener; | |
33 import dwt.events.SelectionEvent; | |
34 import dwt.events.SelectionListener; | |
35 import dwt.events.VerifyListener; | |
36 import dwt.graphics.Color; | |
37 import dwt.graphics.Cursor; | |
38 import dwt.graphics.Font; | |
39 import dwt.graphics.FontData; | |
40 import dwt.graphics.FontMetrics; | |
41 import dwt.graphics.GC; | |
42 import dwt.graphics.GlyphMetrics; | |
43 import dwt.graphics.Image; | |
44 import dwt.graphics.Device; | |
45 import dwt.graphics.Point; | |
46 import dwt.graphics.Rectangle; | |
47 import dwt.graphics.Resource; | |
48 import dwt.graphics.TextLayout; | |
49 import dwt.internal.BidiUtil; | |
50 import dwt.internal.Compatibility; | |
51 import dwt.printing.Printer; | |
52 import dwt.printing.PrinterData; | |
53 import dwt.widgets.Canvas; | |
54 import dwt.widgets.Caret; | |
55 import dwt.widgets.Composite; | |
56 import dwt.widgets.Control; | |
57 import dwt.widgets.Display; | |
58 import dwt.widgets.Event; | |
59 import dwt.widgets.IME; | |
60 import dwt.widgets.Label; | |
61 import dwt.widgets.Listener; | |
62 import dwt.widgets.ScrollBar; | |
63 import dwt.widgets.TypedListener; | |
64 import dwt.custom.StyledTextContent; | |
65 import dwt.custom.TextChangeListener; | |
66 import dwt.custom.StyledTextRenderer; | |
67 import dwt.custom.StyledTextPrintOptions; | |
68 import dwt.custom.ExtendedModifyListener; | |
69 import dwt.custom.BidiSegmentListener; | |
70 import dwt.custom.LineBackgroundListener; | |
71 import dwt.custom.LineStyleListener; | |
72 import dwt.custom.PaintObjectListener; | |
73 import dwt.custom.VerifyKeyListener; | |
74 import dwt.custom.MovementListener; | |
75 import dwt.custom.Bullet; | |
76 import dwt.custom.StyledTextEvent; | |
77 import dwt.custom.StyleRange; | |
78 import dwt.custom.TextChangedEvent; | |
79 import dwt.custom.TextChangingEvent; | |
80 import dwt.custom.DefaultContent; | |
81 import dwt.custom.StyledTextDropTargetEffect; | |
82 import dwt.custom.StyledTextListener; | |
83 import dwt.custom.ST; | |
84 import dwt.dwthelper.Runnable; | |
15 | 85 |
16 import dwt.*; | 86 static import tango.text.Text; |
17 import dwt.accessibility.*; | 87 static import tango.text.Util; |
18 import dwt.dnd.*; | 88 static import tango.io.model.IFile; |
19 import dwt.events.*; | 89 static import tango.text.convert.Utf; |
20 import dwt.graphics.*; | 90 import tango.util.Convert; |
21 import dwt.internal.*; | 91 import dwt.dwthelper.utils; |
22 import dwt.printing.*; | |
23 import dwt.widgets.*; | |
24 | 92 |
25 /** | 93 alias tango.text.Text.Text!(char) StringBuffer; |
26 * A StyledText is an editable user interface object that displays lines | 94 |
27 * of text. The following style attributes can be defined for the text: | 95 /** |
96 * A StyledText is an editable user interface object that displays lines | |
97 * of text. The following style attributes can be defined for the text: | |
28 * <ul> | 98 * <ul> |
29 * <li>foreground color | 99 * <li>foreground color |
30 * <li>background color | 100 * <li>background color |
31 * <li>font style (bold, italic, bold-italic, regular) | 101 * <li>font style (bold, italic, bold-italic, regular) |
32 * <li>underline | 102 * <li>underline |
33 * <li>strikeout | 103 * <li>strikeout |
34 * </ul> | 104 * </ul> |
35 * <p> | 105 * <p> |
36 * In addition to text style attributes, the background color of a line may | 106 * In addition to text style attributes, the background color of a line may |
37 * be specified. | 107 * be specified. |
38 * </p><p> | 108 * </p><p> |
39 * There are two ways to use this widget when specifying text style information. | 109 * There are two ways to use this widget when specifying text style information. |
40 * You may use the API that is defined for StyledText or you may define your own | 110 * You may use the API that is defined for StyledText or you may define your own |
41 * LineStyleListener. If you define your own listener, you will be responsible | 111 * LineStyleListener. If you define your own listener, you will be responsible |
42 * for maintaining the text style information for the widget. IMPORTANT: You may | 112 * for maintaining the text style information for the widget. IMPORTANT: You may |
43 * not define your own listener and use the StyledText API. The following | 113 * not define your own listener and use the StyledText API. The following |
44 * StyledText API is not supported if you have defined a LineStyleListener: | 114 * StyledText API is not supported if you have defined a LineStyleListener: |
45 * <ul> | 115 * <ul> |
46 * <li>getStyleRangeAtOffset(int) | 116 * <li>getStyleRangeAtOffset(int) |
47 * <li>getStyleRanges() | 117 * <li>getStyleRanges() |
49 * <li>setStyleRange(StyleRange) | 119 * <li>setStyleRange(StyleRange) |
50 * <li>setStyleRanges(StyleRange[]) | 120 * <li>setStyleRanges(StyleRange[]) |
51 * </ul> | 121 * </ul> |
52 * </p><p> | 122 * </p><p> |
53 * There are two ways to use this widget when specifying line background colors. | 123 * There are two ways to use this widget when specifying line background colors. |
54 * You may use the API that is defined for StyledText or you may define your own | 124 * You may use the API that is defined for StyledText or you may define your own |
55 * LineBackgroundListener. If you define your own listener, you will be responsible | 125 * LineBackgroundListener. If you define your own listener, you will be responsible |
56 * for maintaining the line background color information for the widget. | 126 * for maintaining the line background color information for the widget. |
57 * IMPORTANT: You may not define your own listener and use the StyledText API. | 127 * IMPORTANT: You may not define your own listener and use the StyledText API. |
58 * The following StyledText API is not supported if you have defined a | 128 * The following StyledText API is not supported if you have defined a |
59 * LineBackgroundListener: | 129 * LineBackgroundListener: |
60 * <ul> | 130 * <ul> |
61 * <li>getLineBackground(int) | 131 * <li>getLineBackground(int) |
62 * <li>setLineBackground(int,int,Color) | 132 * <li>setLineBackground(int,int,Color) |
63 * </ul> | 133 * </ul> |
64 * </p><p> | 134 * </p><p> |
65 * The content implementation for this widget may also be user-defined. To do so, | 135 * The content implementation for this widget may also be user-defined. To do so, |
66 * you must implement the StyledTextContent interface and use the StyledText API | 136 * you must implement the StyledTextContent interface and use the StyledText API |
67 * setContent(StyledTextContent) to initialize the widget. | 137 * setContent(StyledTextContent) to initialize the widget. |
68 * </p><p> | 138 * </p><p> |
69 * <dl> | 139 * <dl> |
70 * <dt><b>Styles:</b><dd>FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP | 140 * <dt><b>Styles:</b><dd>FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP |
71 * <dt><b>Events:</b><dd>ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey | 141 * <dt><b>Events:</b><dd>ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey |
72 * </dl> | 142 * </dl> |
73 * </p><p> | 143 * </p><p> |
74 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | 144 * IMPORTANT: This class is <em>not</em> intended to be subclassed. |
75 * </p> | 145 * </p> |
146 * | |
147 * @see <a href="http://www.eclipse.org/swt/snippets/#styledtext">StyledText snippets</a> | |
148 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Examples: CustomControlExample, TextEditor</a> | |
149 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
76 */ | 150 */ |
77 public class StyledText : Canvas { | 151 public class StyledText : Canvas { |
78 static final char TAB = '\t'; | 152 alias Canvas.computeSize computeSize; |
79 static final String PlatformLineDelimiter = System.getProperty("line.separator"); | 153 |
80 static final int BIDI_CARET_WIDTH = 3; | 154 static const char TAB = '\t'; |
81 static final int DEFAULT_WIDTH = 64; | 155 static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString; |
82 static final int DEFAULT_HEIGHT = 64; | 156 static const int BIDI_CARET_WIDTH = 3; |
83 static final int V_SCROLL_RATE = 50; | 157 static const int DEFAULT_WIDTH = 64; |
84 static final int H_SCROLL_RATE = 10; | 158 static const int DEFAULT_HEIGHT = 64; |
85 | 159 static const int V_SCROLL_RATE = 50; |
86 static final int ExtendedModify = 3000; | 160 static const int H_SCROLL_RATE = 10; |
87 static final int LineGetBackground = 3001; | 161 |
88 static final int LineGetStyle = 3002; | 162 static const int ExtendedModify = 3000; |
89 static final int TextChanging = 3003; | 163 static const int LineGetBackground = 3001; |
90 static final int TextSet = 3004; | 164 static const int LineGetStyle = 3002; |
91 static final int VerifyKey = 3005; | 165 static const int TextChanging = 3003; |
92 static final int TextChanged = 3006; | 166 static const int TextSet = 3004; |
93 static final int LineGetSegments = 3007; | 167 static const int VerifyKey = 3005; |
94 static final int PaintObject = 3008; | 168 static const int TextChanged = 3006; |
95 static final int WordNext = 3009; | 169 static const int LineGetSegments = 3007; |
96 static final int WordPrevious = 3010; | 170 static const int PaintObject = 3008; |
97 | 171 static const int WordNext = 3009; |
98 static final int PREVIOUS_OFFSET_TRAILING = 0; | 172 static const int WordPrevious = 3010; |
99 static final int OFFSET_LEADING = 1; | 173 |
100 | 174 static const int PREVIOUS_OFFSET_TRAILING = 0; |
175 static const int OFFSET_LEADING = 1; | |
176 | |
101 Color selectionBackground; // selection background color | 177 Color selectionBackground; // selection background color |
102 Color selectionForeground; // selection foreground color | 178 Color selectionForeground; // selection foreground color |
103 StyledTextContent content; // native content (default or user specified) | 179 StyledTextContent content; // native content (default or user specified) |
104 StyledTextRenderer renderer; | 180 StyledTextRenderer renderer; |
105 Listener listener; | 181 Listener listener; |
116 int rightMargin; | 192 int rightMargin; |
117 int bottomMargin; | 193 int bottomMargin; |
118 int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 | 194 int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 |
119 int caretOffset = 0; | 195 int caretOffset = 0; |
120 int caretAlignment; | 196 int caretAlignment; |
121 Point selection = new Point(0, 0); // x and y are start and end caret offsets of selection | 197 Point selection; // x and y are start and end caret offsets of selection |
122 Point clipboardSelection; // x and y are start and end caret offsets of previous selection | 198 Point clipboardSelection; // x and y are start and end caret offsets of previous selection |
123 int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text | 199 int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text |
124 Point doubleClickSelection; // selection after last mouse double click | 200 Point doubleClickSelection; // selection after last mouse double click |
125 bool editable = true; | 201 bool editable = true; |
126 bool wordWrap = false; | 202 bool wordWrap = false; |
127 bool doubleClickEnabled = true; // see getDoubleClickEnabled | 203 bool doubleClickEnabled = true; // see getDoubleClickEnabled |
128 bool overwrite = false; // insert/overwrite edit mode | 204 bool overwrite = false; // insert/overwrite edit mode |
129 int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. | 205 int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. |
130 Hashtable keyActionMap = new Hashtable(); | 206 int[int] keyActionMap; |
131 Color background = null; // workaround for bug 4791 | 207 Color background = null; // workaround for bug 4791 |
132 Color foreground = null; // | 208 Color foreground = null; // |
133 Clipboard clipboard; | 209 Clipboard clipboard; |
134 int clickCount; | 210 int clickCount; |
135 int autoScrollDirection = DWT.NULL; // the direction of autoscrolling (up, down, right, left) | 211 int autoScrollDirection = DWT.NULL; // the direction of autoscrolling (up, down, right, left) |
136 int autoScrollDistance = 0; | 212 int autoScrollDistance = 0; |
137 int lastTextChangeStart; // cache data of the | 213 int lastTextChangeStart; // cache data of the |
138 int lastTextChangeNewLineCount; // last text changing | 214 int lastTextChangeNewLineCount; // last text changing |
139 int lastTextChangeNewCharCount; // event for use in the | 215 int lastTextChangeNewCharCount; // event for use in the |
140 int lastTextChangeReplaceLineCount; // text changed handler | 216 int lastTextChangeReplaceLineCount; // text changed handler |
141 int lastTextChangeReplaceCharCount; | 217 int lastTextChangeReplaceCharCount; |
142 int lastLineBottom; // the bottom pixel of the last line been replaced | 218 int lastLineBottom; // the bottom pixel of the last line been replaced |
143 bool isMirrored; | 219 bool isMirrored_; |
144 bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color | 220 bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color |
145 Image leftCaretBitmap = null; | 221 Image leftCaretBitmap = null; |
146 Image rightCaretBitmap = null; | 222 Image rightCaretBitmap = null; |
147 int caretDirection = DWT.NULL; | 223 int caretDirection = DWT.NULL; |
148 int caretWidth = 0; | 224 int caretWidth = 0; |
149 Caret defaultCaret = null; | 225 Caret defaultCaret = null; |
150 bool updateCaretDirection = true; | 226 bool updateCaretDirection = true; |
151 bool fixedLineHeight; | 227 bool fixedLineHeight; |
152 bool dragDetect = true; | 228 bool dragDetect_ = true; |
153 IME ime; | 229 IME ime; |
154 | 230 |
155 int alignment; | 231 int alignment; |
156 bool justify; | 232 bool justify; |
157 int indent; | 233 int indent; |
158 int lineSpacing; | 234 int lineSpacing; |
159 | 235 |
160 final static bool IS_CARBON, IS_GTK, IS_MOTIF; | 236 const static bool IS_CARBON, IS_GTK, IS_MOTIF; |
161 static { | 237 static this(){ |
162 String platform = DWT.getPlatform(); | 238 String platform = DWT.getPlatform(); |
163 IS_CARBON = "carbon".opEquals(platform); | 239 IS_CARBON = ("carbon" == platform); |
164 IS_GTK = "gtk".opEquals(platform); | 240 IS_GTK = ("gtk" == platform); |
165 IS_MOTIF = "motif".opEquals(platform); | 241 IS_MOTIF = ("motif" == platform); |
166 } | 242 } |
167 | 243 |
168 /** | 244 /** |
169 * The Printing class : printing of a range of text. | 245 * The Printing class : printing of a range of text. |
170 * An instance of <code>Printing</code> is returned in the | 246 * An instance of <code>Printing</code> is returned in the |
171 * StyledText#print(Printer) API. The run() method may be | 247 * StyledText#print(Printer) API. The run() method may be |
172 * invoked from any thread. | 248 * invoked from any thread. |
173 */ | 249 */ |
174 static class Printing : Runnable { | 250 static class Printing : Runnable { |
175 final static int LEFT = 0; // left aligned header/footer segment | 251 const static int LEFT = 0; // left aligned header/footer segment |
176 final static int CENTER = 1; // centered header/footer segment | 252 const static int CENTER = 1; // centered header/footer segment |
177 final static int RIGHT = 2; // right aligned header/footer segment | 253 const static int RIGHT = 2; // right aligned header/footer segment |
178 | 254 |
179 Printer printer; | 255 Printer printer; |
180 StyledTextRenderer printerRenderer; | 256 StyledTextRenderer printerRenderer; |
181 StyledTextPrintOptions printOptions; | 257 StyledTextPrintOptions printOptions; |
182 Rectangle clientArea; | 258 Rectangle clientArea; |
183 FontData fontData; | 259 FontData fontData; |
184 Font printerFont; | 260 Font printerFont; |
185 Hashtable resources; | 261 Resource[Resource] resources; |
186 int tabLength; | 262 int tabLength; |
187 GC gc; // printer GC | 263 GC gc; // printer GC |
188 int pageWidth; // width of a printer page in pixels | 264 int pageWidth; // width of a printer page in pixels |
189 int startPage; // first page to print | 265 int startPage; // first page to print |
190 int endPage; // last page to print | 266 int endPage; // last page to print |
191 int startLine; // first (wrapped) line to print | 267 int startLine; // first (wrapped) line to print |
192 int endLine; // last (wrapped) line to print | 268 int endLine; // last (wrapped) line to print |
193 bool singleLine; // widget single line mode | 269 bool singleLine; // widget single line mode |
194 Point selection = null; // selected text | 270 Point selection = null; // selected text |
195 bool mirrored; // indicates the printing gc should be mirrored | 271 bool mirrored; // indicates the printing gc should be mirrored |
196 int lineSpacing; | 272 int lineSpacing; |
197 int printMargin; | 273 int printMargin; |
198 | 274 |
199 /** | 275 /** |
200 * Creates an instance of <code>Printing</code>. | 276 * Creates an instance of <code>Printing</code>. |
201 * Copies the widget content and rendering data that needs | 277 * Copies the widget content and rendering data that needs |
202 * to be requested from listeners. | 278 * to be requested from listeners. |
203 * </p> | 279 * </p> |
204 * @param parent StyledText widget to print. | 280 * @param parent StyledText widget to print. |
205 * @param printer printer device to print on. | 281 * @param printer printer device to print on. |
206 * @param printOptions print options | 282 * @param printOptions print options |
207 */ | 283 */ |
208 this(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { | 284 this(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { |
209 this.printer = printer; | 285 this.printer = printer; |
210 this.printOptions = printOptions; | 286 this.printOptions = printOptions; |
211 this.mirrored = (styledText.getStyle() & DWT.MIRRORED) !is 0; | 287 this.mirrored = (styledText.getStyle() & DWT.MIRRORED) !is 0; |
212 singleLine = styledText.isSingleLine(); | 288 singleLine = styledText.isSingleLine(); |
213 startPage = 1; | 289 startPage = 1; |
214 endPage = Integer.MAX_VALUE; | 290 endPage = int.max; |
215 PrinterData data = printer.getPrinterData(); | 291 PrinterData data = printer.getPrinterData(); |
216 if (data.scope is PrinterData.PAGE_RANGE) { | 292 if (data.scope_ is PrinterData.PAGE_RANGE) { |
217 startPage = data.startPage; | 293 startPage = data.startPage; |
218 endPage = data.endPage; | 294 endPage = data.endPage; |
219 if (endPage < startPage) { | 295 if (endPage < startPage) { |
220 int temp = endPage; | 296 int temp = endPage; |
221 endPage = startPage; | 297 endPage = startPage; |
222 startPage = temp; | 298 startPage = temp; |
223 } | 299 } |
224 } else if (data.scope is PrinterData.SELECTION) { | 300 } else if (data.scope_ is PrinterData.SELECTION) { |
225 selection = styledText.getSelectionRange(); | 301 selection = styledText.getSelectionRange(); |
226 } | 302 } |
227 printerRenderer = new StyledTextRenderer(printer, null); | 303 printerRenderer = new StyledTextRenderer(printer, null); |
228 printerRenderer.setContent(copyContent(styledText.getContent())); | 304 printerRenderer.setContent(copyContent(styledText.getContent())); |
229 cacheLineData(styledText); | 305 cacheLineData(styledText); |
230 } | 306 } |
231 /** | 307 /** |
232 * Caches all line data that needs to be requested from a listener. | 308 * Caches all line data that needs to be requested from a listener. |
233 * </p> | 309 * </p> |
234 * @param printerContent <code>StyledTextContent</code> to request | 310 * @param printerContent <code>StyledTextContent</code> to request |
235 * line data for. | 311 * line data for. |
236 */ | 312 */ |
237 void cacheLineData(StyledText styledText) { | 313 void cacheLineData(StyledText styledText) { |
238 StyledTextRenderer renderer = styledText.renderer; | 314 StyledTextRenderer renderer = styledText.renderer; |
239 renderer.copyInto(printerRenderer); | 315 renderer.copyInto(printerRenderer); |
250 printerRenderer.setLineBackground(i, 1, event.lineBackground); | 326 printerRenderer.setLineBackground(i, 1, event.lineBackground); |
251 } | 327 } |
252 if (styledText.isBidi()) { | 328 if (styledText.isBidi()) { |
253 int[] segments = styledText.getBidiSegments(lineOffset, line); | 329 int[] segments = styledText.getBidiSegments(lineOffset, line); |
254 printerRenderer.setLineSegments(i, 1, segments); | 330 printerRenderer.setLineSegments(i, 1, segments); |
255 } | 331 } |
256 event = styledText.getLineStyleData(lineOffset, line); | 332 event = styledText.getLineStyleData(lineOffset, line); |
257 if (event !is null) { | 333 if (event !is null) { |
258 printerRenderer.setLineIndent(i, 1, event.indent); | 334 printerRenderer.setLineIndent(i, 1, event.indent); |
259 printerRenderer.setLineAlignment(i, 1, event.alignment); | 335 printerRenderer.setLineAlignment(i, 1, event.alignment); |
260 printerRenderer.setLineJustify(i, 1, event.justify); | 336 printerRenderer.setLineJustify(i, 1, event.justify); |
266 } | 342 } |
267 } | 343 } |
268 } | 344 } |
269 Point screenDPI = styledText.getDisplay().getDPI(); | 345 Point screenDPI = styledText.getDisplay().getDPI(); |
270 Point printerDPI = printer.getDPI(); | 346 Point printerDPI = printer.getDPI(); |
271 resources = new Hashtable (); | 347 resources = null; |
272 for (int i = 0; i < lineCount; i++) { | 348 for (int i = 0; i < lineCount; i++) { |
273 Color color = printerRenderer.getLineBackground(i, null); | 349 Color color = printerRenderer.getLineBackground(i, null); |
274 if (color !is null) { | 350 if (color !is null) { |
275 if (printOptions.printLineBackground) { | 351 if (printOptions.printLineBackground) { |
276 Color printerColor = cast(Color)resources.get(color); | 352 Color printerColor; |
277 if (printerColor is null) { | 353 if ( auto p = color in resources ) { |
354 printerColor = cast(Color)*p; | |
355 } | |
356 else { | |
278 printerColor = new Color (printer, color.getRGB()); | 357 printerColor = new Color (printer, color.getRGB()); |
279 resources.put(color, printerColor); | 358 resources[color]=printerColor; |
280 } | 359 } |
281 printerRenderer.setLineBackground(i, 1, printerColor); | 360 printerRenderer.setLineBackground(i, 1, printerColor); |
282 } else { | 361 } else { |
283 printerRenderer.setLineBackground(i, 1, null); | 362 printerRenderer.setLineBackground(i, 1, null); |
284 } | 363 } |
291 StyleRange[] styles = printerRenderer.styles; | 370 StyleRange[] styles = printerRenderer.styles; |
292 for (int i = 0; i < printerRenderer.styleCount; i++) { | 371 for (int i = 0; i < printerRenderer.styleCount; i++) { |
293 StyleRange style = styles[i]; | 372 StyleRange style = styles[i]; |
294 Font font = style.font; | 373 Font font = style.font; |
295 if (style.font !is null) { | 374 if (style.font !is null) { |
296 Font printerFont = cast(Font)resources.get(font); | 375 Font printerFont; |
297 if (printerFont is null) { | 376 if ( auto p = font in resources ) { |
377 printerFont = cast(Font)*p; | |
378 } | |
379 else { | |
298 printerFont = new Font (printer, font.getFontData()); | 380 printerFont = new Font (printer, font.getFontData()); |
299 resources.put(font, printerFont); | 381 resources[font]= printerFont; |
300 } | 382 } |
301 style.font = printerFont; | 383 style.font = printerFont; |
302 } | 384 } |
303 Color color = style.foreground; | 385 Color color = style.foreground; |
304 if (color !is null) { | 386 if (color !is null) { |
305 Color printerColor = cast(Color)resources.get(color); | |
306 if (printOptions.printTextForeground) { | 387 if (printOptions.printTextForeground) { |
307 if (printerColor is null) { | 388 Color printerColor; |
389 if ( auto p = color in resources ) { | |
390 printerColor = cast(Color)*p; | |
391 } | |
392 else { | |
308 printerColor = new Color (printer, color.getRGB()); | 393 printerColor = new Color (printer, color.getRGB()); |
309 resources.put(color, printerColor); | 394 resources[color]=printerColor; |
310 } | 395 } |
311 style.foreground = printerColor; | 396 style.foreground = printerColor; |
312 } else { | 397 } else { |
313 style.foreground = null; | 398 style.foreground = null; |
314 } | 399 } |
315 } | 400 } |
316 color = style.background; | 401 color = style.background; |
317 if (color !is null) { | 402 if (color !is null) { |
318 Color printerColor = cast(Color)resources.get(color); | |
319 if (printOptions.printTextBackground) { | 403 if (printOptions.printTextBackground) { |
320 if (printerColor is null) { | 404 Color printerColor; |
405 if ( auto p = color in resources ) { | |
406 printerColor = cast(Color)*p; | |
407 } | |
408 else { | |
321 printerColor = new Color (printer, color.getRGB()); | 409 printerColor = new Color (printer, color.getRGB()); |
322 resources.put(color, printerColor); | 410 resources[color]=printerColor; |
323 } | 411 } |
324 style.background = printerColor; | 412 style.background = printerColor; |
325 } else { | 413 } else { |
326 style.background = null; | 414 style.background = null; |
327 } | 415 } |
368 void dispose() { | 456 void dispose() { |
369 if (gc !is null) { | 457 if (gc !is null) { |
370 gc.dispose(); | 458 gc.dispose(); |
371 gc = null; | 459 gc = null; |
372 } | 460 } |
373 if (resources !is null) { | 461 foreach( resource; resources.values ){ |
374 Enumeration enumeration = resources.elements(); | 462 resource.dispose(); |
375 while (enumeration.hasMoreElements()) { | 463 } |
376 Resource resource = cast(Resource) enumeration.nextElement(); | 464 resources = null; |
377 resource.dispose(); | |
378 } | |
379 resources = null; | |
380 } | |
381 if (printerFont !is null) { | 465 if (printerFont !is null) { |
382 printerFont.dispose(); | 466 printerFont.dispose(); |
383 printerFont = null; | 467 printerFont = null; |
384 } | 468 } |
385 if (printerRenderer !is null) { | 469 if (printerRenderer !is null) { |
388 } | 472 } |
389 } | 473 } |
390 void init_() { | 474 void init_() { |
391 Rectangle trim = printer.computeTrim(0, 0, 0, 0); | 475 Rectangle trim = printer.computeTrim(0, 0, 0, 0); |
392 Point dpi = printer.getDPI(); | 476 Point dpi = printer.getDPI(); |
393 | 477 |
394 printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), DWT.NORMAL); | 478 printerFont = new Font( cast(Device)printer, fontData.getName(), fontData.getHeight(), DWT.NORMAL); |
395 clientArea = printer.getClientArea(); | 479 clientArea = printer.getClientArea(); |
396 pageWidth = clientArea.width; | 480 pageWidth = clientArea.width; |
397 // one inch margin around text | 481 // one inch margin around text |
398 clientArea.x = dpi.x + trim.x; | 482 clientArea.x = dpi.x + trim.x; |
399 clientArea.y = dpi.y + trim.y; | 483 clientArea.y = dpi.y + trim.y; |
400 clientArea.width -= (clientArea.x + trim.width); | 484 clientArea.width -= (clientArea.x + trim.width); |
401 clientArea.height -= (clientArea.y + trim.height); | 485 clientArea.height -= (clientArea.y + trim.height); |
402 | 486 |
403 int style = mirrored ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; | 487 int style = mirrored ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; |
404 gc = new GC(printer, style); | 488 gc = new GC(printer, style); |
405 gc.setFont(printerFont); | 489 gc.setFont(printerFont); |
406 printerRenderer.setFont(printerFont, tabLength); | 490 printerRenderer.setFont(printerFont, tabLength); |
410 clientArea.height -= lineHeight * 2; | 494 clientArea.height -= lineHeight * 2; |
411 } | 495 } |
412 if (printOptions.footer !is null) { | 496 if (printOptions.footer !is null) { |
413 clientArea.height -= lineHeight * 2; | 497 clientArea.height -= lineHeight * 2; |
414 } | 498 } |
415 | 499 |
416 // TODO not wrapped | 500 // TODO not wrapped |
417 StyledTextContent content = printerRenderer.content; | 501 StyledTextContent content = printerRenderer.content; |
418 startLine = 0; | 502 startLine = 0; |
419 endLine = singleLine ? 0 : content.getLineCount() - 1; | 503 endLine = singleLine ? 0 : content.getLineCount() - 1; |
420 PrinterData data = printer.getPrinterData(); | 504 PrinterData data = printer.getPrinterData(); |
421 if (data.scope is PrinterData.PAGE_RANGE) { | 505 if (data.scope_ is PrinterData.PAGE_RANGE) { |
422 int pageSize = clientArea.height / lineHeight;//WRONG | 506 int pageSize = clientArea.height / lineHeight;//WRONG |
423 startLine = (startPage - 1) * pageSize; | 507 startLine = (startPage - 1) * pageSize; |
424 } else if (data.scope is PrinterData.SELECTION) { | 508 } else if (data.scope_ is PrinterData.SELECTION) { |
425 startLine = content.getLineAtOffset(selection.x); | 509 startLine = content.getLineAtOffset(selection.x); |
426 if (selection.y > 0) { | 510 if (selection.y > 0) { |
427 endLine = content.getLineAtOffset(selection.x + selection.y - 1); | 511 endLine = content.getLineAtOffset(selection.x + selection.y - 1); |
428 } else { | 512 } else { |
429 endLine = startLine - 1; | 513 endLine = startLine - 1; |
475 printer.startPage(); | 559 printer.startPage(); |
476 printDecoration(page, true, printLayout); | 560 printDecoration(page, true, printLayout); |
477 } | 561 } |
478 TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); | 562 TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); |
479 Color lineBackground = printerRenderer.getLineBackground(i, background); | 563 Color lineBackground = printerRenderer.getLineBackground(i, background); |
480 int paragraphBottom = paintY + layout.getBounds().height; | 564 int paragraphBottom = paintY + layout.getBounds().height; |
481 if (paragraphBottom <= pageBottom) { | 565 if (paragraphBottom <= pageBottom) { |
482 //normal case, the whole paragraph fits in the current page | 566 //normal case, the whole paragraph fits in the current page |
483 printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); | 567 printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); |
484 paintY = paragraphBottom; | 568 paintY = paragraphBottom; |
485 } else { | 569 } else { |
505 int height = paragraphBottom - paintY; | 589 int height = paragraphBottom - paintY; |
506 gc.setClipping(clientArea.x, paintY, clientArea.width, height); | 590 gc.setClipping(clientArea.x, paintY, clientArea.width, height); |
507 printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); | 591 printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); |
508 gc.setClipping(cast(Rectangle)null); | 592 gc.setClipping(cast(Rectangle)null); |
509 printDecoration(page, false, printLayout); | 593 printDecoration(page, false, printLayout); |
510 printer.endPage(); | 594 printer.endPage(); |
511 page++; | 595 page++; |
512 if (page <= endPage) { | 596 if (page <= endPage) { |
513 printer.startPage(); | 597 printer.startPage(); |
514 printDecoration(page, true, printLayout); | 598 printDecoration(page, true, printLayout); |
515 paintY = clientArea.y - height; | 599 paintY = clientArea.y - height; |
530 } | 614 } |
531 if (printLayout !is null) printLayout.dispose(); | 615 if (printLayout !is null) printLayout.dispose(); |
532 } | 616 } |
533 /** | 617 /** |
534 * Print header or footer decorations. | 618 * Print header or footer decorations. |
535 * | 619 * |
536 * @param page page number to print, if specified in the StyledTextPrintOptions header or footer. | 620 * @param page page number to print, if specified in the StyledTextPrintOptions header or footer. |
537 * @param header true = print the header, false = print the footer | 621 * @param header true = print the header, false = print the footer |
538 */ | 622 */ |
539 void printDecoration(int page, bool header, TextLayout layout) { | 623 void printDecoration(int page, bool header, TextLayout layout) { |
540 String text = header ? printOptions.header : printOptions.footer; | 624 String text = header ? printOptions.header : printOptions.footer; |
541 if (text is null) return; | 625 if (text is null) return; |
542 int lastSegmentIndex = 0; | 626 int lastSegmentIndex = 0; |
543 for (int i = 0; i < 3; i++) { | 627 for (int i = 0; i < 3; i++) { |
544 int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); | 628 int segmentIndex = text.indexOf( StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); |
545 String segment; | 629 String segment; |
546 if (segmentIndex is -1) { | 630 if (segmentIndex is -1 ) { |
547 segment = text.substring(lastSegmentIndex); | 631 segment = text.substring(lastSegmentIndex); |
548 printDecorationSegment(segment, i, page, header, layout); | 632 printDecorationSegment(segment, i, page, header, layout); |
549 break; | 633 break; |
550 } else { | 634 } else { |
551 segment = text.substring(lastSegmentIndex, segmentIndex); | 635 segment = text.substring(lastSegmentIndex, segmentIndex); |
552 printDecorationSegment(segment, i, page, header, layout); | 636 printDecorationSegment(segment, i, page, header, layout); |
553 lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); | 637 lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length; |
554 } | 638 } |
555 } | 639 } |
556 } | 640 } |
557 /** | 641 /** |
558 * Print one segment of a header or footer decoration. | 642 * Print one segment of a header or footer decoration. |
559 * Headers and footers have three different segments. | 643 * Headers and footers have three different segments. |
560 * One each for left aligned, centered, and right aligned text. | 644 * One each for left aligned, centered, and right aligned text. |
561 * | 645 * |
562 * @param segment decoration segment to print | 646 * @param segment decoration segment to print |
563 * @param alignment alignment of the segment. 0=left, 1=center, 2=right | 647 * @param alignment alignment of the segment. 0=left, 1=center, 2=right |
564 * @param page page number to print, if specified in the decoration segment. | 648 * @param page page number to print, if specified in the decoration segment. |
565 * @param header true = print the header, false = print the footer | 649 * @param header true = print the header, false = print the footer |
566 */ | 650 */ |
567 void printDecorationSegment(String segment, int alignment, int page, bool header, TextLayout layout) { | 651 void printDecorationSegment(String segment, int alignment, int page, bool header, TextLayout layout) { |
568 int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); | 652 int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); |
569 if (pageIndex !is -1) { | 653 if (pageIndex !is -1 ) { |
570 int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); | 654 int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length; |
571 StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex)); | 655 StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex)); |
572 buffer.append (page); | 656 buffer.append (page); |
573 buffer.append (segment.substring(pageIndex + pageTagLength)); | 657 buffer.append (segment.substring(pageIndex + pageTagLength)); |
574 segment = buffer.toString(); | 658 segment = buffer.toString().dup; |
575 } | 659 } |
576 if (segment.length() > 0) { | 660 if (segment.length > 0) { |
577 layout.setText(segment); | 661 layout.setText(segment); |
578 int segmentWidth = layout.getBounds().width; | 662 int segmentWidth = layout.getBounds().width; |
579 int segmentHeight = printerRenderer.getLineHeight(); | 663 int segmentHeight = printerRenderer.getLineHeight(); |
580 int drawX = 0, drawY; | 664 int drawX = 0, drawY; |
581 if (alignment is LEFT) { | 665 if (alignment is LEFT) { |
596 void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) { | 680 void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) { |
597 if (background !is null) { | 681 if (background !is null) { |
598 Rectangle rect = layout.getBounds(); | 682 Rectangle rect = layout.getBounds(); |
599 gc.setBackground(background); | 683 gc.setBackground(background); |
600 gc.fillRectangle(x, y, rect.width, rect.height); | 684 gc.fillRectangle(x, y, rect.width, rect.height); |
601 | 685 |
602 // int lineCount = layout.getLineCount(); | 686 // int lineCount = layout.getLineCount(); |
603 // for (int i = 0; i < lineCount; i++) { | 687 // for (int i = 0; i < lineCount; i++) { |
604 // Rectangle rect = layout.getLineBounds(i); | 688 // Rectangle rect = layout.getLineBounds(i); |
605 // rect.x += paintX; | 689 // rect.x += paintX; |
606 // rect.y += paintY + layout.getSpacing(); | 690 // rect.y += paintY + layout.getSpacing(); |
618 printLayout.setText(lineLabels[index]); | 702 printLayout.setText(lineLabels[index]); |
619 } else { | 703 } else { |
620 printLayout.setText(""); | 704 printLayout.setText(""); |
621 } | 705 } |
622 } else { | 706 } else { |
623 printLayout.setText(String.valueOf(index)); | 707 printLayout.setText(to!(String)(index)); |
624 } | 708 } |
625 int paintX = x - printMargin - printLayout.getBounds().width; | 709 int paintX = x - printMargin - printLayout.getBounds().width; |
626 printLayout.draw(gc, paintX, y); | 710 printLayout.draw(gc, paintX, y); |
627 printLayout.setAscent(-1); | 711 printLayout.setAscent(-1); |
628 printLayout.setDescent(-1); | 712 printLayout.setDescent(-1); |
637 String jobName = printOptions.jobName; | 721 String jobName = printOptions.jobName; |
638 if (jobName is null) { | 722 if (jobName is null) { |
639 jobName = "Printing"; | 723 jobName = "Printing"; |
640 } | 724 } |
641 if (printer.startJob(jobName)) { | 725 if (printer.startJob(jobName)) { |
642 init(); | 726 init_(); |
643 print(); | 727 print(); |
644 dispose(); | 728 dispose(); |
645 printer.endJob(); | 729 printer.endJob(); |
646 } | 730 } |
647 } | 731 } |
648 } | 732 } |
649 /** | 733 /** |
650 * The <code>RTFWriter</code> class is used to write widget content as | 734 * The <code>RTFWriter</code> class is used to write widget content as |
651 * rich text. The implementation complies with the RTF specification | 735 * rich text. The implementation complies with the RTF specification |
652 * version 1.5. | 736 * version 1.5. |
653 * <p> | 737 * <p> |
654 * toString() is guaranteed to return a valid RTF String only after | 738 * toString() is guaranteed to return a valid RTF string only after |
655 * close() has been called. | 739 * close() has been called. |
656 * </p><p> | 740 * </p><p> |
657 * Whole and partial lines and line breaks can be written. Lines will be | 741 * Whole and partial lines and line breaks can be written. Lines will be |
658 * formatted using the styles queried from the LineStyleListener, if | 742 * formatted using the styles queried from the LineStyleListener, if |
659 * set, or those set directly in the widget. All styles are applied to | 743 * set, or those set directly in the widget. All styles are applied to |
660 * the RTF stream like they are rendered by the widget. In addition, the | 744 * the RTF stream like they are rendered by the widget. In addition, the |
661 * widget font name and size is used for the whole text. | 745 * widget font name and size is used for the whole text. |
662 * </p> | 746 * </p> |
663 */ | 747 */ |
664 class RTFWriter : TextWriter { | 748 class RTFWriter : TextWriter { |
665 static final int DEFAULT_FOREGROUND = 0; | 749 |
666 static final int DEFAULT_BACKGROUND = 1; | 750 alias TextWriter.write write; |
667 Vector colorTable, fontTable; | 751 |
752 static const int DEFAULT_FOREGROUND = 0; | |
753 static const int DEFAULT_BACKGROUND = 1; | |
754 Color[] colorTable; | |
755 Font[] fontTable; | |
668 bool WriteUnicode; | 756 bool WriteUnicode; |
669 | 757 |
670 /** | 758 /** |
671 * Creates a RTF writer that writes content starting at offset "start" | 759 * Creates a RTF writer that writes content starting at offset "start" |
672 * in the document. <code>start</code> and <code>length</code>can be set to specify partial | 760 * in the document. <code>start</code> and <code>length</code>can be set to specify partial |
673 * lines. | 761 * lines. |
674 * | 762 * |
675 * @param start start offset of content to write, 0 based from | 763 * @param start start offset of content to write, 0 based from |
676 * beginning of document | 764 * beginning of document |
677 * @param length length of content to write | 765 * @param length length of content to write |
678 */ | 766 */ |
679 public this(int start, int length) { | 767 public this(int start, int length) { |
680 super(start, length); | 768 super(start, length); |
681 colorTable = new Vector(); | 769 colorTable ~= getForeground(); |
682 fontTable = new Vector(); | 770 colorTable ~= getBackground(); |
683 colorTable.addElement(getForeground()); | 771 fontTable ~= getFont(); |
684 colorTable.addElement(getBackground()); | |
685 fontTable.addElement(getFont()); | |
686 setUnicode(); | 772 setUnicode(); |
687 } | 773 } |
688 /** | 774 /** |
689 * Closes the RTF writer. Once closed no more content can be written. | 775 * Closes the RTF writer. Once closed no more content can be written. |
690 * <b>NOTE:</b> <code>toString()</code> does not return a valid RTF String until | 776 * <b>NOTE:</b> <code>toString()</code> does not return a valid RTF string until |
691 * <code>close()</code> has been called. | 777 * <code>close()</code> has been called. |
692 */ | 778 */ |
693 public void close() { | 779 public override void close() { |
694 if (!isClosed()) { | 780 if (!isClosed()) { |
695 writeHeader(); | 781 writeHeader(); |
696 write("\n}}\0"); | 782 write("\n}}\0"); |
697 super.close(); | 783 super.close(); |
698 } | 784 } |
699 } | 785 } |
700 /** | 786 /** |
701 * Returns the index of the specified color in the RTF color table. | 787 * Returns the index of the specified color in the RTF color table. |
702 * | 788 * |
703 * @param color the color | 789 * @param color the color |
704 * @param defaultIndex return value if color is null | 790 * @param defaultIndex return value if color is null |
705 * @return the index of the specified color in the RTF color table | 791 * @return the index of the specified color in the RTF color table |
706 * or "defaultIndex" if "color" is null. | 792 * or "defaultIndex" if "color" is null. |
707 */ | 793 */ |
708 int getColorIndex(Color color, int defaultIndex) { | 794 int getColorIndex(Color color, int defaultIndex) { |
709 if (color is null) return defaultIndex; | 795 if (color is null) return defaultIndex; |
710 int index = colorTable.indexOf(color); | 796 int index = -1; |
797 foreach( i, col; colorTable ){ | |
798 if( col == color ){ | |
799 index = i; | |
800 break; | |
801 } | |
802 } | |
711 if (index is -1) { | 803 if (index is -1) { |
712 index = colorTable.size(); | 804 index = colorTable.length; |
713 colorTable.addElement(color); | 805 colorTable ~= color; |
714 } | 806 } |
715 return index; | 807 return index; |
716 } | 808 } |
717 /** | 809 /** |
718 * Returns the index of the specified color in the RTF color table. | 810 * Returns the index of the specified color in the RTF color table. |
721 * @param defaultIndex return value if color is null | 813 * @param defaultIndex return value if color is null |
722 * @return the index of the specified color in the RTF color table | 814 * @return the index of the specified color in the RTF color table |
723 * or "defaultIndex" if "color" is null. | 815 * or "defaultIndex" if "color" is null. |
724 */ | 816 */ |
725 int getFontIndex(Font font) { | 817 int getFontIndex(Font font) { |
726 int index = fontTable.indexOf(font); | 818 int index = -1; |
819 foreach( i, f; colorTable ){ | |
820 if( f == font ){ | |
821 index = i; | |
822 break; | |
823 } | |
824 } | |
727 if (index is -1) { | 825 if (index is -1) { |
728 index = fontTable.size(); | 826 index = fontTable.length; |
729 fontTable.addElement(font); | 827 fontTable ~= font; |
730 } | 828 } |
731 return index; | 829 return index; |
732 } | 830 } |
733 /** | 831 /** |
734 * Determines if Unicode RTF should be written. | 832 * Determines if Unicode RTF should be written. |
735 * Don't write Unicode RTF on Windows 95/98/ME or NT. | 833 * Don't write Unicode RTF on Windows 95/98/ME or NT. |
736 */ | 834 */ |
737 void setUnicode() { | 835 void setUnicode() { |
738 final String Win95 = "windows 95"; | 836 // const String Win95 = "windows 95"; |
739 final String Win98 = "windows 98"; | 837 // const String Win98 = "windows 98"; |
740 final String WinME = "windows me"; | 838 // const String WinME = "windows me"; |
741 final String WinNT = "windows nt"; | 839 // const String WinNT = "windows nt"; |
742 String osName = System.getProperty("os.name").toLowerCase(); | 840 // String osName = System.getProperty("os.name").toLowerCase(); |
743 String osVersion = System.getProperty("os.version"); | 841 // String osVersion = System.getProperty("os.version"); |
744 int majorVersion = 0; | 842 // int majorVersion = 0; |
745 | 843 // |
746 if (osName.startsWith(WinNT) && osVersion !is null) { | 844 // if (osName.startsWith(WinNT) && osVersion !is null) { |
747 int majorIndex = osVersion.indexOf('.'); | 845 // int majorIndex = osVersion.indexOf('.'); |
748 if (majorIndex !is -1) { | 846 // if (majorIndex !is -1) { |
749 osVersion = osVersion.substring(0, majorIndex); | 847 // osVersion = osVersion.substring(0, majorIndex); |
750 try { | 848 // try { |
751 majorVersion = Integer.parseInt(osVersion); | 849 // majorVersion = Integer.parseInt(osVersion); |
752 } catch (NumberFormatException exception) { | 850 // } catch (NumberFormatException exception) { |
753 // ignore exception. version number remains unknown. | 851 // // ignore exception. version number remains unknown. |
754 // will write without Unicode | 852 // // will write without Unicode |
755 } | 853 // } |
756 } | 854 // } |
757 } | 855 // } |
758 WriteUnicode = !osName.startsWith(Win95) && | 856 // WriteUnicode = !osName.startsWith(Win95) && |
759 !osName.startsWith(Win98) && | 857 // !osName.startsWith(Win98) && |
760 !osName.startsWith(WinME) && | 858 // !osName.startsWith(WinME) && |
761 (!osName.startsWith(WinNT) || majorVersion > 4); | 859 // (!osName.startsWith(WinNT) || majorVersion > 4); |
860 WriteUnicode = true; // we are on linux-gtk | |
762 } | 861 } |
763 /** | 862 /** |
764 * Appends the specified segment of "String" to the RTF data. | 863 * Appends the specified segment of "string" to the RTF data. |
765 * Copy from <code>start</code> up to, but excluding, <code>end</code>. | 864 * Copy from <code>start</code> up to, but excluding, <code>end</code>. |
766 * | 865 * |
767 * @param String String to copy a segment from. Must not contain | 866 * @param string string to copy a segment from. Must not contain |
768 * line breaks. Line breaks should be written using writeLineDelimiter() | 867 * line breaks. Line breaks should be written using writeLineDelimiter() |
769 * @param start start offset of segment. 0 based. | 868 * @param start start offset of segment. 0 based. |
770 * @param end end offset of segment | 869 * @param end end offset of segment |
771 */ | 870 */ |
772 void write(String String, int start, int end) { | 871 void write(String string, int start, int end) { |
773 for (int index = start; index < end; index++) { | 872 start = 0; |
774 char ch = String.charAt(index); | 873 end = string.length; |
874 int incr = 1; | |
875 for (int index = start; index < end; index+=incr) { | |
876 dchar ch = firstCodePoint( string[index .. $], incr ); | |
775 if (ch > 0xFF && WriteUnicode) { | 877 if (ch > 0xFF && WriteUnicode) { |
776 // write the sub String from the last escaped character | 878 // write the sub string from the last escaped character |
777 // to the current one. Fixes bug 21698. | 879 // to the current one. Fixes bug 21698. |
778 if (index > start) { | 880 if (index > start) { |
779 write(String.substring(start, index)); | 881 write( string[start .. index ] ); |
780 } | 882 } |
781 write("\\u"); | 883 write("\\u"); |
782 write(Integer.toString(cast(short) ch)); | 884 write( to!(String)( cast(short)ch )); |
783 write(' '); // control word delimiter | 885 write(' '); // control word delimiter |
784 start = index + 1; | 886 start = index + incr; |
785 } else if (ch is '}' || ch is '{' || ch is '\\') { | 887 } else if (ch is '}' || ch is '{' || ch is '\\') { |
786 // write the sub String from the last escaped character | 888 // write the sub string from the last escaped character |
787 // to the current one. Fixes bug 21698. | 889 // to the current one. Fixes bug 21698. |
788 if (index > start) { | 890 if (index > start) { |
789 write(String.substring(start, index)); | 891 write(string[start .. index]); |
790 } | 892 } |
791 write('\\'); | 893 write('\\'); |
792 write(ch); | 894 write(cast(char)ch); // ok because one of {}\ |
793 start = index + 1; | 895 start = index + 1; |
794 } | 896 } |
795 } | 897 } |
796 // write from the last escaped character to the end. | 898 // write from the last escaped character to the end. |
797 // Fixes bug 21698. | 899 // Fixes bug 21698. |
798 if (start < end) { | 900 if (start < end) { |
799 write(String.substring(start, end)); | 901 write(string[ start .. end]); |
800 } | 902 } |
801 } | 903 } |
802 /** | 904 /** |
803 * Writes the RTF header including font table and color table. | 905 * Writes the RTF header including font table and color table. |
804 */ | 906 */ |
805 void writeHeader() { | 907 void writeHeader() { |
806 StringBuffer header = new StringBuffer(); | 908 StringBuffer header = new StringBuffer(); |
807 FontData fontData = getFont().getFontData()[0]; | 909 FontData fontData = getFont().getFontData()[0]; |
808 header.append("{\\rtf1\\ansi"); | 910 header.append("{\\rtf1\\ansi"); |
809 // specify code page, necessary for copy to work in bidi | 911 // specify code page, necessary for copy to work in bidi |
810 // systems that don't support Unicode RTF. | 912 // systems that don't support Unicode RTF. |
811 String cpg = System.getProperty("file.encoding").toLowerCase(); | 913 // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase(); |
914 String cpg = "UTF16"; | |
915 /+ | |
812 if (cpg.startsWith("cp") || cpg.startsWith("ms")) { | 916 if (cpg.startsWith("cp") || cpg.startsWith("ms")) { |
813 cpg = cpg.substring(2, cpg.length()); | 917 cpg = cpg.substring(2, cpg.length()); |
814 header.append("\\ansicpg"); | 918 header.append("\\ansicpg"); |
815 header.append(cpg); | 919 header.append(cpg); |
816 } | 920 } |
921 +/ | |
817 header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); | 922 header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); |
818 header.append(fontData.getName()); | 923 header.append(fontData.getName()); |
819 header.append(";"); | 924 header.append(";"); |
820 for (int i = 1; i < fontTable.size(); i++) { | 925 for (int i = 1; i < fontTable.length; i++) { |
821 header.append("\\f"); | 926 header.append("\\f"); |
822 header.append(i); | 927 header.append(i); |
823 header.append(" "); | 928 header.append(" "); |
824 FontData fd = (cast(Font)fontTable.elementAt(i)).getFontData()[0]; | 929 FontData fd = (cast(Font)fontTable[i]).getFontData()[0]; |
825 header.append(fd.getName()); | 930 header.append(fd.getName()); |
826 header.append(";"); | 931 header.append(";"); |
827 } | 932 } |
828 header.append("}}\n{\\colortbl"); | 933 header.append("}}\n{\\colortbl"); |
829 for (int i = 0; i < colorTable.size(); i++) { | 934 for (int i = 0; i < colorTable.length; i++) { |
830 Color color = cast(Color) colorTable.elementAt(i); | 935 Color color = cast(Color) colorTable[i]; |
831 header.append("\\red"); | 936 header.append("\\red"); |
832 header.append(color.getRed()); | 937 header.append(color.getRed()); |
833 header.append("\\green"); | 938 header.append("\\green"); |
834 header.append(color.getGreen()); | 939 header.append(color.getGreen()); |
835 header.append("\\blue"); | 940 header.append("\\blue"); |
836 header.append(color.getBlue()); | 941 header.append(color.getBlue()); |
837 header.append(";"); | 942 header.append(";"); |
838 } | 943 } |
839 // some RTF readers ignore the deff0 font tag. Explicitly | 944 // some RTF readers ignore the deff0 font tag. Explicitly |
840 // set the font for the whole document to work around this. | 945 // set the font for the whole document to work around this. |
841 header.append("}\n{\\f0\\fs"); | 946 header.append("}\n{\\f0\\fs"); |
842 // font size is specified in half points | 947 // font size is specified in half points |
843 header.append(fontData.getHeight() * 2); | 948 header.append(fontData.getHeight() * 2); |
844 header.append(" "); | 949 header.append(" "); |
845 write(header.toString(), 0); | 950 write(header.toString(), 0); |
846 } | 951 } |
847 /** | 952 /** |
848 * Appends the specified line text to the RTF data. Lines will be formatted | 953 * Appends the specified line text to the RTF data. Lines will be formatted |
849 * using the styles queried from the LineStyleListener, if set, or those set | 954 * using the styles queried from the LineStyleListener, if set, or those set |
850 * directly in the widget. | 955 * directly in the widget. |
851 * | 956 * |
852 * @param line line text to write as RTF. Must not contain line breaks | 957 * @param line line text to write as RTF. Must not contain line breaks |
853 * Line breaks should be written using writeLineDelimiter() | 958 * Line breaks should be written using writeLineDelimiter() |
854 * @param lineOffset offset of the line. 0 based from the start of the | 959 * @param lineOffset offset of the line. 0 based from the start of the |
855 * widget document. Any text occurring before the start offset or after the | 960 * widget document. Any text occurring before the start offset or after the |
856 * end offset specified during object creation is ignored. | 961 * end offset specified during object creation is ignored. |
857 * @exception DWTException <ul> | 962 * @exception DWTException <ul> |
858 * <li>ERROR_IO when the writer is closed.</li> | 963 * <li>ERROR_IO when the writer is closed.</li> |
859 * </ul> | 964 * </ul> |
860 */ | 965 */ |
861 public void writeLine(String line, int lineOffset) { | 966 public override void writeLine(String line, int lineOffset) { |
862 if (isClosed()) { | 967 if (isClosed()) { |
863 DWT.error(DWT.ERROR_IO); | 968 DWT.error(DWT.ERROR_IO); |
864 } | 969 } |
865 int lineIndex = content.getLineAtOffset(lineOffset); | 970 int lineIndex = content.getLineAtOffset(lineOffset); |
866 int lineAlignment, lineIndent; | 971 int lineAlignment, lineIndent; |
874 lineJustify = event.justify; | 979 lineJustify = event.justify; |
875 ranges = event.ranges; | 980 ranges = event.ranges; |
876 styles = event.styles; | 981 styles = event.styles; |
877 } else { | 982 } else { |
878 lineAlignment = renderer.getLineAlignment(lineIndex, alignment); | 983 lineAlignment = renderer.getLineAlignment(lineIndex, alignment); |
879 lineIndent = renderer.getLineIndent(lineIndex, indent); | 984 lineIndent = renderer.getLineIndent(lineIndex, indent); |
880 lineJustify = renderer.getLineJustify(lineIndex, justify); | 985 lineJustify = renderer.getLineJustify(lineIndex, justify); |
881 ranges = renderer.getRanges(lineOffset, line.length()); | 986 ranges = renderer.getRanges(lineOffset, line.length); |
882 styles = renderer.getStyleRanges(lineOffset, line.length(), false); | 987 styles = renderer.getStyleRanges(lineOffset, line.length, false); |
883 } | 988 } |
884 if (styles is null) styles = new StyleRange[0]; | 989 if (styles is null) styles = new StyleRange[0]; |
885 Color lineBackground = renderer.getLineBackground(lineIndex, null); | 990 Color lineBackground = renderer.getLineBackground(lineIndex, null); |
886 event = getLineBackgroundData(lineOffset, line); | 991 event = getLineBackgroundData(lineOffset, line); |
887 if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground; | 992 if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground; |
888 writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, lineAlignment, lineJustify); | 993 writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, lineAlignment, lineJustify); |
889 } | 994 } |
893 * @param lineDelimiter line delimiter to write as RTF. | 998 * @param lineDelimiter line delimiter to write as RTF. |
894 * @exception DWTException <ul> | 999 * @exception DWTException <ul> |
895 * <li>ERROR_IO when the writer is closed.</li> | 1000 * <li>ERROR_IO when the writer is closed.</li> |
896 * </ul> | 1001 * </ul> |
897 */ | 1002 */ |
898 public void writeLineDelimiter(String lineDelimiter) { | 1003 public override void writeLineDelimiter(String lineDelimiter) { |
899 if (isClosed()) { | 1004 if (isClosed()) { |
900 DWT.error(DWT.ERROR_IO); | 1005 DWT.error(DWT.ERROR_IO); |
901 } | 1006 } |
902 write(lineDelimiter, 0, lineDelimiter.length()); | 1007 write(lineDelimiter, 0, lineDelimiter.length); |
903 write("\\par "); | 1008 write("\\par "); |
904 } | 1009 } |
905 /** | 1010 /** |
906 * Appends the specified line text to the RTF data. | 1011 * Appends the specified line text to the RTF data. |
907 * <p> | 1012 * <p> |
911 * Background colors are written using the \highlight tag (vs. the \cb tag). | 1016 * Background colors are written using the \highlight tag (vs. the \cb tag). |
912 * </p> | 1017 * </p> |
913 * | 1018 * |
914 * @param line line text to write as RTF. Must not contain line breaks | 1019 * @param line line text to write as RTF. Must not contain line breaks |
915 * Line breaks should be written using writeLineDelimiter() | 1020 * Line breaks should be written using writeLineDelimiter() |
916 * @param lineOffset offset of the line. 0 based from the start of the | 1021 * @param lineOffset offset of the line. 0 based from the start of the |
917 * widget document. Any text occurring before the start offset or after the | 1022 * widget document. Any text occurring before the start offset or after the |
918 * end offset specified during object creation is ignored. | 1023 * end offset specified during object creation is ignored. |
919 * @param styles styles to use for formatting. Must not be null. | 1024 * @param styles styles to use for formatting. Must not be null. |
920 * @param lineBackground line background color to use for formatting. | 1025 * @param lineBackground line background color to use for formatting. |
921 * May be null. | 1026 * May be null. |
922 */ | 1027 */ |
923 void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, bool justify) { | 1028 void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, bool justify) { |
924 int lineLength = line.length(); | 1029 int lineLength = line.length; |
925 int startOffset = getStart(); | 1030 int startOffset = getStart(); |
926 int writeOffset = startOffset - lineOffset; | 1031 int writeOffset = startOffset - lineOffset; |
927 if (writeOffset >= lineLength) return; | 1032 if (writeOffset >= lineLength) return; |
928 int lineIndex = Math.max(0, writeOffset); | 1033 int lineIndex = Math.max(0, writeOffset); |
929 | 1034 |
930 write("\\fi"); | 1035 write("\\fi"); |
931 write(indent); | 1036 write(indent); |
932 switch (alignment) { | 1037 switch (alignment) { |
933 case DWT.LEFT: write("\\ql"); break; | 1038 case DWT.LEFT: write("\\ql"); break; |
934 case DWT.CENTER: write("\\qc"); break; | 1039 case DWT.CENTER: write("\\qc"); break; |
935 case DWT.RIGHT: write("\\qr"); break; | 1040 case DWT.RIGHT: write("\\qr"); break; |
1041 default: | |
936 } | 1042 } |
937 if (justify) write("\\qj"); | 1043 if (justify) write("\\qj"); |
938 write(" "); | 1044 write(" "); |
939 | 1045 |
940 if (lineBackground !is null) { | 1046 if (lineBackground !is null) { |
941 write("{\\highlight"); | 1047 write("{\\highlight"); |
942 write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); | 1048 write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); |
943 write(" "); | 1049 write(" "); |
944 } | 1050 } |
945 int endOffset = startOffset + super.getCharCount(); | 1051 int endOffset = startOffset + super.getCharCount(); |
946 int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); | 1052 int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); |
947 for (int i = 0; i < styles.length; i++) { | 1053 for (int i = 0; i < styles.length; i++) { |
948 StyleRange style = styles[i]; | 1054 StyleRange style = styles[i]; |
963 break; | 1069 break; |
964 } | 1070 } |
965 // write any unstyled text | 1071 // write any unstyled text |
966 if (lineIndex < start) { | 1072 if (lineIndex < start) { |
967 // copy to start of style | 1073 // copy to start of style |
968 // style starting beyond end of write range or end of line | 1074 // style starting beyond end of write range or end of line |
969 // is guarded against above. | 1075 // is guarded against above. |
970 write(line, lineIndex, start); | 1076 write(line, lineIndex, start); |
971 lineIndex = start; | 1077 lineIndex = start; |
972 } | 1078 } |
973 // write styled text | 1079 // write styled text |
986 FontData fontData = font.getFontData()[0]; | 1092 FontData fontData = font.getFontData()[0]; |
987 write("\\fs"); | 1093 write("\\fs"); |
988 write(fontData.getHeight() * 2); | 1094 write(fontData.getHeight() * 2); |
989 } else { | 1095 } else { |
990 if ((style.fontStyle & DWT.BOLD) !is 0) { | 1096 if ((style.fontStyle & DWT.BOLD) !is 0) { |
991 write("\\b"); | 1097 write("\\b"); |
992 } | 1098 } |
993 if ((style.fontStyle & DWT.ITALIC) !is 0) { | 1099 if ((style.fontStyle & DWT.ITALIC) !is 0) { |
994 write("\\i"); | 1100 write("\\i"); |
995 } | 1101 } |
996 } | 1102 } |
997 if (style.underline) { | 1103 if (style.underline) { |
998 write("\\ul"); | 1104 write("\\ul"); |
999 } | 1105 } |
1000 if (style.strikeout) { | 1106 if (style.strikeout) { |
1001 write("\\strike"); | 1107 write("\\strike"); |
1002 } | 1108 } |
1003 write(" "); | 1109 write(" "); |
1004 // copy to end of style or end of write range or end of line | 1110 // copy to end of style or end of write range or end of line |
1005 int copyEnd = Math.min(end, lineEndOffset); | 1111 int copyEnd = Math.min(end, lineEndOffset); |
1006 // guard against invalid styles and let style processing continue | 1112 // guard against invalid styles and let style processing continue |
1007 copyEnd = Math.max(copyEnd, lineIndex); | 1113 copyEnd = Math.max(copyEnd, lineIndex); |
1008 write(line, lineIndex, copyEnd); | 1114 write(line, lineIndex, copyEnd); |
1009 if (font is null) { | 1115 if (font is null) { |
1010 if ((style.fontStyle & DWT.BOLD) !is 0) { | 1116 if ((style.fontStyle & DWT.BOLD) !is 0) { |
1011 write("\\b0"); | 1117 write("\\b0"); |
1012 } | 1118 } |
1013 if ((style.fontStyle & DWT.ITALIC) !is 0) { | 1119 if ((style.fontStyle & DWT.ITALIC) !is 0) { |
1014 write("\\i0"); | 1120 write("\\i0"); |
1015 } | 1121 } |
1016 } | 1122 } |
1017 if (style.underline) { | 1123 if (style.underline) { |
1018 write("\\ul0"); | 1124 write("\\ul0"); |
1019 } | 1125 } |
1030 if (lineBackground !is null) write("}"); | 1136 if (lineBackground !is null) write("}"); |
1031 } | 1137 } |
1032 } | 1138 } |
1033 /** | 1139 /** |
1034 * The <code>TextWriter</code> class is used to write widget content to | 1140 * The <code>TextWriter</code> class is used to write widget content to |
1035 * a String. Whole and partial lines and line breaks can be written. To write | 1141 * a string. Whole and partial lines and line breaks can be written. To write |
1036 * partial lines, specify the start and length of the desired segment | 1142 * partial lines, specify the start and length of the desired segment |
1037 * during object creation. | 1143 * during object creation. |
1038 * <p> | 1144 * <p> |
1039 * </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid String only after close() | 1145 * </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close() |
1040 * has been called. | 1146 * has been called. |
1041 * </p> | 1147 * </p> |
1042 */ | 1148 */ |
1043 class TextWriter { | 1149 class TextWriter { |
1044 private StringBuffer buffer; | 1150 private StringBuffer buffer; |
1045 private int startOffset; // offset of first character that will be written | 1151 private int startOffset; // offset of first character that will be written |
1046 private int endOffset; // offset of last character that will be written. | 1152 private int endOffset; // offset of last character that will be written. |
1047 // 0 based from the beginning of the widget text. | 1153 // 0 based from the beginning of the widget text. |
1048 private bool isClosed = false; | 1154 private bool isClosed_ = false; |
1049 | 1155 |
1050 /** | 1156 /** |
1051 * Creates a writer that writes content starting at offset "start" | 1157 * Creates a writer that writes content starting at offset "start" |
1052 * in the document. <code>start</code> and <code>length</code> can be set to specify partial lines. | 1158 * in the document. <code>start</code> and <code>length</code> can be set to specify partial lines. |
1053 * | 1159 * |
1054 * @param start start offset of content to write, 0 based from beginning of document | 1160 * @param start start offset of content to write, 0 based from beginning of document |
1059 startOffset = start; | 1165 startOffset = start; |
1060 endOffset = start + length; | 1166 endOffset = start + length; |
1061 } | 1167 } |
1062 /** | 1168 /** |
1063 * Closes the writer. Once closed no more content can be written. | 1169 * Closes the writer. Once closed no more content can be written. |
1064 * <b>NOTE:</b> <code>toString()</code> is not guaranteed to return a valid String unless | 1170 * <b>NOTE:</b> <code>toString()</code> is not guaranteed to return a valid string unless |
1065 * the writer is closed. | 1171 * the writer is closed. |
1066 */ | 1172 */ |
1067 public void close() { | 1173 public void close() { |
1068 if (!isClosed) { | 1174 if (!isClosed_) { |
1069 isClosed = true; | 1175 isClosed_ = true; |
1070 } | 1176 } |
1071 } | 1177 } |
1072 /** | 1178 /** |
1073 * Returns the number of characters to write. | 1179 * Returns the number of characters to write. |
1074 * @return the integer number of characters to write | 1180 * @return the integer number of characters to write |
1075 */ | 1181 */ |
1076 public int getCharCount() { | 1182 public int getCharCount() { |
1077 return endOffset - startOffset; | 1183 return endOffset - startOffset; |
1078 } | 1184 } |
1079 /** | 1185 /** |
1080 * Returns the offset where writing starts. 0 based from the start of | 1186 * Returns the offset where writing starts. 0 based from the start of |
1081 * the widget text. Used to write partial lines. | 1187 * the widget text. Used to write partial lines. |
1082 * @return the integer offset where writing starts | 1188 * @return the integer offset where writing starts |
1083 */ | 1189 */ |
1084 public int getStart() { | 1190 public int getStart() { |
1085 return startOffset; | 1191 return startOffset; |
1087 /** | 1193 /** |
1088 * Returns whether the writer is closed. | 1194 * Returns whether the writer is closed. |
1089 * @return a bool specifying whether or not the writer is closed | 1195 * @return a bool specifying whether or not the writer is closed |
1090 */ | 1196 */ |
1091 public bool isClosed() { | 1197 public bool isClosed() { |
1092 return isClosed; | 1198 return isClosed_; |
1093 } | 1199 } |
1094 /** | 1200 /** |
1095 * Returns the String. <code>close()</code> must be called before <code>toString()</code> | 1201 * Returns the string. <code>close()</code> must be called before <code>toString()</code> |
1096 * is guaranteed to return a valid String. | 1202 * is guaranteed to return a valid string. |
1097 * | 1203 * |
1098 * @return the String | 1204 * @return the string |
1099 */ | 1205 */ |
1100 public String toString() { | 1206 public override String toString() { |
1101 return buffer.toString(); | 1207 return buffer.toString(); |
1102 } | 1208 } |
1103 /** | 1209 /** |
1104 * Appends the given String to the data. | 1210 * Appends the given string to the data. |
1105 */ | 1211 */ |
1106 void write(String String) { | 1212 void write(String string) { |
1107 buffer.append(String); | 1213 buffer.append(string); |
1108 } | 1214 } |
1109 /** | 1215 /** |
1110 * Inserts the given String to the data at the specified offset. | 1216 * Inserts the given string to the data at the specified offset. |
1111 * <p> | 1217 * <p> |
1112 * Do nothing if "offset" is < 0 or > getCharCount() | 1218 * Do nothing if "offset" is < 0 or > getCharCount() |
1113 * </p> | 1219 * </p> |
1114 * | 1220 * |
1115 * @param String text to insert | 1221 * @param string text to insert |
1116 * @param offset offset in the existing data to insert "String" at. | 1222 * @param offset offset in the existing data to insert "string" at. |
1117 */ | 1223 */ |
1118 void write(String String, int offset) { | 1224 void write(String string, int offset) { |
1119 if (offset < 0 || offset > buffer.length()) { | 1225 if (offset < 0 || offset > buffer.length()) { |
1120 return; | 1226 return; |
1121 } | 1227 } |
1122 buffer.insert(offset, String); | 1228 buffer.select( offset ); |
1229 buffer.prepend( string ); | |
1123 } | 1230 } |
1124 /** | 1231 /** |
1125 * Appends the given int to the data. | 1232 * Appends the given int to the data. |
1126 */ | 1233 */ |
1127 void write(int i) { | 1234 void write(int i) { |
1136 /** | 1243 /** |
1137 * Appends the specified line text to the data. | 1244 * Appends the specified line text to the data. |
1138 * | 1245 * |
1139 * @param line line text to write. Must not contain line breaks | 1246 * @param line line text to write. Must not contain line breaks |
1140 * Line breaks should be written using writeLineDelimiter() | 1247 * Line breaks should be written using writeLineDelimiter() |
1141 * @param lineOffset offset of the line. 0 based from the start of the | 1248 * @param lineOffset offset of the line. 0 based from the start of the |
1142 * widget document. Any text occurring before the start offset or after the | 1249 * widget document. Any text occurring before the start offset or after the |
1143 * end offset specified during object creation is ignored. | 1250 * end offset specified during object creation is ignored. |
1144 * @exception DWTException <ul> | 1251 * @exception DWTException <ul> |
1145 * <li>ERROR_IO when the writer is closed.</li> | 1252 * <li>ERROR_IO when the writer is closed.</li> |
1146 * </ul> | 1253 * </ul> |
1147 */ | 1254 */ |
1148 public void writeLine(String line, int lineOffset) { | 1255 public void writeLine(String line, int lineOffset) { |
1149 if (isClosed) { | 1256 if (isClosed_) { |
1150 DWT.error(DWT.ERROR_IO); | 1257 DWT.error(DWT.ERROR_IO); |
1151 } | 1258 } |
1152 int writeOffset = startOffset - lineOffset; | 1259 int writeOffset = startOffset - lineOffset; |
1153 int lineLength = line.length(); | 1260 int lineLength = line.length; |
1154 int lineIndex; | 1261 int lineIndex; |
1155 if (writeOffset >= lineLength) { | 1262 if (writeOffset >= lineLength) { |
1156 return; // whole line is outside write range | 1263 return; // whole line is outside write range |
1157 } else if (writeOffset > 0) { | 1264 } else if (writeOffset > 0) { |
1158 lineIndex = writeOffset; // line starts before write start | 1265 lineIndex = writeOffset; // line starts before write start |
1171 * @exception DWTException <ul> | 1278 * @exception DWTException <ul> |
1172 * <li>ERROR_IO when the writer is closed.</li> | 1279 * <li>ERROR_IO when the writer is closed.</li> |
1173 * </ul> | 1280 * </ul> |
1174 */ | 1281 */ |
1175 public void writeLineDelimiter(String lineDelimiter) { | 1282 public void writeLineDelimiter(String lineDelimiter) { |
1176 if (isClosed) { | 1283 if (isClosed_) { |
1177 DWT.error(DWT.ERROR_IO); | 1284 DWT.error(DWT.ERROR_IO); |
1178 } | 1285 } |
1179 write(lineDelimiter); | 1286 write(lineDelimiter); |
1180 } | 1287 } |
1181 } | 1288 } |
1184 * Constructs a new instance of this class given its parent | 1291 * Constructs a new instance of this class given its parent |
1185 * and a style value describing its behavior and appearance. | 1292 * and a style value describing its behavior and appearance. |
1186 * <p> | 1293 * <p> |
1187 * The style value is either one of the style constants defined in | 1294 * The style value is either one of the style constants defined in |
1188 * class <code>DWT</code> which is applicable to instances of this | 1295 * class <code>DWT</code> which is applicable to instances of this |
1189 * class, or must be built by <em>bitwise OR</em>'ing together | 1296 * class, or must be built by <em>bitwise OR</em>'ing together |
1190 * (that is, using the <code>int</code> "|" operator) two or more | 1297 * (that is, using the <code>int</code> "|" operator) two or more |
1191 * of those <code>DWT</code> style constants. The class description | 1298 * of those <code>DWT</code> style constants. The class description |
1192 * lists the style constants that are applicable to the class. | 1299 * lists the style constants that are applicable to the class. |
1193 * Style bits are also inherited from superclasses. | 1300 * Style bits are also inherited from superclasses. |
1194 * </p> | 1301 * </p> |
1209 * @see DWT#SINGLE | 1316 * @see DWT#SINGLE |
1210 * @see DWT#WRAP | 1317 * @see DWT#WRAP |
1211 * @see #getStyle | 1318 * @see #getStyle |
1212 */ | 1319 */ |
1213 public this(Composite parent, int style) { | 1320 public this(Composite parent, int style) { |
1321 selection = new Point(0, 0); | |
1214 super(parent, checkStyle(style)); | 1322 super(parent, checkStyle(style)); |
1215 // set the fg in the OS to ensure that these are the same as StyledText, necessary | 1323 // set the fg in the OS to ensure that these are the same as StyledText, necessary |
1216 // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses | 1324 // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses |
1217 super.setForeground(getForeground()); | 1325 super.setForeground(getForeground()); |
1218 super.setDragDetect(false); | 1326 super.setDragDetect(false); |
1219 Display display = getDisplay(); | 1327 Display display = getDisplay(); |
1220 isMirrored = (super.getStyle() & DWT.MIRRORED) !is 0; | 1328 isMirrored_ = (super.getStyle() & DWT.MIRRORED) !is 0; |
1221 fixedLineHeight = true; | 1329 fixedLineHeight = true; |
1222 if ((style & DWT.READ_ONLY) !is 0) { | 1330 if ((style & DWT.READ_ONLY) !is 0) { |
1223 setEditable(false); | 1331 setEditable(false); |
1224 } | 1332 } |
1225 leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0; | 1333 leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0; |
1238 if ((style & DWT.WRAP) !is 0) { | 1346 if ((style & DWT.WRAP) !is 0) { |
1239 setWordWrap(true); | 1347 setWordWrap(true); |
1240 } | 1348 } |
1241 if (isBidiCaret()) { | 1349 if (isBidiCaret()) { |
1242 createCaretBitmaps(); | 1350 createCaretBitmaps(); |
1243 Runnable runnable = new Runnable() { | 1351 Runnable runnable = new class() Runnable { |
1244 public void run() { | 1352 public void run() { |
1245 int direction = BidiUtil.getKeyboardLanguage() is BidiUtil.KEYBOARD_BIDI ? DWT.RIGHT : DWT.LEFT; | 1353 int direction = BidiUtil.getKeyboardLanguage() is BidiUtil.KEYBOARD_BIDI ? DWT.RIGHT : DWT.LEFT; |
1246 if (direction is caretDirection) return; | 1354 if (direction is caretDirection) return; |
1247 if (getCaret() !is defaultCaret) return; | 1355 if (getCaret() !is defaultCaret) return; |
1248 Point newCaretPos = getPointAtOffset(caretOffset); | 1356 Point newCaretPos = getPointAtOffset(caretOffset); |
1249 setCaretLocation(newCaretPos, direction); | 1357 setCaretLocation(newCaretPos, direction); |
1250 } | 1358 } |
1251 }; | 1359 }; |
1252 BidiUtil.addLanguageListener(this, runnable); | 1360 BidiUtil.addLanguageListener(this, runnable); |
1253 } | 1361 } |
1254 setCaret(defaultCaret); | 1362 setCaret(defaultCaret); |
1255 calculateScrollBars(); | 1363 calculateScrollBars(); |
1256 createKeyBindings(); | 1364 createKeyBindings(); |
1257 setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); | 1365 setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); |
1258 installListeners(); | 1366 installListeners(); |
1259 initializeAccessible(); | 1367 initializeAccessible(); |
1260 setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); | 1368 setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); |
1261 } | 1369 } |
1262 /** | 1370 /** |
1263 * Adds an extended modify listener. An ExtendedModify event is sent by the | 1371 * Adds an extended modify listener. An ExtendedModify event is sent by the |
1264 * widget when the widget text has changed. | 1372 * widget when the widget text has changed. |
1265 * | 1373 * |
1266 * @param extendedModifyListener the listener | 1374 * @param extendedModifyListener the listener |
1267 * @exception DWTException <ul> | 1375 * @exception DWTException <ul> |
1268 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1376 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1279 addListener(ExtendedModify, typedListener); | 1387 addListener(ExtendedModify, typedListener); |
1280 } | 1388 } |
1281 /** | 1389 /** |
1282 * Adds a bidirectional segment listener. | 1390 * Adds a bidirectional segment listener. |
1283 * <p> | 1391 * <p> |
1284 * A BidiSegmentEvent is sent | 1392 * A BidiSegmentEvent is sent |
1285 * whenever a line of text is measured or rendered. The user can | 1393 * whenever a line of text is measured or rendered. The user can |
1286 * specify text ranges in the line that should be treated as if they | 1394 * specify text ranges in the line that should be treated as if they |
1287 * had a different direction than the surrounding text. | 1395 * had a different direction than the surrounding text. |
1288 * This may be used when adjacent segments of right-to-left text should | 1396 * This may be used when adjacent segments of right-to-left text should |
1289 * not be reordered relative to each other. | 1397 * not be reordered relative to each other. |
1290 * E.g., Multiple Java String literals in a right-to-left language | 1398 * E.g., Multiple Java string literals in a right-to-left language |
1291 * should generally remain in logical order to each other, that is, the | 1399 * should generally remain in logical order to each other, that is, the |
1292 * way they are stored. | 1400 * way they are stored. |
1293 * </p> | 1401 * </p> |
1294 * | 1402 * |
1295 * @param listener the listener | 1403 * @param listener the listener |
1296 * @exception DWTException <ul> | 1404 * @exception DWTException <ul> |
1297 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1405 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1307 checkWidget(); | 1415 checkWidget(); |
1308 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1416 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1309 addListener(LineGetSegments, new StyledTextListener(listener)); | 1417 addListener(LineGetSegments, new StyledTextListener(listener)); |
1310 } | 1418 } |
1311 /** | 1419 /** |
1312 * Adds a line background listener. A LineGetBackground event is sent by the | 1420 * Adds a line background listener. A LineGetBackground event is sent by the |
1313 * widget to determine the background color for a line. | 1421 * widget to determine the background color for a line. |
1314 * | 1422 * |
1315 * @param listener the listener | 1423 * @param listener the listener |
1316 * @exception DWTException <ul> | 1424 * @exception DWTException <ul> |
1317 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1425 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1328 renderer.clearLineBackground(0, content.getLineCount()); | 1436 renderer.clearLineBackground(0, content.getLineCount()); |
1329 } | 1437 } |
1330 addListener(LineGetBackground, new StyledTextListener(listener)); | 1438 addListener(LineGetBackground, new StyledTextListener(listener)); |
1331 } | 1439 } |
1332 /** | 1440 /** |
1333 * Adds a line style listener. A LineGetStyle event is sent by the widget to | 1441 * Adds a line style listener. A LineGetStyle event is sent by the widget to |
1334 * determine the styles for a line. | 1442 * determine the styles for a line. |
1335 * | 1443 * |
1336 * @param listener the listener | 1444 * @param listener the listener |
1337 * @exception DWTException <ul> | 1445 * @exception DWTException <ul> |
1338 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1446 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1349 setStyleRanges(0, 0, null, null, true); | 1457 setStyleRanges(0, 0, null, null, true); |
1350 renderer.clearLineStyle(0, content.getLineCount()); | 1458 renderer.clearLineStyle(0, content.getLineCount()); |
1351 } | 1459 } |
1352 addListener(LineGetStyle, new StyledTextListener(listener)); | 1460 addListener(LineGetStyle, new StyledTextListener(listener)); |
1353 } | 1461 } |
1354 /** | 1462 /** |
1355 * Adds a modify listener. A Modify event is sent by the widget when the widget text | 1463 * Adds a modify listener. A Modify event is sent by the widget when the widget text |
1356 * has changed. | 1464 * has changed. |
1357 * | 1465 * |
1358 * @param modifyListener the listener | 1466 * @param modifyListener the listener |
1359 * @exception DWTException <ul> | 1467 * @exception DWTException <ul> |
1360 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1468 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1367 public void addModifyListener(ModifyListener modifyListener) { | 1475 public void addModifyListener(ModifyListener modifyListener) { |
1368 checkWidget(); | 1476 checkWidget(); |
1369 if (modifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1477 if (modifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1370 addListener(DWT.Modify, new TypedListener(modifyListener)); | 1478 addListener(DWT.Modify, new TypedListener(modifyListener)); |
1371 } | 1479 } |
1372 /** | 1480 /** |
1373 * Adds a paint object listener. A paint object event is sent by the widget when an object | 1481 * Adds a paint object listener. A paint object event is sent by the widget when an object |
1374 * needs to be drawn. | 1482 * needs to be drawn. |
1375 * | 1483 * |
1376 * @param listener the listener | 1484 * @param listener the listener |
1377 * @exception DWTException <ul> | 1485 * @exception DWTException <ul> |
1379 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1487 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1380 * </ul> | 1488 * </ul> |
1381 * @exception IllegalArgumentException <ul> | 1489 * @exception IllegalArgumentException <ul> |
1382 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 1490 * <li>ERROR_NULL_ARGUMENT when listener is null</li> |
1383 * </ul> | 1491 * </ul> |
1384 * | 1492 * |
1385 * @since 3.2 | 1493 * @since 3.2 |
1386 * | 1494 * |
1387 * @see PaintObjectListener | 1495 * @see PaintObjectListener |
1388 * @see PaintObjectEvent | 1496 * @see PaintObjectEvent |
1389 */ | 1497 */ |
1390 public void addPaintObjectListener(PaintObjectListener listener) { | 1498 public void addPaintObjectListener(PaintObjectListener listener) { |
1391 checkWidget(); | 1499 checkWidget(); |
1392 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1500 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1393 addListener(PaintObject, new StyledTextListener(listener)); | 1501 addListener(PaintObject, new StyledTextListener(listener)); |
1394 } | 1502 } |
1395 /** | 1503 /** |
1396 * Adds a selection listener. A Selection event is sent by the widget when the | 1504 * Adds a selection listener. A Selection event is sent by the widget when the |
1397 * user changes the selection. | 1505 * user changes the selection. |
1398 * <p> | 1506 * <p> |
1399 * When <code>widgetSelected</code> is called, the event x and y fields contain | 1507 * When <code>widgetSelected</code> is called, the event x and y fields contain |
1400 * the start and end caret indices of the selection. | 1508 * the start and end caret indices of the selection. |
1401 * <code>widgetDefaultSelected</code> is not called for StyledTexts. | 1509 * <code>widgetDefaultSelected</code> is not called for StyledTexts. |
1402 * </p> | 1510 * </p> |
1403 * | 1511 * |
1404 * @param listener the listener which should be notified when the user changes the receiver's selection | 1512 * @param listener the listener which should be notified when the user changes the receiver's selection |
1405 | 1513 |
1406 * @exception IllegalArgumentException <ul> | 1514 * @exception IllegalArgumentException <ul> |
1407 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | 1515 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> |
1408 * </ul> | 1516 * </ul> |
1418 public void addSelectionListener(SelectionListener listener) { | 1526 public void addSelectionListener(SelectionListener listener) { |
1419 checkWidget(); | 1527 checkWidget(); |
1420 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1528 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1421 addListener(DWT.Selection, new TypedListener(listener)); | 1529 addListener(DWT.Selection, new TypedListener(listener)); |
1422 } | 1530 } |
1423 /** | 1531 /** |
1424 * Adds a verify key listener. A VerifyKey event is sent by the widget when a key | 1532 * Adds a verify key listener. A VerifyKey event is sent by the widget when a key |
1425 * is pressed. The widget ignores the key press if the listener sets the doit field | 1533 * is pressed. The widget ignores the key press if the listener sets the doit field |
1426 * of the event to false. | 1534 * of the event to false. |
1427 * | 1535 * |
1428 * @param listener the listener | 1536 * @param listener the listener |
1429 * @exception DWTException <ul> | 1537 * @exception DWTException <ul> |
1430 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1538 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1431 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1539 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1437 public void addVerifyKeyListener(VerifyKeyListener listener) { | 1545 public void addVerifyKeyListener(VerifyKeyListener listener) { |
1438 checkWidget(); | 1546 checkWidget(); |
1439 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1547 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1440 addListener(VerifyKey, new StyledTextListener(listener)); | 1548 addListener(VerifyKey, new StyledTextListener(listener)); |
1441 } | 1549 } |
1442 /** | 1550 /** |
1443 * Adds a verify listener. A Verify event is sent by the widget when the widget text | 1551 * Adds a verify listener. A Verify event is sent by the widget when the widget text |
1444 * is about to change. The listener can set the event text and the doit field to | 1552 * is about to change. The listener can set the event text and the doit field to |
1445 * change the text that is set in the widget or to force the widget to ignore the | 1553 * change the text that is set in the widget or to force the widget to ignore the |
1446 * text change. | 1554 * text change. |
1447 * | 1555 * |
1448 * @param verifyListener the listener | 1556 * @param verifyListener the listener |
1449 * @exception DWTException <ul> | 1557 * @exception DWTException <ul> |
1450 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1558 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1457 public void addVerifyListener(VerifyListener verifyListener) { | 1565 public void addVerifyListener(VerifyListener verifyListener) { |
1458 checkWidget(); | 1566 checkWidget(); |
1459 if (verifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1567 if (verifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1460 addListener(DWT.Verify, new TypedListener(verifyListener)); | 1568 addListener(DWT.Verify, new TypedListener(verifyListener)); |
1461 } | 1569 } |
1462 /** | 1570 /** |
1463 * Adds a word movement listener. A movement event is sent when the boundary | 1571 * Adds a word movement listener. A movement event is sent when the boundary |
1464 * of a word is needed. For example, this occurs during word next and word | 1572 * of a word is needed. For example, this occurs during word next and word |
1465 * previous actions. | 1573 * previous actions. |
1466 * | 1574 * |
1467 * @param movementListener the listener | 1575 * @param movementListener the listener |
1468 * @exception DWTException <ul> | 1576 * @exception DWTException <ul> |
1469 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1577 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1470 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1578 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1471 * </ul> | 1579 * </ul> |
1472 * @exception IllegalArgumentException <ul> | 1580 * @exception IllegalArgumentException <ul> |
1473 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 1581 * <li>ERROR_NULL_ARGUMENT when listener is null</li> |
1474 * </ul> | 1582 * </ul> |
1475 * | 1583 * |
1476 * @see MovementEvent | 1584 * @see MovementEvent |
1477 * @see MovementListener | 1585 * @see MovementListener |
1478 * @see #removeWordMovementListener | 1586 * @see #removeWordMovementListener |
1479 * | 1587 * |
1480 * @since 3.3 | 1588 * @since 3.3 |
1481 */ | 1589 */ |
1482 public void addWordMovementListener(MovementListener movementListener) { | 1590 public void addWordMovementListener(MovementListener movementListener) { |
1483 checkWidget(); | 1591 checkWidget(); |
1484 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 1592 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1485 addListener(WordNext, new StyledTextListener(movementListener)); | 1593 addListener(WordNext, new StyledTextListener(movementListener)); |
1486 addListener(WordPrevious, new StyledTextListener(movementListener)); | 1594 addListener(WordPrevious, new StyledTextListener(movementListener)); |
1487 } | 1595 } |
1488 /** | 1596 /** |
1489 * Appends a String to the text at the end of the widget. | 1597 * Appends a string to the text at the end of the widget. |
1490 * | 1598 * |
1491 * @param String the String to be appended | 1599 * @param string the string to be appended |
1492 * @see #replaceTextRange(int,int,String) | 1600 * @see #replaceTextRange(int,int,String) |
1493 * @exception DWTException <ul> | 1601 * @exception DWTException <ul> |
1494 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1602 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1495 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1603 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1496 * </ul> | 1604 * </ul> |
1497 * @exception IllegalArgumentException <ul> | 1605 */ |
1498 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 1606 public void append(String string) { |
1499 * </ul> | 1607 checkWidget(); |
1500 */ | 1608 // DWT extension: allow null for zero length string |
1501 public void append(String String) { | 1609 // if (string is null) { |
1502 checkWidget(); | 1610 // DWT.error(DWT.ERROR_NULL_ARGUMENT); |
1503 if (String is null) { | 1611 // } |
1504 DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
1505 } | |
1506 int lastChar = Math.max(getCharCount(), 0); | 1612 int lastChar = Math.max(getCharCount(), 0); |
1507 replaceTextRange(lastChar, 0, String); | 1613 replaceTextRange(lastChar, 0, string); |
1508 } | 1614 } |
1509 /** | 1615 /** |
1510 * Calculates the scroll bars | 1616 * Calculates the scroll bars |
1511 */ | 1617 */ |
1512 void calculateScrollBars() { | 1618 void calculateScrollBars() { |
1513 ScrollBar horizontalBar = getHorizontalBar(); | 1619 ScrollBar horizontalBar = getHorizontalBar(); |
1514 ScrollBar verticalBar = getVerticalBar(); | 1620 ScrollBar verticalBar = getVerticalBar(); |
1515 setScrollBars(true); | 1621 setScrollBars(true); |
1516 if (verticalBar !is null) { | 1622 if (verticalBar !is null) { |
1517 verticalBar.setIncrement(getVerticalIncrement()); | 1623 verticalBar.setIncrement(getVerticalIncrement()); |
1518 } | 1624 } |
1519 if (horizontalBar !is null) { | 1625 if (horizontalBar !is null) { |
1520 horizontalBar.setIncrement(getHorizontalIncrement()); | 1626 horizontalBar.setIncrement(getHorizontalIncrement()); |
1521 } | 1627 } |
1522 } | 1628 } |
1523 /** | 1629 /** |
1533 int verticalIncrement = getVerticalIncrement(); | 1639 int verticalIncrement = getVerticalIncrement(); |
1534 if (verticalIncrement is 0) { | 1640 if (verticalIncrement is 0) { |
1535 return; | 1641 return; |
1536 } | 1642 } |
1537 topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); | 1643 topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); |
1538 // Set top index to partially visible top line if no line is fully | 1644 // Set top index to partially visible top line if no line is fully |
1539 // visible but at least some of the widget client area is visible. | 1645 // visible but at least some of the widget client area is visible. |
1540 // Fixes bug 15088. | 1646 // Fixes bug 15088. |
1541 if (topIndex > 0) { | 1647 if (topIndex > 0) { |
1542 if (clientAreaHeight > 0) { | 1648 if (clientAreaHeight > 0) { |
1543 int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; | 1649 int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; |
1544 int fullLineTopPixel = topIndex * verticalIncrement; | 1650 int fullLineTopPixel = topIndex * verticalIncrement; |
1545 int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; | 1651 int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; |
1546 // set top index to partially visible line if no line fully fits in | 1652 // set top index to partially visible line if no line fully fits in |
1547 // client area or if space is available but not used (the latter should | 1653 // client area or if space is available but not used (the latter should |
1548 // never happen because we use claimBottomFreeSpace) | 1654 // never happen because we use claimBottomFreeSpace) |
1549 if (fullLineVisibleHeight < verticalIncrement) { | 1655 if (fullLineVisibleHeight < verticalIncrement) { |
1550 topIndex--; | 1656 topIndex--; |
1551 } | 1657 } |
1606 } | 1712 } |
1607 style |= DWT.NO_REDRAW_RESIZE | DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND; | 1713 style |= DWT.NO_REDRAW_RESIZE | DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND; |
1608 return style; | 1714 return style; |
1609 } | 1715 } |
1610 /** | 1716 /** |
1611 * Scrolls down the text to use new space made available by a resize or by | 1717 * Scrolls down the text to use new space made available by a resize or by |
1612 * deleted lines. | 1718 * deleted lines. |
1613 */ | 1719 */ |
1614 void claimBottomFreeSpace() { | 1720 void claimBottomFreeSpace() { |
1615 int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; | 1721 int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; |
1616 if (isFixedLineHeight()) { | 1722 if (isFixedLineHeight()) { |
1630 /** | 1736 /** |
1631 * Scrolls text to the right to use new space made available by a resize. | 1737 * Scrolls text to the right to use new space made available by a resize. |
1632 */ | 1738 */ |
1633 void claimRightFreeSpace() { | 1739 void claimRightFreeSpace() { |
1634 int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin)); | 1740 int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin)); |
1635 if (newHorizontalOffset < horizontalScrollOffset) { | 1741 if (newHorizontalOffset < horizontalScrollOffset) { |
1636 // item is no longer drawn past the right border of the client area | 1742 // item is no longer drawn past the right border of the client area |
1637 // align the right end of the item with the right border of the | 1743 // align the right end of the item with the right border of the |
1638 // client area (window is scrolled right). | 1744 // client area (window is scrolled right). |
1639 scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); | 1745 scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); |
1640 } | 1746 } |
1641 } | 1747 } |
1642 /** | 1748 /** |
1643 * Removes the widget selection. | 1749 * Removes the widget selection. |
1644 * | 1750 * |
1645 * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. | 1751 * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. |
1646 */ | 1752 */ |
1647 void clearSelection(bool sendEvent) { | 1753 void clearSelection(bool sendEvent) { |
1648 int selectionStart = selection.x; | 1754 int selectionStart = selection.x; |
1649 int selectionEnd = selection.y; | 1755 int selectionEnd = selection.y; |
1650 resetSelection(); | 1756 resetSelection(); |
1651 // redraw old selection, if any | 1757 // redraw old selection, if any |
1652 if (selectionEnd - selectionStart > 0) { | 1758 if (selectionEnd - selectionStart > 0) { |
1653 int length = content.getCharCount(); | 1759 int length = content.getCharCount(); |
1654 // called internally to remove selection after text is removed | 1760 // called internally to remove selection after text is removed |
1661 if (sendEvent) { | 1767 if (sendEvent) { |
1662 sendSelectionEvent(); | 1768 sendSelectionEvent(); |
1663 } | 1769 } |
1664 } | 1770 } |
1665 } | 1771 } |
1666 public Point computeSize (int wHint, int hHint, bool changed) { | 1772 public override Point computeSize (int wHint, int hHint, bool changed) { |
1667 checkWidget(); | 1773 checkWidget(); |
1668 int lineCount = (getStyle() & DWT.SINGLE) !is 0 ? 1 : content.getLineCount(); | 1774 int lineCount = (getStyle() & DWT.SINGLE) !is 0 ? 1 : content.getLineCount(); |
1669 int width = 0; | 1775 int width = 0; |
1670 int height = 0; | 1776 int height = 0; |
1671 if (wHint is DWT.DEFAULT || hHint is DWT.DEFAULT) { | 1777 if (wHint is DWT.DEFAULT || hHint is DWT.DEFAULT) { |
1699 /** | 1805 /** |
1700 * Copies the selected text to the <code>DND.CLIPBOARD</code> clipboard. | 1806 * Copies the selected text to the <code>DND.CLIPBOARD</code> clipboard. |
1701 * <p> | 1807 * <p> |
1702 * The text will be put on the clipboard in plain text format and RTF format. | 1808 * The text will be put on the clipboard in plain text format and RTF format. |
1703 * The <code>DND.CLIPBOARD</code> clipboard is used for data that is | 1809 * The <code>DND.CLIPBOARD</code> clipboard is used for data that is |
1704 * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or | 1810 * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or |
1705 * by menu action. | 1811 * by menu action. |
1706 * </p> | 1812 * </p> |
1707 * | 1813 * |
1708 * @exception DWTException <ul> | 1814 * @exception DWTException <ul> |
1709 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1815 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1713 public void copy() { | 1819 public void copy() { |
1714 checkWidget(); | 1820 checkWidget(); |
1715 copy(DND.CLIPBOARD); | 1821 copy(DND.CLIPBOARD); |
1716 } | 1822 } |
1717 /** | 1823 /** |
1718 * Copies the selected text to the specified clipboard. The text will be put in the | 1824 * Copies the selected text to the specified clipboard. The text will be put in the |
1719 * clipboard in plain text format and RTF format. | 1825 * clipboard in plain text format and RTF format. |
1720 * <p> | 1826 * <p> |
1721 * The clipboardType is one of the clipboard constants defined in class | 1827 * The clipboardType is one of the clipboard constants defined in class |
1722 * <code>DND</code>. The <code>DND.CLIPBOARD</code> clipboard is | 1828 * <code>DND</code>. The <code>DND.CLIPBOARD</code> clipboard is |
1723 * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) | 1829 * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) |
1724 * or by menu action. The <code>DND.SELECTION_CLIPBOARD</code> | 1830 * or by menu action. The <code>DND.SELECTION_CLIPBOARD</code> |
1725 * clipboard is used for data that is transferred by selecting text and pasting | 1831 * clipboard is used for data that is transferred by selecting text and pasting |
1726 * with the middle mouse button. | 1832 * with the middle mouse button. |
1727 * </p> | 1833 * </p> |
1728 * | 1834 * |
1729 * @param clipboardType indicates the type of clipboard | 1835 * @param clipboardType indicates the type of clipboard |
1730 * | 1836 * |
1731 * @exception DWTException <ul> | 1837 * @exception DWTException <ul> |
1732 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1838 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1733 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1839 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1734 * </ul> | 1840 * </ul> |
1735 * | 1841 * |
1736 * @since 3.1 | 1842 * @since 3.1 |
1737 */ | 1843 */ |
1738 public void copy(int clipboardType) { | 1844 public void copy(int clipboardType) { |
1739 checkWidget(); | 1845 checkWidget(); |
1740 if (clipboardType !is DND.CLIPBOARD && clipboardType !is DND.SELECTION_CLIPBOARD) return; | 1846 if (clipboardType !is DND.CLIPBOARD && clipboardType !is DND.SELECTION_CLIPBOARD) return; |
1741 int length = selection.y - selection.x; | 1847 int length = selection.y - selection.x; |
1742 if (length > 0) { | 1848 if (length > 0) { |
1743 try { | 1849 try { |
1744 setClipboardContent(selection.x, length, clipboardType); | 1850 setClipboardContent(selection.x, length, clipboardType); |
1745 } catch (DWTError error) { | 1851 } catch (DWTError error) { |
1746 // Copy to clipboard failed. This happens when another application | 1852 // Copy to clipboard failed. This happens when another application |
1747 // is accessing the clipboard while we copy. Ignore the error. | 1853 // is accessing the clipboard while we copy. Ignore the error. |
1748 // Fixes 1GDQAVN | 1854 // Fixes 1GDQAVN |
1749 // Rethrow all other errors. Fixes bug 17578. | 1855 // Rethrow all other errors. Fixes bug 17578. |
1750 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { | 1856 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { |
1751 throw error; | 1857 throw error; |
1753 } | 1859 } |
1754 } | 1860 } |
1755 } | 1861 } |
1756 /** | 1862 /** |
1757 * Returns the alignment of the widget. | 1863 * Returns the alignment of the widget. |
1758 * | 1864 * |
1759 * @return the alignment | 1865 * @return the alignment |
1760 * | 1866 * |
1761 * @exception DWTException <ul> | 1867 * @exception DWTException <ul> |
1762 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 1868 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1763 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 1869 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1764 * </ul> | 1870 * </ul> |
1765 * | 1871 * |
1766 * @see #getLineAlignment(int) | 1872 * @see #getLineAlignment(int) |
1767 * | 1873 * |
1768 * @since 3.2 | 1874 * @since 3.2 |
1769 */ | 1875 */ |
1770 public int getAlignment() { | 1876 public int getAlignment() { |
1771 checkWidget(); | 1877 checkWidget(); |
1772 return alignment; | 1878 return alignment; |
1800 availableHeight += renderer.getLineHeight(lineIndex++); | 1906 availableHeight += renderer.getLineHeight(lineIndex++); |
1801 } | 1907 } |
1802 return Math.min(height, availableHeight); | 1908 return Math.min(height, availableHeight); |
1803 } | 1909 } |
1804 /** | 1910 /** |
1805 * Returns a String that uses only the line delimiter specified by the | 1911 * Returns a string that uses only the line delimiter specified by the |
1806 * StyledTextContent implementation. | 1912 * StyledTextContent implementation. |
1807 * <p> | 1913 * <p> |
1808 * Returns only the first line if the widget has the DWT.SINGLE style. | 1914 * Returns only the first line if the widget has the DWT.SINGLE style. |
1809 * </p> | 1915 * </p> |
1810 * | 1916 * |
1811 * @param text the text that may have line delimiters that don't | 1917 * @param text the text that may have line delimiters that don't |
1812 * match the model line delimiter. Possible line delimiters | 1918 * match the model line delimiter. Possible line delimiters |
1813 * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") | 1919 * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") |
1814 * @return the converted text that only uses the line delimiter | 1920 * @return the converted text that only uses the line delimiter |
1815 * specified by the model. Returns only the first line if the widget | 1921 * specified by the model. Returns only the first line if the widget |
1816 * has the DWT.SINGLE style. | 1922 * has the DWT.SINGLE style. |
1817 */ | 1923 */ |
1818 String getModelDelimitedText(String text) { | 1924 String getModelDelimitedText(String text) { |
1819 int length = text.length(); | 1925 int length = text.length; |
1820 if (length is 0) { | 1926 if (length is 0) { |
1821 return text; | 1927 return text; |
1822 } | 1928 } |
1823 int crIndex = 0; | 1929 int crIndex = 0; |
1824 int lfIndex = 0; | 1930 int lfIndex = 0; |
1825 int i = 0; | 1931 int i = 0; |
1826 StringBuffer convertedText = new StringBuffer(length); | 1932 StringBuffer convertedText = new StringBuffer(length); |
1827 String delimiter = getLineDelimiter(); | 1933 String delimiter = getLineDelimiter(); |
1828 while (i < length) { | 1934 while (i < length) { |
1829 if (crIndex !is -1) { | 1935 if (crIndex !is -1) { |
1830 crIndex = text.indexOf(DWT.CR, i); | 1936 crIndex = text.indexOf (DWT.CR, i); |
1831 } | 1937 } |
1832 if (lfIndex !is -1) { | 1938 if (lfIndex !is -1) { |
1833 lfIndex = text.indexOf(DWT.LF, i); | 1939 lfIndex = text.indexOf (DWT.LF, i); |
1834 } | 1940 } |
1835 if (lfIndex is -1 && crIndex is -1) { // no more line breaks? | 1941 if (lfIndex is -1 && crIndex is -1) { // no more line breaks? |
1836 break; | 1942 break; |
1837 } else if ((crIndex < lfIndex && crIndex !is -1) || lfIndex is -1) { | 1943 } else if ((crIndex < lfIndex && crIndex !is -1) || lfIndex is -1) { |
1838 convertedText.append(text.substring(i, crIndex)); | 1944 convertedText.append(text.substring(i, crIndex)); |
1848 if (isSingleLine()) { | 1954 if (isSingleLine()) { |
1849 break; | 1955 break; |
1850 } | 1956 } |
1851 convertedText.append(delimiter); | 1957 convertedText.append(delimiter); |
1852 } | 1958 } |
1853 // copy remaining text if any and if not in single line mode or no | 1959 // copy remaining text if any and if not in single line mode or no |
1854 // text copied thus far (because there only is one line) | 1960 // text copied thus far (because there only is one line) |
1855 if (i < length && (!isSingleLine() || convertedText.length() is 0)) { | 1961 if (i < length && (!isSingleLine() || convertedText.length() is 0)) { |
1856 convertedText.append(text.substring(i)); | 1962 convertedText.append(text.substring(i)); |
1857 } | 1963 } |
1858 return convertedText.toString(); | 1964 return convertedText.toString(); |
1875 * Creates default key bindings. | 1981 * Creates default key bindings. |
1876 */ | 1982 */ |
1877 void createKeyBindings() { | 1983 void createKeyBindings() { |
1878 int nextKey = isMirrored() ? DWT.ARROW_LEFT : DWT.ARROW_RIGHT; | 1984 int nextKey = isMirrored() ? DWT.ARROW_LEFT : DWT.ARROW_RIGHT; |
1879 int previousKey = isMirrored() ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; | 1985 int previousKey = isMirrored() ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; |
1880 | 1986 |
1881 // Navigation | 1987 // Navigation |
1882 setKeyBinding(DWT.ARROW_UP, ST.LINE_UP); | 1988 setKeyBinding(DWT.ARROW_UP, ST.LINE_UP); |
1883 setKeyBinding(DWT.ARROW_DOWN, ST.LINE_DOWN); | 1989 setKeyBinding(DWT.ARROW_DOWN, ST.LINE_DOWN); |
1884 if (IS_CARBON) { | 1990 if (IS_CARBON) { |
1885 setKeyBinding(previousKey | DWT.MOD1, ST.LINE_START); | 1991 setKeyBinding(previousKey | DWT.MOD1, ST.LINE_START); |
1886 setKeyBinding(nextKey | DWT.MOD1, ST.LINE_END); | 1992 setKeyBinding(nextKey | DWT.MOD1, ST.LINE_END); |
1887 setKeyBinding(DWT.HOME, ST.TEXT_START); | 1993 setKeyBinding(DWT.HOME, ST.TEXT_START); |
1902 setKeyBinding(DWT.PAGE_DOWN, ST.PAGE_DOWN); | 2008 setKeyBinding(DWT.PAGE_DOWN, ST.PAGE_DOWN); |
1903 setKeyBinding(DWT.PAGE_UP | DWT.MOD1, ST.WINDOW_START); | 2009 setKeyBinding(DWT.PAGE_UP | DWT.MOD1, ST.WINDOW_START); |
1904 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1, ST.WINDOW_END); | 2010 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1, ST.WINDOW_END); |
1905 setKeyBinding(nextKey, ST.COLUMN_NEXT); | 2011 setKeyBinding(nextKey, ST.COLUMN_NEXT); |
1906 setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); | 2012 setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); |
1907 | 2013 |
1908 // Selection | 2014 // Selection |
1909 setKeyBinding(DWT.ARROW_UP | DWT.MOD2, ST.SELECT_LINE_UP); | 2015 setKeyBinding(DWT.ARROW_UP | DWT.MOD2, ST.SELECT_LINE_UP); |
1910 setKeyBinding(DWT.ARROW_DOWN | DWT.MOD2, ST.SELECT_LINE_DOWN); | 2016 setKeyBinding(DWT.ARROW_DOWN | DWT.MOD2, ST.SELECT_LINE_DOWN); |
1911 if (IS_CARBON) { | 2017 if (IS_CARBON) { |
1912 setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_START); | 2018 setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_START); |
1913 setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_END); | 2019 setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_END); |
1914 setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_TEXT_START); | 2020 setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_TEXT_START); |
1915 setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_TEXT_END); | 2021 setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_TEXT_END); |
1916 setKeyBinding(DWT.ARROW_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); | 2022 setKeyBinding(DWT.ARROW_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); |
1917 setKeyBinding(DWT.ARROW_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); | 2023 setKeyBinding(DWT.ARROW_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); |
1918 setKeyBinding(nextKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_NEXT); | 2024 setKeyBinding(nextKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_NEXT); |
1919 setKeyBinding(previousKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_PREVIOUS); | 2025 setKeyBinding(previousKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_PREVIOUS); |
1920 } else { | 2026 } else { |
1921 setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_LINE_START); | 2027 setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_LINE_START); |
1922 setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_LINE_END); | 2028 setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_LINE_END); |
1923 setKeyBinding(DWT.HOME | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); | 2029 setKeyBinding(DWT.HOME | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); |
1924 setKeyBinding(DWT.END | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); | 2030 setKeyBinding(DWT.END | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); |
1925 setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_NEXT); | 2031 setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_NEXT); |
1926 setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_PREVIOUS); | 2032 setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_PREVIOUS); |
1927 } | 2033 } |
1928 setKeyBinding(DWT.PAGE_UP | DWT.MOD2, ST.SELECT_PAGE_UP); | 2034 setKeyBinding(DWT.PAGE_UP | DWT.MOD2, ST.SELECT_PAGE_UP); |
1929 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD2, ST.SELECT_PAGE_DOWN); | 2035 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD2, ST.SELECT_PAGE_DOWN); |
1930 setKeyBinding(DWT.PAGE_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_START); | 2036 setKeyBinding(DWT.PAGE_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_START); |
1931 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_END); | 2037 setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_END); |
1932 setKeyBinding(nextKey | DWT.MOD2, ST.SELECT_COLUMN_NEXT); | 2038 setKeyBinding(nextKey | DWT.MOD2, ST.SELECT_COLUMN_NEXT); |
1933 setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); | 2039 setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); |
1934 | 2040 |
1935 // Modification | 2041 // Modification |
1936 // Cut, Copy, Paste | 2042 // Cut, Copy, Paste |
1937 setKeyBinding('X' | DWT.MOD1, ST.CUT); | 2043 setKeyBinding('X' | DWT.MOD1, ST.CUT); |
1938 setKeyBinding('C' | DWT.MOD1, ST.COPY); | 2044 setKeyBinding('C' | DWT.MOD1, ST.COPY); |
1939 setKeyBinding('V' | DWT.MOD1, ST.PASTE); | 2045 setKeyBinding('V' | DWT.MOD1, ST.PASTE); |
1950 setKeyBinding(DWT.BS | DWT.MOD2, ST.DELETE_PREVIOUS); | 2056 setKeyBinding(DWT.BS | DWT.MOD2, ST.DELETE_PREVIOUS); |
1951 setKeyBinding(DWT.BS, ST.DELETE_PREVIOUS); | 2057 setKeyBinding(DWT.BS, ST.DELETE_PREVIOUS); |
1952 setKeyBinding(DWT.DEL, ST.DELETE_NEXT); | 2058 setKeyBinding(DWT.DEL, ST.DELETE_NEXT); |
1953 setKeyBinding(DWT.BS | DWT.MOD1, ST.DELETE_WORD_PREVIOUS); | 2059 setKeyBinding(DWT.BS | DWT.MOD1, ST.DELETE_WORD_PREVIOUS); |
1954 setKeyBinding(DWT.DEL | DWT.MOD1, ST.DELETE_WORD_NEXT); | 2060 setKeyBinding(DWT.DEL | DWT.MOD1, ST.DELETE_WORD_NEXT); |
1955 | 2061 |
1956 // Miscellaneous | 2062 // Miscellaneous |
1957 setKeyBinding(DWT.INSERT, ST.TOGGLE_OVERWRITE); | 2063 setKeyBinding(DWT.INSERT, ST.TOGGLE_OVERWRITE); |
1958 } | 2064 } |
1959 /** | 2065 /** |
1960 * Create the bitmaps to use for the caret in bidi mode. This | 2066 * Create the bitmaps to use for the caret in bidi mode. This |
1963 */ | 2069 */ |
1964 void createCaretBitmaps() { | 2070 void createCaretBitmaps() { |
1965 int caretWidth = BIDI_CARET_WIDTH; | 2071 int caretWidth = BIDI_CARET_WIDTH; |
1966 Display display = getDisplay(); | 2072 Display display = getDisplay(); |
1967 if (leftCaretBitmap !is null) { | 2073 if (leftCaretBitmap !is null) { |
1968 if (defaultCaret !is null && leftCaretBitmap.opEquals(defaultCaret.getImage())) { | 2074 if (defaultCaret !is null && leftCaretBitmap==/*eq*/defaultCaret.getImage()) { |
1969 defaultCaret.setImage(null); | 2075 defaultCaret.setImage(null); |
1970 } | 2076 } |
1971 leftCaretBitmap.dispose(); | 2077 leftCaretBitmap.dispose(); |
1972 } | 2078 } |
1973 int lineHeight = renderer.getLineHeight(); | 2079 int lineHeight = renderer.getLineHeight(); |
1974 leftCaretBitmap = new Image(display, caretWidth, lineHeight); | 2080 leftCaretBitmap = new Image(display, caretWidth, lineHeight); |
1975 GC gc = new GC (leftCaretBitmap); | 2081 GC gc = new GC (leftCaretBitmap); |
1976 gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); | 2082 gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); |
1977 gc.fillRectangle(0, 0, caretWidth, lineHeight); | 2083 gc.fillRectangle(0, 0, caretWidth, lineHeight); |
1978 gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); | 2084 gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); |
1979 gc.drawLine(0,0,0,lineHeight); | 2085 gc.drawLine(0,0,0,lineHeight); |
1980 gc.drawLine(0,0,caretWidth-1,0); | 2086 gc.drawLine(0,0,caretWidth-1,0); |
1981 gc.drawLine(0,1,1,1); | 2087 gc.drawLine(0,1,1,1); |
1982 gc.dispose(); | 2088 gc.dispose(); |
1983 | 2089 |
1984 if (rightCaretBitmap !is null) { | 2090 if (rightCaretBitmap !is null) { |
1985 if (defaultCaret !is null && rightCaretBitmap.opEquals(defaultCaret.getImage())) { | 2091 if (defaultCaret !is null && rightCaretBitmap==/*eq*/defaultCaret.getImage()) { |
1986 defaultCaret.setImage(null); | 2092 defaultCaret.setImage(null); |
1987 } | 2093 } |
1988 rightCaretBitmap.dispose(); | 2094 rightCaretBitmap.dispose(); |
1989 } | 2095 } |
1990 rightCaretBitmap = new Image(display, caretWidth, lineHeight); | 2096 rightCaretBitmap = new Image(display, caretWidth, lineHeight); |
1991 gc = new GC (rightCaretBitmap); | 2097 gc = new GC (rightCaretBitmap); |
1992 gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); | 2098 gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); |
1993 gc.fillRectangle(0, 0, caretWidth, lineHeight); | 2099 gc.fillRectangle(0, 0, caretWidth, lineHeight); |
1994 gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); | 2100 gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); |
1995 gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); | 2101 gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); |
1996 gc.drawLine(0,0,caretWidth-1,0); | 2102 gc.drawLine(0,0,caretWidth-1,0); |
1997 gc.drawLine(caretWidth-1,1,1,1); | 2103 gc.drawLine(caretWidth-1,1,1,1); |
1998 gc.dispose(); | 2104 gc.dispose(); |
1999 } | 2105 } |
2000 /** | 2106 /** |
2001 * Moves the selected text to the clipboard. The text will be put in the | 2107 * Moves the selected text to the clipboard. The text will be put in the |
2002 * clipboard in plain text format and RTF format. | 2108 * clipboard in plain text format and RTF format. |
2003 * | 2109 * |
2004 * @exception DWTException <ul> | 2110 * @exception DWTException <ul> |
2005 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 2111 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
2006 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 2112 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
2011 int length = selection.y - selection.x; | 2117 int length = selection.y - selection.x; |
2012 if (length > 0) { | 2118 if (length > 0) { |
2013 try { | 2119 try { |
2014 setClipboardContent(selection.x, length, DND.CLIPBOARD); | 2120 setClipboardContent(selection.x, length, DND.CLIPBOARD); |
2015 } catch (DWTError error) { | 2121 } catch (DWTError error) { |
2016 // Copy to clipboard failed. This happens when another application | 2122 // Copy to clipboard failed. This happens when another application |
2017 // is accessing the clipboard while we copy. Ignore the error. | 2123 // is accessing the clipboard while we copy. Ignore the error. |
2018 // Fixes 1GDQAVN | 2124 // Fixes 1GDQAVN |
2019 // Rethrow all other errors. Fixes bug 17578. | 2125 // Rethrow all other errors. Fixes bug 17578. |
2020 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { | 2126 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { |
2021 throw error; | 2127 throw error; |
2025 return; | 2131 return; |
2026 } | 2132 } |
2027 doDelete(); | 2133 doDelete(); |
2028 } | 2134 } |
2029 } | 2135 } |
2030 /** | 2136 /** |
2031 * A mouse move event has occurred. See if we should start autoscrolling. If | 2137 * A mouse move event has occurred. See if we should start autoscrolling. If |
2032 * the move position is outside of the client area, initiate autoscrolling. | 2138 * the move position is outside of the client area, initiate autoscrolling. |
2033 * Otherwise, we've moved back into the widget so end autoscrolling. | 2139 * Otherwise, we've moved back into the widget so end autoscrolling. |
2034 */ | 2140 */ |
2035 void doAutoScroll(Event event) { | 2141 void doAutoScroll(Event event) { |
2036 if (event.y > clientAreaHeight) { | 2142 if (event.y > clientAreaHeight) { |
2037 doAutoScroll(DWT.DOWN, event.y - clientAreaHeight); | 2143 doAutoScroll(DWT.DOWN, event.y - clientAreaHeight); |
2043 doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - leftMargin - rightMargin)); | 2149 doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - leftMargin - rightMargin)); |
2044 } else { | 2150 } else { |
2045 endAutoScroll(); | 2151 endAutoScroll(); |
2046 } | 2152 } |
2047 } | 2153 } |
2048 /** | 2154 /** |
2049 * Initiates autoscrolling. | 2155 * Initiates autoscrolling. |
2050 * | 2156 * |
2051 * @param direction DWT.UP, DWT.DOWN, DWT.COLUMN_NEXT, DWT.COLUMN_PREVIOUS | 2157 * @param direction DWT.UP, DWT.DOWN, DWT.COLUMN_NEXT, DWT.COLUMN_PREVIOUS |
2052 */ | 2158 */ |
2053 void doAutoScroll(int direction, int distance) { | 2159 void doAutoScroll(int direction, int distance) { |
2054 autoScrollDistance = distance; | 2160 autoScrollDistance = distance; |
2055 // If we're already autoscrolling in the given direction do nothing | 2161 // If we're already autoscrolling in the given direction do nothing |
2056 if (autoScrollDirection is direction) { | 2162 if (autoScrollDirection is direction) { |
2057 return; | 2163 return; |
2058 } | 2164 } |
2059 | 2165 |
2060 Runnable timer = null; | 2166 Runnable timer = null; |
2061 final Display display = getDisplay(); | 2167 final Display disp = getDisplay(); |
2062 // Set a timer that will simulate the user pressing and holding | 2168 // Set a timer that will simulate the user pressing and holding |
2063 // down a cursor key (i.e., arrowUp, arrowDown). | 2169 // down a cursor key (i.e., arrowUp, arrowDown). |
2064 if (direction is DWT.UP) { | 2170 if (direction is DWT.UP) { |
2065 timer = new Runnable() { | 2171 timer = new class(disp) Runnable { |
2172 Display display; | |
2173 this( Display d ){ this.display = d; } | |
2066 public void run() { | 2174 public void run() { |
2067 if (autoScrollDirection is DWT.UP) { | 2175 if (autoScrollDirection is DWT.UP) { |
2068 doSelectionPageUp(autoScrollDistance); | 2176 doSelectionPageUp(autoScrollDistance); |
2069 display.timerExec(V_SCROLL_RATE, this); | 2177 display.timerExec(V_SCROLL_RATE, this); |
2070 } | 2178 } |
2071 } | 2179 } |
2072 }; | 2180 }; |
2073 autoScrollDirection = direction; | 2181 autoScrollDirection = direction; |
2074 display.timerExec(V_SCROLL_RATE, timer); | 2182 display.timerExec(V_SCROLL_RATE, timer); |
2075 } else if (direction is DWT.DOWN) { | 2183 } else if (direction is DWT.DOWN) { |
2076 timer = new Runnable() { | 2184 timer = new class(disp) Runnable { |
2185 Display display; | |
2186 this( Display d ){ this.display = d; } | |
2077 public void run() { | 2187 public void run() { |
2078 if (autoScrollDirection is DWT.DOWN) { | 2188 if (autoScrollDirection is DWT.DOWN) { |
2079 doSelectionPageDown(autoScrollDistance); | 2189 doSelectionPageDown(autoScrollDistance); |
2080 display.timerExec(V_SCROLL_RATE, this); | 2190 display.timerExec(V_SCROLL_RATE, this); |
2081 } | 2191 } |
2082 } | 2192 } |
2083 }; | 2193 }; |
2084 autoScrollDirection = direction; | 2194 autoScrollDirection = direction; |
2085 display.timerExec(V_SCROLL_RATE, timer); | 2195 display.timerExec(V_SCROLL_RATE, timer); |
2086 } else if (direction is ST.COLUMN_NEXT) { | 2196 } else if (direction is ST.COLUMN_NEXT) { |
2087 timer = new Runnable() { | 2197 timer = new class(disp) Runnable { |
2198 Display display; | |
2199 this( Display d ){ this.display = d; } | |
2088 public void run() { | 2200 public void run() { |
2089 if (autoScrollDirection is ST.COLUMN_NEXT) { | 2201 if (autoScrollDirection is ST.COLUMN_NEXT) { |
2090 doVisualNext(); | 2202 doVisualNext(); |
2091 setMouseWordSelectionAnchor(); | 2203 setMouseWordSelectionAnchor(); |
2092 doMouseSelection(); | 2204 doMouseSelection(); |
2095 } | 2207 } |
2096 }; | 2208 }; |
2097 autoScrollDirection = direction; | 2209 autoScrollDirection = direction; |
2098 display.timerExec(H_SCROLL_RATE, timer); | 2210 display.timerExec(H_SCROLL_RATE, timer); |
2099 } else if (direction is ST.COLUMN_PREVIOUS) { | 2211 } else if (direction is ST.COLUMN_PREVIOUS) { |
2100 timer = new Runnable() { | 2212 timer = new class(disp) Runnable { |
2213 Display display; | |
2214 this( Display d ){ this.display = d; } | |
2101 public void run() { | 2215 public void run() { |
2102 if (autoScrollDirection is ST.COLUMN_PREVIOUS) { | 2216 if (autoScrollDirection is ST.COLUMN_PREVIOUS) { |
2103 doVisualPrevious(); | 2217 doVisualPrevious(); |
2104 setMouseWordSelectionAnchor(); | 2218 setMouseWordSelectionAnchor(); |
2105 doMouseSelection(); | 2219 doMouseSelection(); |
2124 sendKeyEvent(event); | 2238 sendKeyEvent(event); |
2125 } else if (caretOffset > 0) { | 2239 } else if (caretOffset > 0) { |
2126 int lineIndex = content.getLineAtOffset(caretOffset); | 2240 int lineIndex = content.getLineAtOffset(caretOffset); |
2127 int lineOffset = content.getOffsetAtLine(lineIndex); | 2241 int lineOffset = content.getOffsetAtLine(lineIndex); |
2128 if (caretOffset is lineOffset) { | 2242 if (caretOffset is lineOffset) { |
2243 // DWT: on line start, delete line break | |
2129 lineOffset = content.getOffsetAtLine(lineIndex - 1); | 2244 lineOffset = content.getOffsetAtLine(lineIndex - 1); |
2130 event.start = lineOffset + content.getLine(lineIndex - 1).length(); | 2245 event.start = lineOffset + content.getLine(lineIndex - 1).length; |
2131 event.end = caretOffset; | 2246 event.end = caretOffset; |
2132 } else { | 2247 } else { |
2133 TextLayout layout = renderer.getTextLayout(lineIndex); | 2248 TextLayout layout = renderer.getTextLayout(lineIndex); |
2134 int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CHAR); | 2249 int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CLUSTER); |
2135 renderer.disposeTextLayout(layout); | 2250 renderer.disposeTextLayout(layout); |
2136 event.start = start + lineOffset; | 2251 event.start = start + lineOffset; |
2137 event.end = caretOffset; | 2252 event.end = caretOffset; |
2138 } | 2253 } |
2139 sendKeyEvent(event); | 2254 sendKeyEvent(event); |
2140 } | 2255 } |
2141 } | 2256 } |
2142 /** | 2257 /** |
2143 * Replaces the selection with the character or insert the character at the | 2258 * Replaces the selection with the character or insert the character at the |
2144 * current caret position if no selection exists. | 2259 * current caret position if no selection exists. |
2145 * <p> | 2260 * <p> |
2146 * If a carriage return was typed replace it with the line break character | 2261 * If a carriage return was typed replace it with the line break character |
2147 * used by the widget on this platform. | 2262 * used by the widget on this platform. |
2148 * </p> | 2263 * </p> |
2149 * | 2264 * |
2150 * @param key the character typed by the user | 2265 * @param key the character typed by the user |
2151 */ | 2266 */ |
2152 void doContent(char key) { | 2267 void doContent(dchar key) { |
2153 Event event = new Event(); | 2268 Event event = new Event(); |
2154 event.start = selection.x; | 2269 event.start = selection.x; |
2155 event.end = selection.y; | 2270 event.end = selection.y; |
2156 // replace a CR line break with the widget line break | 2271 // replace a CR line break with the widget line break |
2157 // CR does not make sense on Windows since most (all?) applications | 2272 // CR does not make sense on Windows since most (all?) applications |
2160 if (!isSingleLine()) { | 2275 if (!isSingleLine()) { |
2161 event.text = getLineDelimiter(); | 2276 event.text = getLineDelimiter(); |
2162 } | 2277 } |
2163 } else if (selection.x is selection.y && overwrite && key !is TAB) { | 2278 } else if (selection.x is selection.y && overwrite && key !is TAB) { |
2164 // no selection and overwrite mode is on and the typed key is not a | 2279 // no selection and overwrite mode is on and the typed key is not a |
2165 // tab character (tabs are always inserted without overwriting)? | 2280 // tab character (tabs are always inserted without overwriting)? |
2166 int lineIndex = content.getLineAtOffset(event.end); | 2281 int lineIndex = content.getLineAtOffset(event.end); |
2167 int lineOffset = content.getOffsetAtLine(lineIndex); | 2282 int lineOffset = content.getOffsetAtLine(lineIndex); |
2168 String line = content.getLine(lineIndex); | 2283 String line = content.getLine(lineIndex); |
2169 // replace character at caret offset if the caret is not at the | 2284 // replace character at caret offset if the caret is not at the |
2170 // end of the line | 2285 // end of the line |
2171 if (event.end < lineOffset + line.length()) { | 2286 if (event.end < lineOffset + line.length) { |
2172 event.end++; | 2287 event.end+=dcharToString( key ).length; |
2173 } | 2288 } |
2174 event.text = new String(new char[] {key}); | 2289 event.text = dcharToString( key ); |
2175 } else { | 2290 } else { |
2176 event.text = new String(new char[] {key}); | 2291 event.text = dcharToString( key ); |
2177 } | 2292 } |
2178 if (event.text !is null) { | 2293 if (event.text !is null) { |
2179 if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { | 2294 if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { |
2180 return; | 2295 return; |
2181 } | 2296 } |
2184 } | 2299 } |
2185 /** | 2300 /** |
2186 * Moves the caret after the last character of the widget content. | 2301 * Moves the caret after the last character of the widget content. |
2187 */ | 2302 */ |
2188 void doContentEnd() { | 2303 void doContentEnd() { |
2189 // place caret at end of first line if receiver is in single | 2304 // place caret at end of first line if receiver is in single |
2190 // line mode. fixes 4820. | 2305 // line mode. fixes 4820. |
2191 if (isSingleLine()) { | 2306 if (isSingleLine()) { |
2192 doLineEnd(); | 2307 doLineEnd(); |
2193 } else { | 2308 } else { |
2194 int length = content.getCharCount(); | 2309 int length = content.getCharCount(); |
2195 if (caretOffset < length) { | 2310 if (caretOffset < length) { |
2196 caretOffset = length; | 2311 caretOffset = length; |
2197 showCaret(); | 2312 showCaret(); |
2198 } | 2313 } |
2199 } | 2314 } |
2207 showCaret(); | 2322 showCaret(); |
2208 } | 2323 } |
2209 } | 2324 } |
2210 /** | 2325 /** |
2211 * Moves the caret to the start of the selection if a selection exists. | 2326 * Moves the caret to the start of the selection if a selection exists. |
2212 * Otherwise, if no selection exists move the cursor according to the | 2327 * Otherwise, if no selection exists move the cursor according to the |
2213 * cursor selection rules. | 2328 * cursor selection rules. |
2214 * | 2329 * |
2215 * @see #doSelectionCursorPrevious | 2330 * @see #doSelectionCursorPrevious |
2216 */ | 2331 */ |
2217 void doCursorPrevious() { | 2332 void doCursorPrevious() { |
2223 doSelectionCursorPrevious(); | 2338 doSelectionCursorPrevious(); |
2224 } | 2339 } |
2225 } | 2340 } |
2226 /** | 2341 /** |
2227 * Moves the caret to the end of the selection if a selection exists. | 2342 * Moves the caret to the end of the selection if a selection exists. |
2228 * Otherwise, if no selection exists move the cursor according to the | 2343 * Otherwise, if no selection exists move the cursor according to the |
2229 * cursor selection rules. | 2344 * cursor selection rules. |
2230 * | 2345 * |
2231 * @see #doSelectionCursorNext | 2346 * @see #doSelectionCursorNext |
2232 */ | 2347 */ |
2233 void doCursorNext() { | 2348 void doCursorNext() { |
2250 event.end = selection.y; | 2365 event.end = selection.y; |
2251 sendKeyEvent(event); | 2366 sendKeyEvent(event); |
2252 } else if (caretOffset < content.getCharCount()) { | 2367 } else if (caretOffset < content.getCharCount()) { |
2253 int line = content.getLineAtOffset(caretOffset); | 2368 int line = content.getLineAtOffset(caretOffset); |
2254 int lineOffset = content.getOffsetAtLine(line); | 2369 int lineOffset = content.getOffsetAtLine(line); |
2255 int lineLength = content.getLine(line).length(); | 2370 int lineLength = content.getLine(line).length; |
2256 if (caretOffset is lineOffset + lineLength) { | 2371 if (caretOffset is lineOffset + lineLength) { |
2257 event.start = caretOffset; | 2372 event.start = caretOffset; |
2258 event.end = content.getOffsetAtLine(line + 1); | 2373 event.end = content.getOffsetAtLine(line + 1); |
2259 } else { | 2374 } else { |
2260 event.start = caretOffset; | 2375 event.start = caretOffset; |
2266 /** | 2381 /** |
2267 * Deletes the next word. | 2382 * Deletes the next word. |
2268 */ | 2383 */ |
2269 void doDeleteWordNext() { | 2384 void doDeleteWordNext() { |
2270 if (selection.x !is selection.y) { | 2385 if (selection.x !is selection.y) { |
2271 // if a selection exists, treat the as if | 2386 // if a selection exists, treat the as if |
2272 // only the delete key was pressed | 2387 // only the delete key was pressed |
2273 doDelete(); | 2388 doDelete(); |
2274 } else { | 2389 } else { |
2275 Event event = new Event(); | 2390 Event event = new Event(); |
2276 event.text = ""; | 2391 event.text = ""; |
2282 /** | 2397 /** |
2283 * Deletes the previous word. | 2398 * Deletes the previous word. |
2284 */ | 2399 */ |
2285 void doDeleteWordPrevious() { | 2400 void doDeleteWordPrevious() { |
2286 if (selection.x !is selection.y) { | 2401 if (selection.x !is selection.y) { |
2287 // if a selection exists, treat as if | 2402 // if a selection exists, treat as if |
2288 // only the backspace key was pressed | 2403 // only the backspace key was pressed |
2289 doBackspace(); | 2404 doBackspace(); |
2290 } else { | 2405 } else { |
2291 Event event = new Event(); | 2406 Event event = new Event(); |
2292 event.text = ""; | 2407 event.text = ""; |
2294 event.end = caretOffset; | 2409 event.end = caretOffset; |
2295 sendKeyEvent(event); | 2410 sendKeyEvent(event); |
2296 } | 2411 } |
2297 } | 2412 } |
2298 /** | 2413 /** |
2299 * Moves the caret one line down and to the same character offset relative | 2414 * Moves the caret one line down and to the same character offset relative |
2300 * to the beginning of the line. Move the caret to the end of the new line | 2415 * to the beginning of the line. Move the caret to the end of the new line |
2301 * if the new line is shorter than the character offset. | 2416 * if the new line is shorter than the character offset. |
2302 */ | 2417 */ |
2303 void doLineDown(bool select) { | 2418 void doLineDown(bool select) { |
2304 int caretLine = getCaretLine(); | 2419 int caretLine = getCaretLine(); |
2305 int lineCount = content.getLineCount(); | 2420 int lineCount = content.getLineCount(); |
2328 caretOffset = getOffsetAtPoint(columnX, y, caretLine); | 2443 caretOffset = getOffsetAtPoint(columnX, y, caretLine); |
2329 } | 2444 } |
2330 int oldColumnX = columnX; | 2445 int oldColumnX = columnX; |
2331 int oldHScrollOffset = horizontalScrollOffset; | 2446 int oldHScrollOffset = horizontalScrollOffset; |
2332 if (select) { | 2447 if (select) { |
2333 setMouseWordSelectionAnchor(); | 2448 setMouseWordSelectionAnchor(); |
2334 // select first and then scroll to reduce flash when key | 2449 // select first and then scroll to reduce flash when key |
2335 // repeat scrolls lots of lines | 2450 // repeat scrolls lots of lines |
2336 doSelection(ST.COLUMN_NEXT); | 2451 doSelection(ST.COLUMN_NEXT); |
2337 } | 2452 } |
2338 showCaret(); | 2453 showCaret(); |
2339 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; | 2454 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; |
2342 /** | 2457 /** |
2343 * Moves the caret to the end of the line. | 2458 * Moves the caret to the end of the line. |
2344 */ | 2459 */ |
2345 void doLineEnd() { | 2460 void doLineEnd() { |
2346 int caretLine = getCaretLine(); | 2461 int caretLine = getCaretLine(); |
2347 int lineOffset = content.getOffsetAtLine(caretLine); | 2462 int lineOffset = content.getOffsetAtLine(caretLine); |
2348 int lineEndOffset; | 2463 int lineEndOffset; |
2349 if (wordWrap) { | 2464 if (wordWrap) { |
2350 TextLayout layout = renderer.getTextLayout(caretLine); | 2465 TextLayout layout = renderer.getTextLayout(caretLine); |
2351 int offsetInLine = caretOffset - lineOffset; | 2466 int offsetInLine = caretOffset - lineOffset; |
2352 int lineIndex = getVisualLineIndex(layout, offsetInLine); | 2467 int lineIndex = getVisualLineIndex(layout, offsetInLine); |
2353 int[] offsets = layout.getLineOffsets(); | 2468 int[] offsets = layout.getLineOffsets(); |
2354 lineEndOffset = lineOffset + offsets[lineIndex + 1]; | 2469 lineEndOffset = lineOffset + offsets[lineIndex + 1]; |
2355 renderer.disposeTextLayout(layout); | 2470 renderer.disposeTextLayout(layout); |
2356 } else { | 2471 } else { |
2357 int lineLength = content.getLine(caretLine).length(); | 2472 int lineLength = content.getLine(caretLine).length; |
2358 lineEndOffset = lineOffset + lineLength; | 2473 lineEndOffset = lineOffset + lineLength; |
2359 } | 2474 } |
2360 if (caretOffset < lineEndOffset) { | 2475 if (caretOffset < lineEndOffset) { |
2361 caretOffset = lineEndOffset; | 2476 caretOffset = lineEndOffset; |
2362 caretAlignment = PREVIOUS_OFFSET_TRAILING; | 2477 caretAlignment = PREVIOUS_OFFSET_TRAILING; |
2382 caretAlignment = OFFSET_LEADING; | 2497 caretAlignment = OFFSET_LEADING; |
2383 showCaret(); | 2498 showCaret(); |
2384 } | 2499 } |
2385 } | 2500 } |
2386 /** | 2501 /** |
2387 * Moves the caret one line up and to the same character offset relative | 2502 * Moves the caret one line up and to the same character offset relative |
2388 * to the beginning of the line. Move the caret to the end of the new line | 2503 * to the beginning of the line. Move the caret to the end of the new line |
2389 * if the new line is shorter than the character offset. | 2504 * if the new line is shorter than the character offset. |
2390 */ | 2505 */ |
2391 void doLineUp(bool select) { | 2506 void doLineUp(bool select) { |
2392 int caretLine = getCaretLine(), y = 0; | 2507 int caretLine = getCaretLine(), y = 0; |
2393 bool firstLine = false; | 2508 bool firstLine = false; |
2433 */ | 2548 */ |
2434 void doMouseLocationChange(int x, int y, bool select) { | 2549 void doMouseLocationChange(int x, int y, bool select) { |
2435 int line = getLineIndex(y); | 2550 int line = getLineIndex(y); |
2436 | 2551 |
2437 updateCaretDirection = true; | 2552 updateCaretDirection = true; |
2438 // allow caret to be placed below first line only if receiver is | 2553 // allow caret to be placed below first line only if receiver is |
2439 // not in single line mode. fixes 4820. | 2554 // not in single line mode. fixes 4820. |
2440 if (line < 0 || (isSingleLine() && line > 0)) { | 2555 if (line < 0 || (isSingleLine() && line > 0)) { |
2441 return; | 2556 return; |
2442 } | 2557 } |
2443 int oldCaretAlignment = caretAlignment; | 2558 int oldCaretAlignment = caretAlignment; |
2444 int newCaretOffset = getOffsetAtPoint(x, y); | 2559 int newCaretOffset = getOffsetAtPoint(x, y); |
2445 | 2560 |
2446 if (doubleClickEnabled && clickCount > 1) { | 2561 if (doubleClickEnabled && clickCount > 1) { |
2447 newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); | 2562 newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); |
2448 } | 2563 } |
2449 | 2564 |
2450 int newCaretLine = content.getLineAtOffset(newCaretOffset); | 2565 int newCaretLine = content.getLineAtOffset(newCaretOffset); |
2451 | 2566 |
2452 // Is the mouse within the left client area border or on | 2567 // Is the mouse within the left client area border or on |
2453 // a different line? If not the autoscroll selection | 2568 // a different line? If not the autoscroll selection |
2454 // could be incorrectly reset. Fixes 1GKM3XS | 2569 // could be incorrectly reset. Fixes 1GKM3XS |
2455 if (0 <= y && y < clientAreaHeight && | 2570 if (0 <= y && y < clientAreaHeight && |
2456 (0 <= x && x < clientAreaWidth || wordWrap || | 2571 (0 <= x && x < clientAreaWidth || wordWrap || |
2457 newCaretLine !is content.getLineAtOffset(caretOffset))) { | 2572 newCaretLine !is content.getLineAtOffset(caretOffset))) { |
2458 if (newCaretOffset !is caretOffset || caretAlignment !is oldCaretAlignment) { | 2573 if (newCaretOffset !is caretOffset || caretAlignment !is oldCaretAlignment) { |
2459 caretOffset = newCaretOffset; | 2574 caretOffset = newCaretOffset; |
2460 if (select) doMouseSelection(); | 2575 if (select) doMouseSelection(); |
2461 showCaret(); | 2576 showCaret(); |
2468 } | 2583 } |
2469 /** | 2584 /** |
2470 * Updates the selection based on the caret position | 2585 * Updates the selection based on the caret position |
2471 */ | 2586 */ |
2472 void doMouseSelection() { | 2587 void doMouseSelection() { |
2473 if (caretOffset <= selection.x || | 2588 if (caretOffset <= selection.x || |
2474 (caretOffset > selection.x && | 2589 (caretOffset > selection.x && |
2475 caretOffset < selection.y && selectionAnchor is selection.x)) { | 2590 caretOffset < selection.y && selectionAnchor is selection.x)) { |
2476 doSelection(ST.COLUMN_PREVIOUS); | 2591 doSelection(ST.COLUMN_PREVIOUS); |
2477 } else { | 2592 } else { |
2478 doSelection(ST.COLUMN_NEXT); | 2593 doSelection(ST.COLUMN_NEXT); |
2479 } | 2594 } |
2480 } | 2595 } |
2481 /** | 2596 /** |
2482 * Returns the offset of the word at the specified offset. | 2597 * Returns the offset of the word at the specified offset. |
2483 * If the current selection : from high index to low index | 2598 * If the current selection extends from high index to low index |
2484 * (i.e., right to left, or caret is at left border of selection on | 2599 * (i.e., right to left, or caret is at left border of selection on |
2485 * non-bidi platforms) the start offset of the word preceding the | 2600 * non-bidi platforms) the start offset of the word preceding the |
2486 * selection is returned. If the current selection : from | 2601 * selection is returned. If the current selection extends from |
2487 * low index to high index the end offset of the word following | 2602 * low index to high index the end offset of the word following |
2488 * the selection is returned. | 2603 * the selection is returned. |
2489 * | 2604 * |
2490 * @param x mouse x location | 2605 * @param x mouse x location |
2491 * @param newCaretOffset caret offset of the mouse cursor location | 2606 * @param newCaretOffset caret offset of the mouse cursor location |
2492 * @param line line index of the mouse cursor location | 2607 * @param line line index of the mouse cursor location |
2493 */ | 2608 */ |
2494 int doMouseWordSelect(int x, int newCaretOffset, int line) { | 2609 int doMouseWordSelect(int x, int newCaretOffset, int line) { |
2495 // flip selection anchor based on word selection direction from | 2610 // flip selection anchor based on word selection direction from |
2496 // base double click. Always do this here (and don't rely on doAutoScroll) | 2611 // base double click. Always do this here (and don't rely on doAutoScroll) |
2497 // because auto scroll only does not cover all possible mouse selections | 2612 // because auto scroll only does not cover all possible mouse selections |
2498 // (e.g., mouse x < 0 && mouse y > caret line y) | 2613 // (e.g., mouse x < 0 && mouse y > caret line y) |
2499 if (newCaretOffset < selectionAnchor && selectionAnchor is selection.x) { | 2614 if (newCaretOffset < selectionAnchor && selectionAnchor is selection.x) { |
2500 selectionAnchor = doubleClickSelection.y; | 2615 selectionAnchor = doubleClickSelection.y; |
2515 } else { | 2630 } else { |
2516 int lineEnd = content.getCharCount(); | 2631 int lineEnd = content.getCharCount(); |
2517 if (line + 1 < content.getLineCount()) { | 2632 if (line + 1 < content.getLineCount()) { |
2518 lineEnd = content.getOffsetAtLine(line + 1); | 2633 lineEnd = content.getOffsetAtLine(line + 1); |
2519 } | 2634 } |
2520 newCaretOffset = lineEnd; | 2635 newCaretOffset = lineEnd; |
2521 } | 2636 } |
2522 } | 2637 } |
2523 } | 2638 } |
2524 return newCaretOffset; | 2639 return newCaretOffset; |
2525 } | 2640 } |
2526 /** | 2641 /** |
2527 * Scrolls one page down so that the last line (truncated or whole) | 2642 * Scrolls one page down so that the last line (truncated or whole) |
2528 * of the current page becomes the fully visible top line. | 2643 * of the current page becomes the fully visible top line. |
2529 * <p> | 2644 * <p> |
2530 * The caret is scrolled the same number of lines so that its location | 2645 * The caret is scrolled the same number of lines so that its location |
2531 * relative to the top line remains the same. The exception is the end | 2646 * relative to the top line remains the same. The exception is the end |
2532 * of the text where a full page scroll is not possible. In this case | 2647 * of the text where a full page scroll is not possible. In this case |
2533 * the caret is moved after the last character. | 2648 * the caret is moved after the last character. |
2534 * </p> | 2649 * </p> |
2535 * | 2650 * |
2536 * @param select whether or not to select the page | 2651 * @param select whether or not to select the page |
2537 */ | 2652 */ |
2544 int caretLine = getCaretLine(); | 2659 int caretLine = getCaretLine(); |
2545 if (caretLine < lineCount - 1) { | 2660 if (caretLine < lineCount - 1) { |
2546 int lineHeight = renderer.getLineHeight(); | 2661 int lineHeight = renderer.getLineHeight(); |
2547 int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; | 2662 int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; |
2548 int scrollLines = Math.min(lineCount - caretLine - 1, lines); | 2663 int scrollLines = Math.min(lineCount - caretLine - 1, lines); |
2549 // ensure that scrollLines never gets negative and at least one | 2664 // ensure that scrollLines never gets negative and at least one |
2550 // line is scrolled. fixes bug 5602. | 2665 // line is scrolled. fixes bug 5602. |
2551 scrollLines = Math.max(1, scrollLines); | 2666 scrollLines = Math.max(1, scrollLines); |
2552 caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines)); | 2667 caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines)); |
2553 if (select) { | 2668 if (select) { |
2554 doSelection(ST.COLUMN_NEXT); | 2669 doSelection(ST.COLUMN_NEXT); |
2625 caretOffset = getOffsetAtPoint(columnX, caretHeight, lineIndex); | 2740 caretOffset = getOffsetAtPoint(columnX, caretHeight, lineIndex); |
2626 if (select) doSelection(ST.COLUMN_NEXT); | 2741 if (select) doSelection(ST.COLUMN_NEXT); |
2627 height = getAvailableHeightBellow(height); | 2742 height = getAvailableHeightBellow(height); |
2628 scrollVertical(height, true); | 2743 scrollVertical(height, true); |
2629 if (height is 0) setCaretLocation(); | 2744 if (height is 0) setCaretLocation(); |
2630 } | 2745 } |
2631 showCaret(); | 2746 showCaret(); |
2632 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; | 2747 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; |
2633 columnX = oldColumnX + hScrollChange; | 2748 columnX = oldColumnX + hScrollChange; |
2634 } | 2749 } |
2635 /** | 2750 /** |
2636 * Moves the cursor to the end of the last fully visible line. | 2751 * Moves the cursor to the end of the last fully visible line. |
2637 */ | 2752 */ |
2638 void doPageEnd() { | 2753 void doPageEnd() { |
2650 Rectangle bounds = layout.getLineBounds(index); | 2765 Rectangle bounds = layout.getLineBounds(index); |
2651 if (y >= bounds.y + bounds.height) break; | 2766 if (y >= bounds.y + bounds.height) break; |
2652 index--; | 2767 index--; |
2653 } | 2768 } |
2654 if (index is -1 && lineIndex > 0) { | 2769 if (index is -1 && lineIndex > 0) { |
2655 bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); | 2770 bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length; |
2656 } else { | 2771 } else { |
2657 bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); | 2772 bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); |
2658 } | 2773 } |
2659 renderer.disposeTextLayout(layout); | 2774 renderer.disposeTextLayout(layout); |
2660 } else { | 2775 } else { |
2661 int lineIndex = getBottomIndex(); | 2776 int lineIndex = getBottomIndex(); |
2662 bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length(); | 2777 bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length; |
2663 } | 2778 } |
2664 if (caretOffset < bottomOffset) { | 2779 if (caretOffset < bottomOffset) { |
2665 caretOffset = bottomOffset; | 2780 caretOffset = bottomOffset; |
2666 caretAlignment = OFFSET_LEADING; | 2781 caretAlignment = OFFSET_LEADING; |
2667 showCaret(); | 2782 showCaret(); |
2693 if (index is lineCount) { | 2808 if (index is lineCount) { |
2694 topOffset = content.getOffsetAtLine(lineIndex + 1); | 2809 topOffset = content.getOffsetAtLine(lineIndex + 1); |
2695 } else { | 2810 } else { |
2696 topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; | 2811 topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; |
2697 } | 2812 } |
2698 renderer.disposeTextLayout(layout); | 2813 renderer.disposeTextLayout(layout); |
2699 } else { | 2814 } else { |
2700 topOffset = content.getOffsetAtLine(topIndex); | 2815 topOffset = content.getOffsetAtLine(topIndex); |
2701 } | 2816 } |
2702 if (caretOffset > topOffset) { | 2817 if (caretOffset > topOffset) { |
2703 caretOffset = topOffset; | 2818 caretOffset = topOffset; |
2706 } | 2821 } |
2707 } | 2822 } |
2708 /** | 2823 /** |
2709 * Scrolls one page up so that the first line (truncated or whole) | 2824 * Scrolls one page up so that the first line (truncated or whole) |
2710 * of the current page becomes the fully visible last line. | 2825 * of the current page becomes the fully visible last line. |
2711 * The caret is scrolled the same number of lines so that its location | 2826 * The caret is scrolled the same number of lines so that its location |
2712 * relative to the top line remains the same. The exception is the beginning | 2827 * relative to the top line remains the same. The exception is the beginning |
2713 * of the text where a full page scroll is not possible. In this case the | 2828 * of the text where a full page scroll is not possible. In this case the |
2714 * caret is moved in front of the first character. | 2829 * caret is moved in front of the first character. |
2715 */ | 2830 */ |
2716 void doPageUp(bool select, int height) { | 2831 void doPageUp(bool select, int height) { |
2717 if (isSingleLine()) return; | 2832 if (isSingleLine()) return; |
2718 int oldHScrollOffset = horizontalScrollOffset; | 2833 int oldHScrollOffset = horizontalScrollOffset; |
2719 int oldColumnX = columnX; | 2834 int oldColumnX = columnX; |
2720 if (isFixedLineHeight()) { | 2835 if (isFixedLineHeight()) { |
2721 int caretLine = getCaretLine(); | 2836 int caretLine = getCaretLine(); |
2722 if (caretLine > 0) { | 2837 if (caretLine > 0) { |
2723 int lineHeight = renderer.getLineHeight(); | 2838 int lineHeight = renderer.getLineHeight(); |
2724 int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; | 2839 int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; |
2725 int scrollLines = Math.max(1, Math.min(caretLine, lines)); | 2840 int scrollLines = Math.max(1, Math.min(caretLine, lines)); |
2726 caretLine -= scrollLines; | 2841 caretLine -= scrollLines; |
2796 while (caretHeight - lineHeight >= 0 && lineIndex > 0) { | 2911 while (caretHeight - lineHeight >= 0 && lineIndex > 0) { |
2797 caretHeight -= lineHeight; | 2912 caretHeight -= lineHeight; |
2798 lineHeight = renderer.getLineHeight(--lineIndex); | 2913 lineHeight = renderer.getLineHeight(--lineIndex); |
2799 } | 2914 } |
2800 lineHeight = renderer.getLineHeight(lineIndex); | 2915 lineHeight = renderer.getLineHeight(lineIndex); |
2801 caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); | 2916 caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); |
2802 if (select) doSelection(ST.COLUMN_PREVIOUS); | 2917 if (select) doSelection(ST.COLUMN_PREVIOUS); |
2803 height = getAvailableHeightAbove(height); | 2918 height = getAvailableHeightAbove(height); |
2804 scrollVertical(-height, true); | 2919 scrollVertical(-height, true); |
2805 if (height is 0) setCaretLocation(); | 2920 if (height is 0) setCaretLocation(); |
2806 } | 2921 } |
2807 showCaret(); | 2922 showCaret(); |
2808 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; | 2923 int hScrollChange = oldHScrollOffset - horizontalScrollOffset; |
2809 columnX = oldColumnX + hScrollChange; | 2924 columnX = oldColumnX + hScrollChange; |
2810 } | 2925 } |
2811 /** | 2926 /** |
2812 * Updates the selection to extend to the current caret position. | 2927 * Updates the selection to extend to the current caret position. |
2813 */ | 2928 */ |
2814 void doSelection(int direction) { | 2929 void doSelection(int direction) { |
2815 int redrawStart = -1; | 2930 int redrawStart = -1; |
2816 int redrawEnd = -1; | 2931 int redrawEnd = -1; |
2817 if (selectionAnchor is -1) { | 2932 if (selectionAnchor is -1) { |
2818 selectionAnchor = selection.x; | 2933 selectionAnchor = selection.x; |
2819 } | 2934 } |
2820 if (direction is ST.COLUMN_PREVIOUS) { | 2935 if (direction is ST.COLUMN_PREVIOUS) { |
2821 if (caretOffset < selection.x) { | 2936 if (caretOffset < selection.x) { |
2822 // grow selection | 2937 // grow selection |
2823 redrawEnd = selection.x; | 2938 redrawEnd = selection.x; |
2824 redrawStart = selection.x = caretOffset; | 2939 redrawStart = selection.x = caretOffset; |
2825 // check if selection has reversed direction | 2940 // check if selection has reversed direction |
2826 if (selection.y !is selectionAnchor) { | 2941 if (selection.y !is selectionAnchor) { |
2827 redrawEnd = selection.y; | 2942 redrawEnd = selection.y; |
2828 selection.y = selectionAnchor; | 2943 selection.y = selectionAnchor; |
2829 } | 2944 } |
2830 // test whether selection actually changed. Fixes 1G71EO1 | 2945 // test whether selection actually changed. Fixes 1G71EO1 |
2831 } else if (selectionAnchor is selection.x && caretOffset < selection.y) { | 2946 } else if (selectionAnchor is selection.x && caretOffset < selection.y) { |
2832 // caret moved towards selection anchor (left side of selection). | 2947 // caret moved towards selection anchor (left side of selection). |
2833 // shrink selection | 2948 // shrink selection |
2834 redrawEnd = selection.y; | 2949 redrawEnd = selection.y; |
2835 redrawStart = selection.y = caretOffset; | 2950 redrawStart = selection.y = caretOffset; |
2836 } | 2951 } |
2837 } else { | 2952 } else { |
2838 if (caretOffset > selection.y) { | 2953 if (caretOffset > selection.y) { |
2839 // grow selection | 2954 // grow selection |
2840 redrawStart = selection.y; | 2955 redrawStart = selection.y; |
2841 redrawEnd = selection.y = caretOffset; | 2956 redrawEnd = selection.y = caretOffset; |
2842 // check if selection has reversed direction | 2957 // check if selection has reversed direction |
2843 if (selection.x !is selectionAnchor) { | 2958 if (selection.x !is selectionAnchor) { |
2844 redrawStart = selection.x; | 2959 redrawStart = selection.x; |
2845 selection.x = selectionAnchor; | 2960 selection.x = selectionAnchor; |
2846 } | 2961 } |
2847 // test whether selection actually changed. Fixes 1G71EO1 | 2962 // test whether selection actually changed. Fixes 1G71EO1 |
2848 } else if (selectionAnchor is selection.y && caretOffset > selection.x) { | 2963 } else if (selectionAnchor is selection.y && caretOffset > selection.x) { |
2849 // caret moved towards selection anchor (right side of selection). | 2964 // caret moved towards selection anchor (right side of selection). |
2850 // shrink selection | 2965 // shrink selection |
2851 redrawStart = selection.x; | 2966 redrawStart = selection.x; |
2852 redrawEnd = selection.x = caretOffset; | 2967 redrawEnd = selection.x = caretOffset; |
2853 } | 2968 } |
2854 } | 2969 } |
2855 if (redrawStart !is -1 && redrawEnd !is -1) { | 2970 if (redrawStart !is -1 && redrawEnd !is -1) { |
2856 internalRedrawRange(redrawStart, redrawEnd - redrawStart); | 2971 internalRedrawRange(redrawStart, redrawEnd - redrawStart); |
2857 sendSelectionEvent(); | 2972 sendSelectionEvent(); |
2858 } | 2973 } |
2859 } | 2974 } |
2860 /** | 2975 /** |
2861 * Moves the caret to the next character or to the beginning of the | 2976 * Moves the caret to the next character or to the beginning of the |
2862 * next line if the cursor is at the end of a line. | 2977 * next line if the cursor is at the end of a line. |
2863 */ | 2978 */ |
2864 void doSelectionCursorNext() { | 2979 void doSelectionCursorNext() { |
2865 int caretLine = getCaretLine(); | 2980 int caretLine = getCaretLine(); |
2866 int lineOffset = content.getOffsetAtLine(caretLine); | 2981 int lineOffset = content.getOffsetAtLine(caretLine); |
2867 int offsetInLine = caretOffset - lineOffset; | 2982 int offsetInLine = caretOffset - lineOffset; |
2868 if (offsetInLine < content.getLine(caretLine).length()) { | 2983 if (offsetInLine < content.getLine(caretLine).length) { |
2869 TextLayout layout = renderer.getTextLayout(caretLine); | 2984 TextLayout layout = renderer.getTextLayout(caretLine); |
2870 offsetInLine = layout.getNextOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); | 2985 offsetInLine = layout.getNextOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); |
2871 int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; | 2986 int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; |
2872 renderer.disposeTextLayout(layout); | 2987 renderer.disposeTextLayout(layout); |
2873 caretOffset = offsetInLine + lineOffset; | 2988 caretOffset = offsetInLine + lineOffset; |
2874 caretAlignment = offsetInLine is lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; | 2989 caretAlignment = offsetInLine is lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; |
2875 showCaret(); | 2990 showCaret(); |
2876 } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { | 2991 } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { |
2877 caretLine++; | 2992 caretLine++; |
2878 caretOffset = content.getOffsetAtLine(caretLine); | 2993 caretOffset = content.getOffsetAtLine(caretLine); |
2879 caretAlignment = PREVIOUS_OFFSET_TRAILING; | 2994 caretAlignment = PREVIOUS_OFFSET_TRAILING; |
2880 showCaret(); | 2995 showCaret(); |
2881 } | 2996 } |
2882 } | 2997 } |
2883 /** | 2998 /** |
2884 * Moves the caret to the previous character or to the end of the previous | 2999 * Moves the caret to the previous character or to the end of the previous |
2885 * line if the cursor is at the beginning of a line. | 3000 * line if the cursor is at the beginning of a line. |
2886 */ | 3001 */ |
2887 void doSelectionCursorPrevious() { | 3002 void doSelectionCursorPrevious() { |
2888 int caretLine = getCaretLine(); | 3003 int caretLine = getCaretLine(); |
2889 int lineOffset = content.getOffsetAtLine(caretLine); | 3004 int lineOffset = content.getOffsetAtLine(caretLine); |
2890 int offsetInLine = caretOffset - lineOffset; | 3005 int offsetInLine = caretOffset - lineOffset; |
2891 caretAlignment = OFFSET_LEADING; | 3006 caretAlignment = OFFSET_LEADING; |
3007 | |
2892 if (offsetInLine > 0) { | 3008 if (offsetInLine > 0) { |
2893 caretOffset = getClusterPrevious(caretOffset, caretLine); | 3009 caretOffset = getClusterPrevious(caretOffset, caretLine); |
2894 showCaret(); | 3010 showCaret(); |
2895 } else if (caretLine > 0) { | 3011 } else if (caretLine > 0) { |
2896 caretLine--; | 3012 caretLine--; |
2897 lineOffset = content.getOffsetAtLine(caretLine); | 3013 lineOffset = content.getOffsetAtLine(caretLine); |
2898 caretOffset = lineOffset + content.getLine(caretLine).length(); | 3014 caretOffset = lineOffset + content.getLine(caretLine).length; |
2899 showCaret(); | 3015 showCaret(); |
2900 } | 3016 } |
2901 } | 3017 } |
2902 /** | 3018 /** |
2903 * Moves the caret one line down and to the same character offset relative | 3019 * Moves the caret one line down and to the same character offset relative |
2904 * to the beginning of the line. Moves the caret to the end of the new line | 3020 * to the beginning of the line. Moves the caret to the end of the new line |
2905 * if the new line is shorter than the character offset. | 3021 * if the new line is shorter than the character offset. |
2906 * Moves the caret to the end of the text if the caret already is on the | 3022 * Moves the caret to the end of the text if the caret already is on the |
2907 * last line. | 3023 * last line. |
2908 * Adjusts the selection according to the caret change. This can either add | 3024 * Adjusts the selection according to the caret change. This can either add |
2909 * to or subtract from the old selection, depending on the previous selection | 3025 * to or subtract from the old selection, depending on the previous selection |
2910 * direction. | 3026 * direction. |
2911 */ | 3027 */ |
2913 int oldColumnX = columnX = getPointAtOffset(caretOffset).x; | 3029 int oldColumnX = columnX = getPointAtOffset(caretOffset).x; |
2914 doLineDown(true); | 3030 doLineDown(true); |
2915 columnX = oldColumnX; | 3031 columnX = oldColumnX; |
2916 } | 3032 } |
2917 /** | 3033 /** |
2918 * Moves the caret one line up and to the same character offset relative | 3034 * Moves the caret one line up and to the same character offset relative |
2919 * to the beginning of the line. Moves the caret to the end of the new line | 3035 * to the beginning of the line. Moves the caret to the end of the new line |
2920 * if the new line is shorter than the character offset. | 3036 * if the new line is shorter than the character offset. |
2921 * Moves the caret to the beginning of the document if it is already on the | 3037 * Moves the caret to the beginning of the document if it is already on the |
2922 * first line. | 3038 * first line. |
2923 * Adjusts the selection according to the caret change. This can either add | 3039 * Adjusts the selection according to the caret change. This can either add |
2924 * to or subtract from the old selection, depending on the previous selection | 3040 * to or subtract from the old selection, depending on the previous selection |
2925 * direction. | 3041 * direction. |
2926 */ | 3042 */ |
2927 void doSelectionLineUp() { | 3043 void doSelectionLineUp() { |
2928 int oldColumnX = columnX = getPointAtOffset(caretOffset).x; | 3044 int oldColumnX = columnX = getPointAtOffset(caretOffset).x; |
2929 doLineUp(true); | 3045 doLineUp(true); |
2930 columnX = oldColumnX; | 3046 columnX = oldColumnX; |
2931 } | 3047 } |
2932 /** | 3048 /** |
2933 * Scrolls one page down so that the last line (truncated or whole) | 3049 * Scrolls one page down so that the last line (truncated or whole) |
2934 * of the current page becomes the fully visible top line. | 3050 * of the current page becomes the fully visible top line. |
2935 * <p> | 3051 * <p> |
2936 * The caret is scrolled the same number of lines so that its location | 3052 * The caret is scrolled the same number of lines so that its location |
2937 * relative to the top line remains the same. The exception is the end | 3053 * relative to the top line remains the same. The exception is the end |
2938 * of the text where a full page scroll is not possible. In this case | 3054 * of the text where a full page scroll is not possible. In this case |
2939 * the caret is moved after the last character. | 3055 * the caret is moved after the last character. |
2940 * <p></p> | 3056 * <p></p> |
2941 * Adjusts the selection according to the caret change. This can either add | 3057 * Adjusts the selection according to the caret change. This can either add |
2942 * to or subtract from the old selection, depending on the previous selection | 3058 * to or subtract from the old selection, depending on the previous selection |
2943 * direction. | 3059 * direction. |
2950 } | 3066 } |
2951 /** | 3067 /** |
2952 * Scrolls one page up so that the first line (truncated or whole) | 3068 * Scrolls one page up so that the first line (truncated or whole) |
2953 * of the current page becomes the fully visible last line. | 3069 * of the current page becomes the fully visible last line. |
2954 * <p> | 3070 * <p> |
2955 * The caret is scrolled the same number of lines so that its location | 3071 * The caret is scrolled the same number of lines so that its location |
2956 * relative to the top line remains the same. The exception is the beginning | 3072 * relative to the top line remains the same. The exception is the beginning |
2957 * of the text where a full page scroll is not possible. In this case the | 3073 * of the text where a full page scroll is not possible. In this case the |
2958 * caret is moved in front of the first character. | 3074 * caret is moved in front of the first character. |
2959 * </p><p> | 3075 * </p><p> |
2960 * Adjusts the selection according to the caret change. This can either add | 3076 * Adjusts the selection according to the caret change. This can either add |
2961 * to or subtract from the old selection, depending on the previous selection | 3077 * to or subtract from the old selection, depending on the previous selection |
2972 */ | 3088 */ |
2973 void doSelectionWordNext() { | 3089 void doSelectionWordNext() { |
2974 int newCaretOffset = getWordNext(caretOffset, DWT.MOVEMENT_WORD); | 3090 int newCaretOffset = getWordNext(caretOffset, DWT.MOVEMENT_WORD); |
2975 // Force symmetrical movement for word next and previous. Fixes 14536 | 3091 // Force symmetrical movement for word next and previous. Fixes 14536 |
2976 caretAlignment = OFFSET_LEADING; | 3092 caretAlignment = OFFSET_LEADING; |
2977 // don't change caret position if in single line mode and the cursor | 3093 // don't change caret position if in single line mode and the cursor |
2978 // would be on a different line. fixes 5673 | 3094 // would be on a different line. fixes 5673 |
2979 if (!isSingleLine() || | 3095 if (!isSingleLine() || |
2980 content.getLineAtOffset(caretOffset) is content.getLineAtOffset(newCaretOffset)) { | 3096 content.getLineAtOffset(caretOffset) is content.getLineAtOffset(newCaretOffset)) { |
2981 caretOffset = newCaretOffset; | 3097 caretOffset = newCaretOffset; |
2982 showCaret(); | 3098 showCaret(); |
2983 } | 3099 } |
2984 } | 3100 } |
2997 } | 3113 } |
2998 showCaret(); | 3114 showCaret(); |
2999 } | 3115 } |
3000 /** | 3116 /** |
3001 * Moves the caret one character to the left. Do not go to the previous line. | 3117 * Moves the caret one character to the left. Do not go to the previous line. |
3002 * When in a bidi locale and at a R2L character the caret is moved to the | 3118 * When in a bidi locale and at a R2L character the caret is moved to the |
3003 * beginning of the R2L segment (visually right) and then one character to the | 3119 * beginning of the R2L segment (visually right) and then one character to the |
3004 * left (visually left because it's now in a L2R segment). | 3120 * left (visually left because it's now in a L2R segment). |
3005 */ | 3121 */ |
3006 void doVisualPrevious() { | 3122 void doVisualPrevious() { |
3007 caretOffset = getClusterPrevious(caretOffset, getCaretLine()); | 3123 caretOffset = getClusterPrevious(caretOffset, getCaretLine()); |
3008 showCaret(); | 3124 showCaret(); |
3009 } | 3125 } |
3010 /** | 3126 /** |
3011 * Moves the caret one character to the right. Do not go to the next line. | 3127 * Moves the caret one character to the right. Do not go to the next line. |
3012 * When in a bidi locale and at a R2L character the caret is moved to the | 3128 * When in a bidi locale and at a R2L character the caret is moved to the |
3013 * end of the R2L segment (visually left) and then one character to the | 3129 * end of the R2L segment (visually left) and then one character to the |
3014 * right (visually right because it's now in a L2R segment). | 3130 * right (visually right because it's now in a L2R segment). |
3015 */ | 3131 */ |
3016 void doVisualNext() { | 3132 void doVisualNext() { |
3017 caretOffset = getClusterNext(caretOffset, getCaretLine()); | 3133 caretOffset = getClusterNext(caretOffset, getCaretLine()); |
3018 showCaret(); | 3134 showCaret(); |
3041 showCaret(); | 3157 showCaret(); |
3042 } else { | 3158 } else { |
3043 doSelectionWordPrevious(); | 3159 doSelectionWordPrevious(); |
3044 } | 3160 } |
3045 } | 3161 } |
3046 /** | 3162 /** |
3047 * Ends the autoscroll process. | 3163 * Ends the autoscroll process. |
3048 */ | 3164 */ |
3049 void endAutoScroll() { | 3165 void endAutoScroll() { |
3050 autoScrollDirection = DWT.NULL; | 3166 autoScrollDirection = DWT.NULL; |
3051 } | 3167 } |
3052 public Color getBackground() { | 3168 public override Color getBackground() { |
3053 checkWidget(); | 3169 checkWidget(); |
3054 if (background is null) { | 3170 if (background is null) { |
3055 return getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND); | 3171 return getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND); |
3056 } | 3172 } |
3057 return background; | 3173 return background; |
3058 } | 3174 } |
3059 /** | 3175 /** |
3060 * Returns the baseline, in pixels. | 3176 * Returns the baseline, in pixels. |
3061 * | 3177 * |
3062 * Note: this API should not be used if a StyleRange attribute causes lines to | 3178 * Note: this API should not be used if a StyleRange attribute causes lines to |
3063 * have different heights (i.e. different fonts, rise, etc). | 3179 * have different heights (i.e. different fonts, rise, etc). |
3064 * | 3180 * |
3065 * @return baseline the baseline | 3181 * @return baseline the baseline |
3066 * @exception DWTException <ul> | 3182 * @exception DWTException <ul> |
3067 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3183 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3068 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3184 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3069 * </ul> | 3185 * </ul> |
3070 * @since 3.0 | 3186 * @since 3.0 |
3071 * | 3187 * |
3072 * @see #getBaseline(int) | 3188 * @see #getBaseline(int) |
3073 */ | 3189 */ |
3074 public int getBaseline() { | 3190 public int getBaseline() { |
3075 checkWidget(); | 3191 checkWidget(); |
3076 return renderer.getBaseline(); | 3192 return renderer.getBaseline(); |
3077 } | 3193 } |
3078 /** | 3194 /** |
3079 * Returns the baseline at the given offset, in pixels. | 3195 * Returns the baseline at the given offset, in pixels. |
3080 * | 3196 * |
3081 * @param offset the offset | 3197 * @param offset the offset |
3082 * | 3198 * |
3083 * @return baseline the baseline | 3199 * @return baseline the baseline |
3084 * | 3200 * |
3085 * @exception DWTException <ul> | 3201 * @exception DWTException <ul> |
3086 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3202 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3087 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3203 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3088 * </ul> | 3204 * </ul> |
3089 * @exception IllegalArgumentException <ul> | 3205 * @exception IllegalArgumentException <ul> |
3090 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> | 3206 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3091 * </ul> | 3207 * </ul> |
3092 * | 3208 * |
3093 * @since 3.2 | 3209 * @since 3.2 |
3094 */ | 3210 */ |
3095 public int getBaseline(int offset) { | 3211 public int getBaseline(int offset) { |
3096 checkWidget(); | 3212 checkWidget(); |
3097 if (!(0 <= offset && offset <= content.getCharCount())) { | 3213 if (!(0 <= offset && offset <= content.getCharCount())) { |
3101 return renderer.getBaseline(); | 3217 return renderer.getBaseline(); |
3102 } | 3218 } |
3103 int lineIndex = content.getLineAtOffset(offset); | 3219 int lineIndex = content.getLineAtOffset(offset); |
3104 int lineOffset = content.getOffsetAtLine(lineIndex); | 3220 int lineOffset = content.getOffsetAtLine(lineIndex); |
3105 TextLayout layout = renderer.getTextLayout(lineIndex); | 3221 TextLayout layout = renderer.getTextLayout(lineIndex); |
3106 int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); | 3222 int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); |
3107 FontMetrics metrics = layout.getLineMetrics(lineInParagraph); | 3223 FontMetrics metrics = layout.getLineMetrics(lineInParagraph); |
3108 renderer.disposeTextLayout(layout); | 3224 renderer.disposeTextLayout(layout); |
3109 return metrics.getAscent() + metrics.getLeading(); | 3225 return metrics.getAscent() + metrics.getLeading(); |
3110 } | 3226 } |
3111 /** | 3227 /** |
3116 * @return the current coloring mode | 3232 * @return the current coloring mode |
3117 * @exception DWTException <ul> | 3233 * @exception DWTException <ul> |
3118 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3234 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3119 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3235 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3120 * </ul> | 3236 * </ul> |
3121 * | 3237 * |
3122 * @deprecated use BidiSegmentListener instead. | 3238 * @deprecated use BidiSegmentListener instead. |
3123 */ | 3239 */ |
3124 public bool getBidiColoring() { | 3240 public bool getBidiColoring() { |
3125 checkWidget(); | 3241 checkWidget(); |
3126 return bidiColoring; | 3242 return bidiColoring; |
3127 } | 3243 } |
3128 /** | 3244 /** |
3129 * Returns the index of the last fully visible line. | 3245 * Returns the index of the last fully visible line. |
3130 * | 3246 * |
3131 * @return index of the last fully visible line. | 3247 * @return index of the last fully visible line. |
3132 */ | 3248 */ |
3133 int getBottomIndex() { | 3249 int getBottomIndex() { |
3159 Rectangle getBoundsAtOffset(int offset) { | 3275 Rectangle getBoundsAtOffset(int offset) { |
3160 int lineIndex = content.getLineAtOffset(offset); | 3276 int lineIndex = content.getLineAtOffset(offset); |
3161 int lineOffset = content.getOffsetAtLine(lineIndex); | 3277 int lineOffset = content.getOffsetAtLine(lineIndex); |
3162 String line = content.getLine(lineIndex); | 3278 String line = content.getLine(lineIndex); |
3163 Rectangle bounds; | 3279 Rectangle bounds; |
3164 if (line.length() !is 0) { | 3280 if (line.length !is 0) { |
3165 int offsetInLine = offset - lineOffset; | 3281 int offsetInLine = offset - lineOffset; |
3166 TextLayout layout = renderer.getTextLayout(lineIndex); | 3282 TextLayout layout = renderer.getTextLayout(lineIndex); |
3167 bounds = layout.getBounds(offsetInLine, offsetInLine); | 3283 bounds = layout.getBounds(offsetInLine, offsetInLine); |
3168 renderer.disposeTextLayout(layout); | 3284 renderer.disposeTextLayout(layout); |
3169 } else { | 3285 } else { |
3170 bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); | 3286 bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); |
3171 } | 3287 } |
3172 if (offset is caretOffset) { | 3288 if (offset is caretOffset) { |
3173 int lineEnd = lineOffset + line.length(); | 3289 int lineEnd = lineOffset + line.length; |
3174 if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) { | 3290 if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) { |
3175 bounds.width += getCaretWidth(); | 3291 bounds.width += getCaretWidth(); |
3176 } | 3292 } |
3177 } | 3293 } |
3178 bounds.x += leftMargin - horizontalScrollOffset; | 3294 bounds.x += leftMargin - horizontalScrollOffset; |
3205 Object getClipboardContent(int clipboardType) { | 3321 Object getClipboardContent(int clipboardType) { |
3206 TextTransfer plainTextTransfer = TextTransfer.getInstance(); | 3322 TextTransfer plainTextTransfer = TextTransfer.getInstance(); |
3207 return clipboard.getContents(plainTextTransfer, clipboardType); | 3323 return clipboard.getContents(plainTextTransfer, clipboardType); |
3208 } | 3324 } |
3209 int getClusterNext(int offset, int lineIndex) { | 3325 int getClusterNext(int offset, int lineIndex) { |
3210 int lineOffset = content.getOffsetAtLine(lineIndex); | 3326 int lineOffset = content.getOffsetAtLine(lineIndex); |
3211 TextLayout layout = renderer.getTextLayout(lineIndex); | 3327 TextLayout layout = renderer.getTextLayout(lineIndex); |
3212 offset -= lineOffset; | 3328 offset -= lineOffset; |
3213 offset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); | 3329 offset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); |
3214 offset += lineOffset; | 3330 offset += lineOffset; |
3215 renderer.disposeTextLayout(layout); | 3331 renderer.disposeTextLayout(layout); |
3216 return offset; | 3332 return offset; |
3217 } | 3333 } |
3218 int getClusterPrevious(int offset, int lineIndex) { | 3334 int getClusterPrevious(int offset, int lineIndex) { |
3219 int lineOffset = content.getOffsetAtLine(lineIndex); | 3335 int lineOffset = content.getOffsetAtLine(lineIndex); |
3220 TextLayout layout = renderer.getTextLayout(lineIndex); | 3336 TextLayout layout = renderer.getTextLayout(lineIndex); |
3221 offset -= lineOffset; | 3337 offset -= lineOffset; |
3222 offset = layout.getPreviousOffset(offset, DWT.MOVEMENT_CLUSTER); | 3338 offset = layout.getPreviousOffset(offset, DWT.MOVEMENT_CLUSTER); |
3223 offset += lineOffset; | 3339 offset += lineOffset; |
3224 renderer.disposeTextLayout(layout); | 3340 renderer.disposeTextLayout(layout); |
3225 return offset; | 3341 return offset; |
3226 } | 3342 } |
3227 /** | 3343 /** |
3228 * Returns the content implementation that is used for text storage. | 3344 * Returns the content implementation that is used for text storage. |
3229 * | 3345 * |
3230 * @return content the user defined content implementation that is used for | 3346 * @return content the user defined content implementation that is used for |
3231 * text storage or the default content implementation if no user defined | 3347 * text storage or the default content implementation if no user defined |
3232 * content implementation has been set. | 3348 * content implementation has been set. |
3233 * @exception DWTException <ul> | 3349 * @exception DWTException <ul> |
3234 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3350 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3235 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3351 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3236 * </ul> | 3352 * </ul> |
3237 */ | 3353 */ |
3238 public StyledTextContent getContent() { | 3354 public StyledTextContent getContent() { |
3239 checkWidget(); | 3355 checkWidget(); |
3240 return content; | 3356 return content; |
3241 } | 3357 } |
3242 public bool getDragDetect () { | 3358 public override bool getDragDetect () { |
3243 checkWidget (); | 3359 checkWidget (); |
3244 return dragDetect; | 3360 return dragDetect_; |
3245 } | 3361 } |
3246 /** | 3362 /** |
3247 * Returns whether the widget : double click mouse behavior. | 3363 * Returns whether the widget implements double click mouse behavior. |
3248 * | 3364 * |
3249 * @return true if double clicking a word selects the word, false if double clicks | 3365 * @return true if double clicking a word selects the word, false if double clicks |
3250 * have the same effect as regular mouse clicks | 3366 * have the same effect as regular mouse clicks |
3251 * @exception DWTException <ul> | 3367 * @exception DWTException <ul> |
3252 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3368 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3268 */ | 3384 */ |
3269 public bool getEditable() { | 3385 public bool getEditable() { |
3270 checkWidget(); | 3386 checkWidget(); |
3271 return editable; | 3387 return editable; |
3272 } | 3388 } |
3273 public Color getForeground() { | 3389 public override Color getForeground() { |
3274 checkWidget(); | 3390 checkWidget(); |
3275 if (foreground is null) { | 3391 if (foreground is null) { |
3276 return getDisplay().getSystemColor(DWT.COLOR_LIST_FOREGROUND); | 3392 return getDisplay().getSystemColor(DWT.COLOR_LIST_FOREGROUND); |
3277 } | 3393 } |
3278 return foreground; | 3394 return foreground; |
3279 } | 3395 } |
3280 /** | 3396 /** |
3281 * Returns the horizontal scroll increment. | 3397 * Returns the horizontal scroll increment. |
3282 * | 3398 * |
3283 * @return horizontal scroll increment. | 3399 * @return horizontal scroll increment. |
3284 */ | 3400 */ |
3285 int getHorizontalIncrement() { | 3401 int getHorizontalIncrement() { |
3286 return renderer.averageCharWidth; | 3402 return renderer.averageCharWidth; |
3287 } | 3403 } |
3288 /** | 3404 /** |
3289 * Returns the horizontal scroll offset relative to the start of the line. | 3405 * Returns the horizontal scroll offset relative to the start of the line. |
3290 * | 3406 * |
3291 * @return horizontal scroll offset relative to the start of the line, | 3407 * @return horizontal scroll offset relative to the start of the line, |
3292 * measured in character increments starting at 0, if > 0 the content is scrolled | 3408 * measured in character increments starting at 0, if > 0 the content is scrolled |
3293 * @exception DWTException <ul> | 3409 * @exception DWTException <ul> |
3297 */ | 3413 */ |
3298 public int getHorizontalIndex() { | 3414 public int getHorizontalIndex() { |
3299 checkWidget(); | 3415 checkWidget(); |
3300 return horizontalScrollOffset / getHorizontalIncrement(); | 3416 return horizontalScrollOffset / getHorizontalIncrement(); |
3301 } | 3417 } |
3302 /** | 3418 /** |
3303 * Returns the horizontal scroll offset relative to the start of the line. | 3419 * Returns the horizontal scroll offset relative to the start of the line. |
3304 * | 3420 * |
3305 * @return the horizontal scroll offset relative to the start of the line, | 3421 * @return the horizontal scroll offset relative to the start of the line, |
3306 * measured in pixel starting at 0, if > 0 the content is scrolled. | 3422 * measured in pixel starting at 0, if > 0 the content is scrolled. |
3307 * @exception DWTException <ul> | 3423 * @exception DWTException <ul> |
3313 checkWidget(); | 3429 checkWidget(); |
3314 return horizontalScrollOffset; | 3430 return horizontalScrollOffset; |
3315 } | 3431 } |
3316 /** | 3432 /** |
3317 * Returns the line indentation of the widget. | 3433 * Returns the line indentation of the widget. |
3318 * | 3434 * |
3319 * @return the line indentation | 3435 * @return the line indentation |
3320 * | 3436 * |
3321 * @exception DWTException <ul> | 3437 * @exception DWTException <ul> |
3322 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3438 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3323 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3439 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3324 * </ul> | 3440 * </ul> |
3325 * | 3441 * |
3326 * @see #getLineIndent(int) | 3442 * @see #getLineIndent(int) |
3327 * | 3443 * |
3328 * @since 3.2 | 3444 * @since 3.2 |
3329 */ | 3445 */ |
3330 public int getIndent() { | 3446 public int getIndent() { |
3331 checkWidget(); | 3447 checkWidget(); |
3332 return indent; | 3448 return indent; |
3333 } | 3449 } |
3334 /** | 3450 /** |
3335 * Returns whether the widget justifies lines. | 3451 * Returns whether the widget justifies lines. |
3336 * | 3452 * |
3337 * @return whether lines are justified | 3453 * @return whether lines are justified |
3338 * | 3454 * |
3339 * @exception DWTException <ul> | 3455 * @exception DWTException <ul> |
3340 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3456 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3341 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3457 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3342 * </ul> | 3458 * </ul> |
3343 * | 3459 * |
3344 * @see #getLineJustify(int) | 3460 * @see #getLineJustify(int) |
3345 * | 3461 * |
3346 * @since 3.2 | 3462 * @since 3.2 |
3347 */ | 3463 */ |
3348 public bool getJustify() { | 3464 public bool getJustify() { |
3349 checkWidget(); | 3465 checkWidget(); |
3350 return justify; | 3466 return justify; |
3351 } | 3467 } |
3352 /** | 3468 /** |
3353 * Returns the action assigned to the key. | 3469 * Returns the action assigned to the key. |
3354 * Returns DWT.NULL if there is no action associated with the key. | 3470 * Returns DWT.NULL if there is no action associated with the key. |
3355 * | 3471 * |
3356 * @param key a key code defined in DWT.java or a character. | 3472 * @param key a key code defined in DWT.java or a character. |
3357 * Optionally ORd with a state mask. Preferred state masks are one or more of | 3473 * Optionally ORd with a state mask. Preferred state masks are one or more of |
3358 * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform | 3474 * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform |
3359 * differences. However, there may be cases where using the specific state masks | 3475 * differences. However, there may be cases where using the specific state masks |
3360 * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. | 3476 * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. |
3361 * @return one of the predefined actions defined in ST.java or DWT.NULL | 3477 * @return one of the predefined actions defined in ST.java or DWT.NULL |
3362 * if there is no action associated with the key. | 3478 * if there is no action associated with the key. |
3363 * @exception DWTException <ul> | 3479 * @exception DWTException <ul> |
3364 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3480 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3365 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3481 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3366 * </ul> | 3482 * </ul> |
3367 */ | 3483 */ |
3368 public int getKeyBinding(int key) { | 3484 public int getKeyBinding(int key) { |
3369 checkWidget(); | 3485 checkWidget(); |
3370 Integer action = cast(Integer) keyActionMap.get(new Integer(key)); | 3486 if( auto p = key in keyActionMap ){ |
3371 return action is null ? DWT.NULL : action.intValue(); | 3487 return *p; |
3488 } | |
3489 return DWT.NULL; | |
3372 } | 3490 } |
3373 /** | 3491 /** |
3374 * Gets the number of characters. | 3492 * Gets the number of characters. |
3375 * | 3493 * |
3376 * @return number of characters in the widget | 3494 * @return number of characters in the widget |
3384 return content.getCharCount(); | 3502 return content.getCharCount(); |
3385 } | 3503 } |
3386 /** | 3504 /** |
3387 * Returns the line at the given line index without delimiters. | 3505 * Returns the line at the given line index without delimiters. |
3388 * Index 0 is the first line of the content. When there are not | 3506 * Index 0 is the first line of the content. When there are not |
3389 * any lines, getLine(0) is a valid call that answers an empty String. | 3507 * any lines, getLine(0) is a valid call that answers an empty string. |
3390 * <p> | 3508 * <p> |
3391 * | 3509 * |
3392 * @param lineIndex index of the line to return. | 3510 * @param lineIndex index of the line to return. |
3393 * @return the line text without delimiters | 3511 * @return the line text without delimiters |
3394 * | 3512 * |
3395 * @exception DWTException <ul> | 3513 * @exception DWTException <ul> |
3396 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3514 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3397 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3515 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3398 * </ul> | 3516 * </ul> |
3399 * @exception IllegalArgumentException <ul> | 3517 * @exception IllegalArgumentException <ul> |
3400 * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> | 3518 * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> |
3401 * </ul> | 3519 * </ul> |
3402 * @since 3.4 | 3520 * @since 3.4 |
3403 */ | 3521 */ |
3404 public String getLine(int lineIndex) { | 3522 public String getLine(int lineIndex) { |
3405 checkWidget(); | 3523 checkWidget(); |
3406 if (lineIndex < 0 || | 3524 if (lineIndex < 0 || |
3407 (lineIndex > 0 && lineIndex >= content.getLineCount())) { | 3525 (lineIndex > 0 && lineIndex >= content.getLineCount())) { |
3408 DWT.error(DWT.ERROR_INVALID_RANGE); | 3526 DWT.error(DWT.ERROR_INVALID_RANGE); |
3409 } | 3527 } |
3410 return content.getLine(lineIndex); | 3528 return content.getLine(lineIndex); |
3411 } | 3529 } |
3412 /** | 3530 /** |
3413 * Returns the alignment of the line at the given index. | 3531 * Returns the alignment of the line at the given index. |
3414 * | 3532 * |
3415 * @param index the index of the line | 3533 * @param index the index of the line |
3416 * | 3534 * |
3417 * @return the line alignment | 3535 * @return the line alignment |
3418 * | 3536 * |
3419 * @exception DWTException <ul> | 3537 * @exception DWTException <ul> |
3420 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3538 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3421 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3539 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3422 * </ul> | 3540 * </ul> |
3423 * @exception IllegalArgumentException <ul> | 3541 * @exception IllegalArgumentException <ul> |
3424 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> | 3542 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> |
3425 * </ul> | 3543 * </ul> |
3426 * | 3544 * |
3427 * @see #getAlignment() | 3545 * @see #getAlignment() |
3428 * | 3546 * |
3429 * @since 3.2 | 3547 * @since 3.2 |
3430 */ | 3548 */ |
3431 public int getLineAlignment(int index) { | 3549 public int getLineAlignment(int index) { |
3432 checkWidget(); | 3550 checkWidget(); |
3433 if (index < 0 || index > content.getLineCount()) { | 3551 if (index < 0 || index > content.getLineCount()) { |
3438 /** | 3556 /** |
3439 * Returns the line at the specified offset in the text | 3557 * Returns the line at the specified offset in the text |
3440 * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) | 3558 * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) |
3441 * returns the line of the insert location. | 3559 * returns the line of the insert location. |
3442 * | 3560 * |
3443 * @param offset offset relative to the start of the content. | 3561 * @param offset offset relative to the start of the content. |
3444 * 0 <= offset <= getCharCount() | 3562 * 0 <= offset <= getCharCount() |
3445 * @return line at the specified offset in the text | 3563 * @return line at the specified offset in the text |
3446 * @exception DWTException <ul> | 3564 * @exception DWTException <ul> |
3447 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3565 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3448 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3566 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3449 * </ul> | 3567 * </ul> |
3450 * @exception IllegalArgumentException <ul> | 3568 * @exception IllegalArgumentException <ul> |
3451 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> | 3569 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3452 * </ul> | 3570 * </ul> |
3453 */ | 3571 */ |
3454 public int getLineAtOffset(int offset) { | 3572 public int getLineAtOffset(int offset) { |
3455 checkWidget(); | 3573 checkWidget(); |
3456 if (offset < 0 || offset > getCharCount()) { | 3574 if (offset < 0 || offset > getCharCount()) { |
3457 DWT.error(DWT.ERROR_INVALID_RANGE); | 3575 DWT.error(DWT.ERROR_INVALID_RANGE); |
3458 } | 3576 } |
3459 return content.getLineAtOffset(offset); | 3577 return content.getLineAtOffset(offset); |
3460 } | 3578 } |
3461 /** | 3579 /** |
3462 * Returns the background color of the line at the given index. | 3580 * Returns the background color of the line at the given index. |
3463 * Returns null if a LineBackgroundListener has been set or if no background | 3581 * Returns null if a LineBackgroundListener has been set or if no background |
3464 * color has been specified for the line. Should not be called if a | 3582 * color has been specified for the line. Should not be called if a |
3465 * LineBackgroundListener has been set since the listener maintains the | 3583 * LineBackgroundListener has been set since the listener maintains the |
3466 * line background colors. | 3584 * line background colors. |
3467 * | 3585 * |
3468 * @param index the index of the line | 3586 * @param index the index of the line |
3469 * @return the background color of the line at the given index. | 3587 * @return the background color of the line at the given index. |
3470 * | 3588 * |
3471 * @exception DWTException <ul> | 3589 * @exception DWTException <ul> |
3472 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3590 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3473 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3591 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3474 * </ul> | 3592 * </ul> |
3475 * @exception IllegalArgumentException <ul> | 3593 * @exception IllegalArgumentException <ul> |
3483 } | 3601 } |
3484 return isListening(LineGetBackground) ? null : renderer.getLineBackground(index, null); | 3602 return isListening(LineGetBackground) ? null : renderer.getLineBackground(index, null); |
3485 } | 3603 } |
3486 /** | 3604 /** |
3487 * Returns the bullet of the line at the given index. | 3605 * Returns the bullet of the line at the given index. |
3488 * | 3606 * |
3489 * @param index the index of the line | 3607 * @param index the index of the line |
3490 * | 3608 * |
3491 * @return the line bullet | 3609 * @return the line bullet |
3492 * | 3610 * |
3493 * @exception DWTException <ul> | 3611 * @exception DWTException <ul> |
3494 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3612 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3495 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3613 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3496 * </ul> | 3614 * </ul> |
3497 * @exception IllegalArgumentException <ul> | 3615 * @exception IllegalArgumentException <ul> |
3498 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> | 3616 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> |
3499 * </ul> | 3617 * </ul> |
3500 * | 3618 * |
3501 * @since 3.2 | 3619 * @since 3.2 |
3502 */ | 3620 */ |
3503 public Bullet getLineBullet(int index) { | 3621 public Bullet getLineBullet(int index) { |
3504 checkWidget(); | 3622 checkWidget(); |
3505 if (index < 0 || index > content.getLineCount()) { | 3623 if (index < 0 || index > content.getLineCount()) { |
3506 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 3624 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
3507 } | 3625 } |
3508 return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null); | 3626 return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null); |
3509 } | 3627 } |
3510 /** | 3628 /** |
3511 * Returns the line background data for the given line or null if | 3629 * Returns the line background data for the given line or null if |
3512 * there is none. | 3630 * there is none. |
3513 * | 3631 * |
3514 * @param lineOffset offset of the line start relative to the start | 3632 * @param lineOffset offset of the line start relative to the start |
3515 * of the content. | 3633 * of the content. |
3516 * @param line line to get line background data for | 3634 * @param line line to get line background data for |
3517 * @return line background data for the given line. | 3635 * @return line background data for the given line. |
3518 */ | 3636 */ |
3519 StyledTextEvent getLineBackgroundData(int lineOffset, String line) { | 3637 StyledTextEvent getLineBackgroundData(int lineOffset, String line) { |
3520 return sendLineEvent(LineGetBackground, lineOffset, line); | 3638 return sendLineEvent(LineGetBackground, lineOffset, line); |
3521 } | 3639 } |
3522 /** | 3640 /** |
3523 * Gets the number of text lines. | 3641 * Gets the number of text lines. |
3524 * | 3642 * |
3525 * @return the number of lines in the widget | 3643 * @return the number of lines in the widget |
3526 * @exception DWTException <ul> | 3644 * @exception DWTException <ul> |
3527 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3645 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3531 public int getLineCount() { | 3649 public int getLineCount() { |
3532 checkWidget(); | 3650 checkWidget(); |
3533 return content.getLineCount(); | 3651 return content.getLineCount(); |
3534 } | 3652 } |
3535 /** | 3653 /** |
3536 * Returns the number of lines that can be completely displayed in the | 3654 * Returns the number of lines that can be completely displayed in the |
3537 * widget client area. | 3655 * widget client area. |
3538 * | 3656 * |
3539 * @return number of lines that can be completely displayed in the widget | 3657 * @return number of lines that can be completely displayed in the widget |
3540 * client area. | 3658 * client area. |
3541 */ | 3659 */ |
3542 int getLineCountWhole() { | 3660 int getLineCountWhole() { |
3543 if (isFixedLineHeight()) { | 3661 if (isFixedLineHeight()) { |
3544 int lineHeight = renderer.getLineHeight(); | 3662 int lineHeight = renderer.getLineHeight(); |
3562 return content.getLineDelimiter(); | 3680 return content.getLineDelimiter(); |
3563 } | 3681 } |
3564 /** | 3682 /** |
3565 * Returns the line height. | 3683 * Returns the line height. |
3566 * <p> | 3684 * <p> |
3567 * Note: this API should not be used if a StyleRange attribute causes lines to | 3685 * Note: this API should not be used if a StyleRange attribute causes lines to |
3568 * have different heights (i.e. different fonts, rise, etc). | 3686 * have different heights (i.e. different fonts, rise, etc). |
3569 * </p> | 3687 * </p> |
3570 * | 3688 * |
3571 * @return line height in pixel. | 3689 * @return line height in pixel. |
3572 * @exception DWTException <ul> | 3690 * @exception DWTException <ul> |
3581 } | 3699 } |
3582 /** | 3700 /** |
3583 * Returns the line height at the given offset. | 3701 * Returns the line height at the given offset. |
3584 * | 3702 * |
3585 * @param offset the offset | 3703 * @param offset the offset |
3586 * | 3704 * |
3587 * @return line height in pixels | 3705 * @return line height in pixels |
3588 * | 3706 * |
3589 * @exception DWTException <ul> | 3707 * @exception DWTException <ul> |
3590 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3708 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3591 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3709 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3592 * </ul> | 3710 * </ul> |
3593 * @exception IllegalArgumentException <ul> | 3711 * @exception IllegalArgumentException <ul> |
3594 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> | 3712 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3595 * </ul> | 3713 * </ul> |
3596 * | 3714 * |
3597 * @since 3.2 | 3715 * @since 3.2 |
3598 */ | 3716 */ |
3599 public int getLineHeight(int offset) { | 3717 public int getLineHeight(int offset) { |
3600 checkWidget(); | 3718 checkWidget(); |
3601 if (!(0 <= offset && offset <= content.getCharCount())) { | 3719 if (!(0 <= offset && offset <= content.getCharCount())) { |
3605 return renderer.getLineHeight(); | 3723 return renderer.getLineHeight(); |
3606 } | 3724 } |
3607 int lineIndex = content.getLineAtOffset(offset); | 3725 int lineIndex = content.getLineAtOffset(offset); |
3608 int lineOffset = content.getOffsetAtLine(lineIndex); | 3726 int lineOffset = content.getOffsetAtLine(lineIndex); |
3609 TextLayout layout = renderer.getTextLayout(lineIndex); | 3727 TextLayout layout = renderer.getTextLayout(lineIndex); |
3610 int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); | 3728 int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); |
3611 int height = layout.getLineBounds(lineInParagraph).height; | 3729 int height = layout.getLineBounds(lineInParagraph).height; |
3612 renderer.disposeTextLayout(layout); | 3730 renderer.disposeTextLayout(layout); |
3613 return height; | 3731 return height; |
3614 } | 3732 } |
3615 /** | 3733 /** |
3616 * Returns the indentation of the line at the given index. | 3734 * Returns the indentation of the line at the given index. |
3617 * | 3735 * |
3618 * @param index the index of the line | 3736 * @param index the index of the line |
3619 * | 3737 * |
3620 * @return the line indentation | 3738 * @return the line indentation |
3621 * | 3739 * |
3622 * @exception DWTException <ul> | 3740 * @exception DWTException <ul> |
3623 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3741 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3624 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3742 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3625 * </ul> | 3743 * </ul> |
3626 * @exception IllegalArgumentException <ul> | 3744 * @exception IllegalArgumentException <ul> |
3627 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> | 3745 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> |
3628 * </ul> | 3746 * </ul> |
3629 * | 3747 * |
3630 * @see #getIndent() | 3748 * @see #getIndent() |
3631 * | 3749 * |
3632 * @since 3.2 | 3750 * @since 3.2 |
3633 */ | 3751 */ |
3634 public int getLineIndent(int index) { | 3752 public int getLineIndent(int index) { |
3635 checkWidget(); | 3753 checkWidget(); |
3636 if (index < 0 || index > content.getLineCount()) { | 3754 if (index < 0 || index > content.getLineCount()) { |
3638 } | 3756 } |
3639 return isListening(LineGetStyle) ? 0 : renderer.getLineIndent(index, indent); | 3757 return isListening(LineGetStyle) ? 0 : renderer.getLineIndent(index, indent); |
3640 } | 3758 } |
3641 /** | 3759 /** |
3642 * Returns whether the line at the given index is justified. | 3760 * Returns whether the line at the given index is justified. |
3643 * | 3761 * |
3644 * @param index the index of the line | 3762 * @param index the index of the line |
3645 * | 3763 * |
3646 * @return whether the line is justified | 3764 * @return whether the line is justified |
3647 * | 3765 * |
3648 * @exception DWTException <ul> | 3766 * @exception DWTException <ul> |
3649 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3767 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3650 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3768 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3651 * </ul> | 3769 * </ul> |
3652 * @exception IllegalArgumentException <ul> | 3770 * @exception IllegalArgumentException <ul> |
3653 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> | 3771 * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> |
3654 * </ul> | 3772 * </ul> |
3655 * | 3773 * |
3656 * @see #getJustify() | 3774 * @see #getJustify() |
3657 * | 3775 * |
3658 * @since 3.2 | 3776 * @since 3.2 |
3659 */ | 3777 */ |
3660 public bool getLineJustify(int index) { | 3778 public bool getLineJustify(int index) { |
3661 checkWidget(); | 3779 checkWidget(); |
3662 if (index < 0 || index > content.getLineCount()) { | 3780 if (index < 0 || index > content.getLineCount()) { |
3663 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 3781 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
3664 } | 3782 } |
3665 return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); | 3783 return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); |
3666 } | 3784 } |
3667 /** | 3785 /** |
3668 * Returns the line spacing of the widget. | 3786 * Returns the line spacing of the widget. |
3669 * | 3787 * |
3670 * @return the line spacing | 3788 * @return the line spacing |
3671 * | 3789 * |
3672 * @exception DWTException <ul> | 3790 * @exception DWTException <ul> |
3673 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3791 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3674 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3792 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3675 * </ul> | 3793 * </ul> |
3676 * | 3794 * |
3677 * @since 3.2 | 3795 * @since 3.2 |
3678 */ | 3796 */ |
3679 public int getLineSpacing() { | 3797 public int getLineSpacing() { |
3680 checkWidget(); | 3798 checkWidget(); |
3681 return lineSpacing; | 3799 return lineSpacing; |
3682 } | 3800 } |
3683 /** | 3801 /** |
3684 * Returns the line style data for the given line or null if there is | 3802 * Returns the line style data for the given line or null if there is |
3685 * none. | 3803 * none. |
3686 * <p> | 3804 * <p> |
3687 * If there is a LineStyleListener but it does not set any styles, | 3805 * If there is a LineStyleListener but it does not set any styles, |
3688 * the StyledTextEvent.styles field will be initialized to an empty | 3806 * the StyledTextEvent.styles field will be initialized to an empty |
3689 * array. | 3807 * array. |
3690 * </p> | 3808 * </p> |
3691 * | 3809 * |
3692 * @param lineOffset offset of the line start relative to the start of | 3810 * @param lineOffset offset of the line start relative to the start of |
3693 * the content. | 3811 * the content. |
3694 * @param line line to get line styles for | 3812 * @param line line to get line styles for |
3695 * @return line style data for the given line. Styles may start before | 3813 * @return line style data for the given line. Styles may start before |
3696 * line start and end after line end | 3814 * line start and end after line end |
3697 */ | 3815 */ |
3698 StyledTextEvent getLineStyleData(int lineOffset, String line) { | 3816 StyledTextEvent getLineStyleData(int lineOffset, String line) { |
3699 return sendLineEvent(LineGetStyle, lineOffset, line); | 3817 return sendLineEvent(LineGetStyle, lineOffset, line); |
3700 } | 3818 } |
3701 /** | 3819 /** |
3702 * Returns the top pixel, relative to the client area, of a given line. | 3820 * Returns the top pixel, relative to the client area, of a given line. |
3703 * Clamps out of ranges index. | 3821 * Clamps out of ranges index. |
3704 * | 3822 * |
3705 * @param lineIndex the line index, the max value is lineCount. If | 3823 * @param lineIndex the line index, the max value is lineCount. If |
3706 * lineIndex is lineCount it returns the bottom pixel of the last line. | 3824 * lineIndex is lineCount it returns the bottom pixel of the last line. |
3707 * It means this function can be used to retrieve the bottom pixel of any line. | 3825 * It means this function can be used to retrieve the bottom pixel of any line. |
3708 * | 3826 * |
3827 * @return the top pixel of a given line index | |
3828 * | |
3709 * @since 3.2 | 3829 * @since 3.2 |
3710 */ | 3830 */ |
3711 public int getLinePixel(int lineIndex) { | 3831 public int getLinePixel(int lineIndex) { |
3712 checkWidget(); | 3832 checkWidget(); |
3713 int lineCount = content.getLineCount(); | 3833 int lineCount = content.getLineCount(); |
3730 return height + topMargin; | 3850 return height + topMargin; |
3731 } | 3851 } |
3732 /** | 3852 /** |
3733 * Returns the line index for a y, relative to the client area. | 3853 * Returns the line index for a y, relative to the client area. |
3734 * The line index returned is always in the range 0..lineCount - 1. | 3854 * The line index returned is always in the range 0..lineCount - 1. |
3855 * | |
3856 * @param y the y-coordinate pixel | |
3857 * | |
3858 * @return the line index for a given y-coordinate pixel | |
3735 * | 3859 * |
3736 * @since 3.2 | 3860 * @since 3.2 |
3737 */ | 3861 */ |
3738 public int getLineIndex(int y) { | 3862 public int getLineIndex(int y) { |
3739 checkWidget(); | 3863 checkWidget(); |
3760 } | 3884 } |
3761 } | 3885 } |
3762 return line; | 3886 return line; |
3763 } | 3887 } |
3764 /** | 3888 /** |
3765 * Returns the x, y location of the upper left corner of the character | 3889 * Returns the x, y location of the upper left corner of the character |
3766 * bounding box at the specified offset in the text. The point is | 3890 * bounding box at the specified offset in the text. The point is |
3767 * relative to the upper left corner of the widget client area. | 3891 * relative to the upper left corner of the widget client area. |
3768 * | 3892 * |
3769 * @param offset offset relative to the start of the content. | 3893 * @param offset offset relative to the start of the content. |
3770 * 0 <= offset <= getCharCount() | 3894 * 0 <= offset <= getCharCount() |
3771 * @return x, y location of the upper left corner of the character | 3895 * @return x, y location of the upper left corner of the character |
3772 * bounding box at the specified offset in the text. | 3896 * bounding box at the specified offset in the text. |
3773 * @exception DWTException <ul> | 3897 * @exception DWTException <ul> |
3774 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3898 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3775 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3899 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3776 * </ul> | 3900 * </ul> |
3777 * @exception IllegalArgumentException <ul> | 3901 * @exception IllegalArgumentException <ul> |
3778 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> | 3902 * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3779 * </ul> | 3903 * </ul> |
3780 */ | 3904 */ |
3781 public Point getLocationAtOffset(int offset) { | 3905 public Point getLocationAtOffset(int offset) { |
3782 checkWidget(); | 3906 checkWidget(); |
3783 if (offset < 0 || offset > getCharCount()) { | 3907 if (offset < 0 || offset > getCharCount()) { |
3784 DWT.error(DWT.ERROR_INVALID_RANGE); | 3908 DWT.error(DWT.ERROR_INVALID_RANGE); |
3785 } | 3909 } |
3786 return getPointAtOffset(offset); | 3910 return getPointAtOffset(offset); |
3787 } | 3911 } |
3788 /** | 3912 /** |
3789 * Returns the character offset of the first character of the given line. | 3913 * Returns the character offset of the first character of the given line. |
3790 * | 3914 * |
3791 * @param lineIndex index of the line, 0 based relative to the first | 3915 * @param lineIndex index of the line, 0 based relative to the first |
3792 * line in the content. 0 <= lineIndex < getLineCount(), except | 3916 * line in the content. 0 <= lineIndex < getLineCount(), except |
3793 * lineIndex may always be 0 | 3917 * lineIndex may always be 0 |
3794 * @return offset offset of the first character of the line, relative to | 3918 * @return offset offset of the first character of the line, relative to |
3795 * the beginning of the document. The first character of the document is | 3919 * the beginning of the document. The first character of the document is |
3796 * at offset 0. | 3920 * at offset 0. |
3797 * When there are not any lines, getOffsetAtLine(0) is a valid call that | 3921 * When there are not any lines, getOffsetAtLine(0) is a valid call that |
3798 * answers 0. | 3922 * answers 0. |
3799 * @exception DWTException <ul> | 3923 * @exception DWTException <ul> |
3800 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3924 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3801 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3925 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3802 * </ul> | 3926 * </ul> |
3803 * @exception IllegalArgumentException <ul> | 3927 * @exception IllegalArgumentException <ul> |
3804 * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> | 3928 * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> |
3805 * </ul> | 3929 * </ul> |
3806 * @since 2.0 | 3930 * @since 2.0 |
3807 */ | 3931 */ |
3808 public int getOffsetAtLine(int lineIndex) { | 3932 public int getOffsetAtLine(int lineIndex) { |
3809 checkWidget(); | 3933 checkWidget(); |
3810 if (lineIndex < 0 || | 3934 if (lineIndex < 0 || |
3811 (lineIndex > 0 && lineIndex >= content.getLineCount())) { | 3935 (lineIndex > 0 && lineIndex >= content.getLineCount())) { |
3812 DWT.error(DWT.ERROR_INVALID_RANGE); | 3936 DWT.error(DWT.ERROR_INVALID_RANGE); |
3813 } | 3937 } |
3814 return content.getOffsetAtLine(lineIndex); | 3938 return content.getOffsetAtLine(lineIndex); |
3815 } | 3939 } |
3816 /** | 3940 /** |
3817 * Returns the offset of the character at the given location relative | 3941 * Returns the offset of the character at the given location relative |
3818 * to the first character in the document. | 3942 * to the first character in the document. |
3819 * <p> | 3943 * <p> |
3820 * The return value reflects the character offset that the caret will | 3944 * The return value reflects the character offset that the caret will |
3821 * be placed at if a mouse click occurred at the specified location. | 3945 * be placed at if a mouse click occurred at the specified location. |
3822 * If the x coordinate of the location is beyond the center of a character | 3946 * If the x coordinate of the location is beyond the center of a character |
3823 * the returned offset will be behind the character. | 3947 * the returned offset will be behind the character. |
3824 * </p> | 3948 * </p> |
3825 * | 3949 * |
3826 * @param point the origin of character bounding box relative to | 3950 * @param point the origin of character bounding box relative to |
3827 * the origin of the widget client area. | 3951 * the origin of the widget client area. |
3828 * @return offset of the character at the given location relative | 3952 * @return offset of the character at the given location relative |
3829 * to the first character in the document. | 3953 * to the first character in the document. |
3830 * @exception DWTException <ul> | 3954 * @exception DWTException <ul> |
3831 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 3955 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3832 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 3956 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3833 * </ul> | 3957 * </ul> |
3862 * relative to the beginning of the document | 3986 * relative to the beginning of the document |
3863 */ | 3987 */ |
3864 int getOffsetAtPoint(int x, int y, int lineIndex) { | 3988 int getOffsetAtPoint(int x, int y, int lineIndex) { |
3865 TextLayout layout = renderer.getTextLayout(lineIndex); | 3989 TextLayout layout = renderer.getTextLayout(lineIndex); |
3866 x += horizontalScrollOffset - leftMargin; | 3990 x += horizontalScrollOffset - leftMargin; |
3867 int[] trailing = new int[1]; | 3991 int[1] trailing; |
3868 int offsetInLine = layout.getOffset(x, y, trailing); | 3992 int offsetInLine = layout.getOffset(x, y, trailing); |
3869 caretAlignment = OFFSET_LEADING; | 3993 caretAlignment = OFFSET_LEADING; |
3870 if (trailing[0] !is 0) { | 3994 if (trailing[0] !is 0) { |
3871 int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); | 3995 int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); |
3872 int lineStart = layout.getLineOffsets()[lineInParagraph]; | 3996 int lineStart = layout.getLineOffsets()[lineInParagraph]; |
3873 if (offsetInLine + trailing[0] is lineStart) { | 3997 if (offsetInLine + trailing[0] is lineStart) { |
3874 offsetInLine += trailing[0]; | 3998 offsetInLine += trailing[0]; |
3875 caretAlignment = PREVIOUS_OFFSET_TRAILING; | 3999 caretAlignment = PREVIOUS_OFFSET_TRAILING; |
3876 } else { | 4000 } else { |
3877 String line = content.getLine(lineIndex); | 4001 String line = content.getLine(lineIndex); |
3878 int level; | 4002 int level; |
3879 int offset = offsetInLine; | 4003 int offset = offsetInLine; |
3880 while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; | 4004 while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; |
3881 if (offset is 0 && Character.isDigit(line.charAt(offset))) { | 4005 if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { |
3882 level = isMirrored() ? 1 : 0; | 4006 level = isMirrored() ? 1 : 0; |
3883 } else { | 4007 } else { |
3884 level = layout.getLevel(offset) & 0x1; | 4008 level = layout.getLevel(offset) & 0x1; |
3885 } | 4009 } |
3886 offsetInLine += trailing[0]; | 4010 offsetInLine += trailing[0]; |
3904 if (inTextOnly && y > height) { | 4028 if (inTextOnly && y > height) { |
3905 return -1; | 4029 return -1; |
3906 } | 4030 } |
3907 int lineIndex = getLineIndex(y); | 4031 int lineIndex = getLineIndex(y); |
3908 int lineOffset = content.getOffsetAtLine(lineIndex); | 4032 int lineOffset = content.getOffsetAtLine(lineIndex); |
3909 TextLayout layout = renderer.getTextLayout(lineIndex); | 4033 TextLayout layout = renderer.getTextLayout(lineIndex); |
3910 x += horizontalScrollOffset - leftMargin ; | 4034 x += horizontalScrollOffset - leftMargin ; |
3911 y -= getLinePixel(lineIndex); | 4035 y -= getLinePixel(lineIndex); |
3912 int offset = layout.getOffset(x, y, trailing); | 4036 int offset = layout.getOffset(x, y, trailing); |
3913 Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset)); | 4037 Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset)); |
3914 renderer.disposeTextLayout(layout); | 4038 renderer.disposeTextLayout(layout); |
3919 } | 4043 } |
3920 /** | 4044 /** |
3921 * Returns the orientation of the receiver. | 4045 * Returns the orientation of the receiver. |
3922 * | 4046 * |
3923 * @return the orientation style | 4047 * @return the orientation style |
3924 * | 4048 * |
3925 * @exception DWTException <ul> | 4049 * @exception DWTException <ul> |
3926 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4050 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3927 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4051 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3928 * </ul> | 4052 * </ul> |
3929 * | 4053 * |
3930 * @since 2.1.2 | 4054 * @since 2.1.2 |
3931 */ | 4055 */ |
3932 public int getOrientation () { | 4056 public int getOrientation () { |
3933 checkWidget(); | 4057 checkWidget(); |
3934 return isMirrored() ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; | 4058 return isMirrored() ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; |
3935 } | 4059 } |
3936 /** | 4060 /** |
3937 * Returns the index of the last partially visible line. | 4061 * Returns the index of the last partially visible line. |
3938 * | 4062 * |
3939 * @return index of the last partially visible line. | 4063 * @return index of the last partially visible line. |
3940 */ | 4064 */ |
3941 int getPartialBottomIndex() { | 4065 int getPartialBottomIndex() { |
3944 int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); | 4068 int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); |
3945 return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1); | 4069 return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1); |
3946 } | 4070 } |
3947 return getLineIndex(clientAreaHeight - bottomMargin); | 4071 return getLineIndex(clientAreaHeight - bottomMargin); |
3948 } | 4072 } |
3949 /** | 4073 /** |
3950 * Returns the index of the first partially visible line. | 4074 * Returns the index of the first partially visible line. |
3951 * | 4075 * |
3952 * @return index of the first partially visible line. | 4076 * @return index of the first partially visible line. |
3953 */ | 4077 */ |
3954 int getPartialTopIndex() { | 4078 int getPartialTopIndex() { |
3957 return getVerticalScrollOffset() / lineHeight; | 4081 return getVerticalScrollOffset() / lineHeight; |
3958 } | 4082 } |
3959 return topIndexY <= 0 ? topIndex : topIndex - 1; | 4083 return topIndexY <= 0 ? topIndex : topIndex - 1; |
3960 } | 4084 } |
3961 /** | 4085 /** |
3962 * Returns the content in the specified range using the platform line | 4086 * Returns the content in the specified range using the platform line |
3963 * delimiter to separate lines. | 4087 * delimiter to separate lines. |
3964 * | 4088 * |
3965 * @param writer the TextWriter to write line text into | 4089 * @param writer the TextWriter to write line text into |
3966 * @return the content in the specified range using the platform line | 4090 * @return the content in the specified range using the platform line |
3967 * delimiter to separate lines as written by the specified TextWriter. | 4091 * delimiter to separate lines as written by the specified TextWriter. |
3968 */ | 4092 */ |
3969 String getPlatformDelimitedText(TextWriter writer) { | 4093 String getPlatformDelimitedText(TextWriter writer) { |
3970 int end = writer.getStart() + writer.getCharCount(); | 4094 int end = writer.getStart() + writer.getCharCount(); |
3971 int startLine = content.getLineAtOffset(writer.getStart()); | 4095 int startLine = content.getLineAtOffset(writer.getStart()); |
3972 int endLine = content.getLineAtOffset(end); | 4096 int endLine = content.getLineAtOffset(end); |
3973 String endLineText = content.getLine(endLine); | 4097 String endLineText = content.getLine(endLine); |
3974 int endLineOffset = content.getOffsetAtLine(endLine); | 4098 int endLineOffset = content.getOffsetAtLine(endLine); |
3975 | 4099 |
3976 for (int i = startLine; i <= endLine; i++) { | 4100 for (int i = startLine; i <= endLine; i++) { |
3977 writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); | 4101 writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); |
3978 if (i < endLine) { | 4102 if (i < endLine) { |
3979 writer.writeLineDelimiter(PlatformLineDelimiter); | 4103 writer.writeLineDelimiter(PlatformLineDelimiter); |
3980 } | 4104 } |
3981 } | 4105 } |
3982 if (end > endLineOffset + endLineText.length()) { | 4106 if (end > endLineOffset + endLineText.length) { |
3983 writer.writeLineDelimiter(PlatformLineDelimiter); | 4107 writer.writeLineDelimiter(PlatformLineDelimiter); |
3984 } | 4108 } |
3985 writer.close(); | 4109 writer.close(); |
3986 return writer.toString(); | 4110 return writer.toString(); |
3987 } | 4111 } |
3988 /** | 4112 /** |
3989 * Returns all the ranges of text that have an associated StyleRange. | 4113 * Returns all the ranges of text that have an associated StyleRange. |
3990 * Returns an empty array if a LineStyleListener has been set. | 4114 * Returns an empty array if a LineStyleListener has been set. |
3991 * Should not be called if a LineStyleListener has been set since the | 4115 * Should not be called if a LineStyleListener has been set since the |
3992 * listener maintains the styles. | 4116 * listener maintains the styles. |
3993 * <p> | 4117 * <p> |
3994 * The ranges array contains start and length pairs. Each pair refers to | 4118 * The ranges array contains start and length pairs. Each pair refers to |
3995 * the corresponding style in the styles array. For example, the pair | 4119 * the corresponding style in the styles array. For example, the pair |
3996 * that starts at ranges[n] with length ranges[n+1] uses the style | 4120 * that starts at ranges[n] with length ranges[n+1] uses the style |
3997 * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>. | 4121 * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>. |
3998 * </p> | 4122 * </p> |
3999 * | 4123 * |
4000 * @return the ranges or an empty array if a LineStyleListener has been set. | 4124 * @return the ranges or an empty array if a LineStyleListener has been set. |
4001 * | 4125 * |
4002 * @exception DWTException <ul> | 4126 * @exception DWTException <ul> |
4003 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4127 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4004 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4128 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4005 * </ul> | 4129 * </ul> |
4006 * | 4130 * |
4007 * @since 3.2 | 4131 * @since 3.2 |
4008 * | 4132 * |
4009 * @see #getStyleRanges(bool) | 4133 * @see #getStyleRanges(bool) |
4010 */ | 4134 */ |
4011 public int[] getRanges() { | 4135 public int[] getRanges() { |
4012 checkWidget(); | 4136 checkWidget(); |
4013 if (!isListening(LineGetStyle)) { | 4137 if (!isListening(LineGetStyle)) { |
4016 } | 4140 } |
4017 return new int[0]; | 4141 return new int[0]; |
4018 } | 4142 } |
4019 /** | 4143 /** |
4020 * Returns the ranges of text that have an associated StyleRange. | 4144 * Returns the ranges of text that have an associated StyleRange. |
4021 * Returns an empty array if a LineStyleListener has been set. | 4145 * Returns an empty array if a LineStyleListener has been set. |
4022 * Should not be called if a LineStyleListener has been set since the | 4146 * Should not be called if a LineStyleListener has been set since the |
4023 * listener maintains the styles. | 4147 * listener maintains the styles. |
4024 * <p> | 4148 * <p> |
4025 * The ranges array contains start and length pairs. Each pair refers to | 4149 * The ranges array contains start and length pairs. Each pair refers to |
4026 * the corresponding style in the styles array. For example, the pair | 4150 * the corresponding style in the styles array. For example, the pair |
4027 * that starts at ranges[n] with length ranges[n+1] uses the style | 4151 * that starts at ranges[n] with length ranges[n+1] uses the style |
4028 * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>. | 4152 * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>. |
4029 * </p> | 4153 * </p> |
4030 * | 4154 * |
4031 * @param start the start offset of the style ranges to return | 4155 * @param start the start offset of the style ranges to return |
4032 * @param length the number of style ranges to return | 4156 * @param length the number of style ranges to return |
4033 * | 4157 * |
4034 * @return the ranges or an empty array if a LineStyleListener has been set. | 4158 * @return the ranges or an empty array if a LineStyleListener has been set. |
4035 * | 4159 * |
4036 * @exception DWTException <ul> | 4160 * @exception DWTException <ul> |
4037 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4161 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4038 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4162 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4039 * </ul> | 4163 * </ul> |
4040 * @exception IllegalArgumentException <ul> | 4164 * @exception IllegalArgumentException <ul> |
4041 * <li>ERROR_INVALID_RANGE if start or length are outside the widget content</li> | 4165 * <li>ERROR_INVALID_RANGE if start or length are outside the widget content</li> |
4042 * </ul> | 4166 * </ul> |
4043 * | 4167 * |
4044 * @since 3.2 | 4168 * @since 3.2 |
4045 * | 4169 * |
4046 * @see #getStyleRanges(int, int, bool) | 4170 * @see #getStyleRanges(int, int, bool) |
4047 */ | 4171 */ |
4048 public int[] getRanges(int start, int length) { | 4172 public int[] getRanges(int start, int length) { |
4049 checkWidget(); | 4173 checkWidget(); |
4050 int contentLength = getCharCount(); | 4174 int contentLength = getCharCount(); |
4060 } | 4184 } |
4061 /** | 4185 /** |
4062 * Returns the selection. | 4186 * Returns the selection. |
4063 * <p> | 4187 * <p> |
4064 * Text selections are specified in terms of caret positions. In a text | 4188 * Text selections are specified in terms of caret positions. In a text |
4065 * widget that contains N characters, there are N+1 caret positions, | 4189 * widget that contains N characters, there are N+1 caret positions, |
4066 * ranging from 0..N | 4190 * ranging from 0..N |
4067 * </p> | 4191 * </p> |
4068 * | 4192 * |
4069 * @return start and end of the selection, x is the offset of the first | 4193 * @return start and end of the selection, x is the offset of the first |
4070 * selected character, y is the offset after the last selected character. | 4194 * selected character, y is the offset after the last selected character. |
4071 * The selection values returned are visual (i.e., x will always always be | 4195 * The selection values returned are visual (i.e., x will always always be |
4072 * <= y). To determine if a selection is right-to-left cast(RtoL) vs. left-to-right | 4196 * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4073 * cast(LtoR), compare the caretOffset to the start and end of the selection | 4197 * (LtoR), compare the caretOffset to the start and end of the selection |
4074 * (e.g., caretOffset is start of selection implies that the selection is RtoL). | 4198 * (e.g., caretOffset is start of selection implies that the selection is RtoL). |
4075 * @see #getSelectionRange | 4199 * @see #getSelectionRange |
4076 * @exception DWTException <ul> | 4200 * @exception DWTException <ul> |
4077 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4201 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4078 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4202 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4083 return new Point(selection.x, selection.y); | 4207 return new Point(selection.x, selection.y); |
4084 } | 4208 } |
4085 /** | 4209 /** |
4086 * Returns the selection. | 4210 * Returns the selection. |
4087 * | 4211 * |
4088 * @return start and length of the selection, x is the offset of the | 4212 * @return start and length of the selection, x is the offset of the |
4089 * first selected character, relative to the first character of the | 4213 * first selected character, relative to the first character of the |
4090 * widget content. y is the length of the selection. | 4214 * widget content. y is the length of the selection. |
4091 * The selection values returned are visual (i.e., length will always always be | 4215 * The selection values returned are visual (i.e., length will always always be |
4092 * positive). To determine if a selection is right-to-left cast(RtoL) vs. left-to-right | 4216 * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4093 * cast(LtoR), compare the caretOffset to the start and end of the selection | 4217 * (LtoR), compare the caretOffset to the start and end of the selection |
4094 * (e.g., caretOffset is start of selection implies that the selection is RtoL). | 4218 * (e.g., caretOffset is start of selection implies that the selection is RtoL). |
4095 * @exception DWTException <ul> | 4219 * @exception DWTException <ul> |
4096 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4220 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4097 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4221 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4098 * </ul> | 4222 * </ul> |
4161 */ | 4285 */ |
4162 public String getSelectionText() { | 4286 public String getSelectionText() { |
4163 checkWidget(); | 4287 checkWidget(); |
4164 return content.getTextRange(selection.x, selection.y - selection.x); | 4288 return content.getTextRange(selection.x, selection.y - selection.x); |
4165 } | 4289 } |
4166 public int getStyle() { | 4290 public override int getStyle() { |
4167 int style = super.getStyle(); | 4291 int style = super.getStyle(); |
4168 style &= ~(DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.MIRRORED); | 4292 style &= ~(DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.MIRRORED); |
4169 if (isMirrored()) { | 4293 if (isMirrored()) { |
4170 style |= DWT.RIGHT_TO_LEFT | DWT.MIRRORED; | 4294 style |= DWT.RIGHT_TO_LEFT | DWT.MIRRORED; |
4171 } else { | 4295 } else { |
4173 } | 4297 } |
4174 return style; | 4298 return style; |
4175 } | 4299 } |
4176 | 4300 |
4177 /** | 4301 /** |
4178 * Returns the text segments that should be treated as if they | 4302 * Returns the text segments that should be treated as if they |
4179 * had a different direction than the surrounding text. | 4303 * had a different direction than the surrounding text. |
4180 * | 4304 * |
4181 * @param lineOffset offset of the first character in the line. | 4305 * @param lineOffset offset of the first character in the line. |
4182 * 0 based from the beginning of the document. | 4306 * 0 based from the beginning of the document. |
4183 * @param line text of the line to specify bidi segments for | 4307 * @param line text of the line to specify bidi segments for |
4184 * @return text segments that should be treated as if they had a | 4308 * @return text segments that should be treated as if they had a |
4185 * different direction than the surrounding text. Only the start | 4309 * different direction than the surrounding text. Only the start |
4186 * index of a segment is specified, relative to the start of the | 4310 * index of a segment is specified, relative to the start of the |
4187 * line. Always starts with 0 and ends with the line length. | 4311 * line. Always starts with 0 and ends with the line length. |
4188 * @exception IllegalArgumentException <ul> | 4312 * @exception IllegalArgumentException <ul> |
4189 * <li>ERROR_INVALID_ARGUMENT - if the segment indices returned | 4313 * <li>ERROR_INVALID_ARGUMENT - if the segment indices returned |
4190 * by the listener do not start with 0, are not in ascending order, | 4314 * by the listener do not start with 0, are not in ascending order, |
4191 * exceed the line length or have duplicates</li> | 4315 * exceed the line length or have duplicates</li> |
4192 * </ul> | 4316 * </ul> |
4193 */ | 4317 */ |
4194 int [] getBidiSegments(int lineOffset, String line) { | 4318 int [] getBidiSegments(int lineOffset, String line) { |
4195 if (!isBidi()) return null; | 4319 if (!isBidi()) return null; |
4196 if (!isListening(LineGetSegments)) { | 4320 if (!isListening(LineGetSegments)) { |
4197 return getBidiSegmentsCompatibility(line, lineOffset); | 4321 return getBidiSegmentsCompatibility(line, lineOffset); |
4198 } | 4322 } |
4199 StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); | 4323 StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); |
4200 int lineLength = line.length(); | 4324 int lineLength = line.length; |
4201 int[] segments; | 4325 int[] segments; |
4202 if (event is null || event.segments is null || event.segments.length is 0) { | 4326 if (event is null || event.segments is null || event.segments.length is 0) { |
4203 segments = new int[] {0, lineLength}; | 4327 segments = [0, lineLength]; |
4204 } else { | 4328 } else { |
4205 int segmentCount = event.segments.length; | 4329 int segmentCount = event.segments.length; |
4206 | 4330 |
4207 // test segment index consistency | 4331 // test segment index consistency |
4208 if (event.segments[0] !is 0) { | 4332 if (event.segments[0] !is 0) { |
4209 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 4333 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
4210 } | 4334 } |
4211 for (int i = 1; i < segmentCount; i++) { | 4335 for (int i = 1; i < segmentCount; i++) { |
4212 if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { | 4336 if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { |
4213 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 4337 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
4214 } | 4338 } |
4215 } | 4339 } |
4216 // ensure that last segment index is line end offset | 4340 // ensure that last segment index is line end offset |
4217 if (event.segments[segmentCount - 1] !is lineLength) { | 4341 if (event.segments[segmentCount - 1] !is lineLength) { |
4218 segments = new int[segmentCount + 1]; | 4342 segments = new int[segmentCount + 1]; |
4219 System.arraycopy(event.segments, 0, segments, 0, segmentCount); | 4343 System.arraycopy(event.segments, 0, segments, 0, segmentCount); |
4227 /** | 4351 /** |
4228 * @see #getBidiSegments | 4352 * @see #getBidiSegments |
4229 * Supports deprecated setBidiColoring API. Remove when API is removed. | 4353 * Supports deprecated setBidiColoring API. Remove when API is removed. |
4230 */ | 4354 */ |
4231 int [] getBidiSegmentsCompatibility(String line, int lineOffset) { | 4355 int [] getBidiSegmentsCompatibility(String line, int lineOffset) { |
4232 int lineLength = line.length(); | 4356 int lineLength = line.length; |
4233 if (!bidiColoring) { | 4357 if (!bidiColoring) { |
4234 return new int[] {0, lineLength}; | 4358 return [0, lineLength]; |
4235 } | 4359 } |
4236 StyleRange [] styles = null; | 4360 StyleRange [] styles = null; |
4237 StyledTextEvent event = getLineStyleData(lineOffset, line); | 4361 StyledTextEvent event = getLineStyleData(lineOffset, line); |
4238 if (event !is null) { | 4362 if (event !is null) { |
4239 styles = event.styles; | 4363 styles = event.styles; |
4240 } else { | 4364 } else { |
4241 styles = renderer.getStyleRanges(lineOffset, lineLength, true); | 4365 styles = renderer.getStyleRanges(lineOffset, lineLength, true); |
4242 } | 4366 } |
4243 if (styles is null || styles.length is 0) { | 4367 if (styles is null || styles.length is 0) { |
4244 return new int[] {0, lineLength}; | 4368 return [0, lineLength]; |
4245 } | 4369 } |
4246 int k=0, count = 1; | 4370 int k=0, count = 1; |
4247 while (k < styles.length && styles[k].start is 0 && styles[k].length is lineLength) { | 4371 while (k < styles.length && styles[k].start is 0 && styles[k].length is lineLength) { |
4248 k++; | 4372 k++; |
4249 } | 4373 } |
4250 int[] offsets = new int[(styles.length - k) * 2 + 2]; | 4374 int[] offsets = new int[(styles.length - k) * 2 + 2]; |
4251 for (int i = k; i < styles.length; i++) { | 4375 for (int i = k; i < styles.length; i++) { |
4252 StyleRange style = styles[i]; | 4376 StyleRange style = styles[i]; |
4253 int styleLineStart = Math.max(style.start - lineOffset, 0); | 4377 int styleLineStart = Math.max(style.start - lineOffset, 0); |
4254 int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); | 4378 int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); |
4255 styleLineEnd = Math.min (styleLineEnd, line.length ()); | 4379 styleLineEnd = Math.min (styleLineEnd, line.length ); |
4256 if (i > 0 && count > 1 && | 4380 if (i > 0 && count > 1 && |
4257 ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || | 4381 ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || |
4258 (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && | 4382 (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && |
4259 style.similarTo(styles[i-1])) { | 4383 style.similarTo(styles[i-1])) { |
4260 offsets[count-2] = Math.min(offsets[count-2], styleLineStart); | 4384 offsets[count-2] = Math.min(offsets[count-2], styleLineStart); |
4282 } | 4406 } |
4283 /** | 4407 /** |
4284 * Returns the style range at the given offset. | 4408 * Returns the style range at the given offset. |
4285 * <p> | 4409 * <p> |
4286 * Returns null if a LineStyleListener has been set or if a style is not set | 4410 * Returns null if a LineStyleListener has been set or if a style is not set |
4287 * for the offset. | 4411 * for the offset. |
4288 * Should not be called if a LineStyleListener has been set since the | 4412 * Should not be called if a LineStyleListener has been set since the |
4289 * listener maintains the styles. | 4413 * listener maintains the styles. |
4290 * </p> | 4414 * </p> |
4291 * | 4415 * |
4292 * @param offset the offset to return the style for. | 4416 * @param offset the offset to return the style for. |
4293 * 0 <= offset < getCharCount() must be true. | 4417 * 0 <= offset < getCharCount() must be true. |
4294 * @return a StyleRange with start is offset and length is 1, indicating | 4418 * @return a StyleRange with start is offset and length is 1, indicating |
4295 * the style at the given offset. null if a LineStyleListener has been set | 4419 * the style at the given offset. null if a LineStyleListener has been set |
4296 * or if a style is not set for the given offset. | 4420 * or if a style is not set for the given offset. |
4297 * @exception DWTException <ul> | 4421 * @exception DWTException <ul> |
4298 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4422 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4299 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4423 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4300 * </ul> | 4424 * </ul> |
4314 return null; | 4438 return null; |
4315 } | 4439 } |
4316 /** | 4440 /** |
4317 * Returns the styles. | 4441 * Returns the styles. |
4318 * <p> | 4442 * <p> |
4319 * Returns an empty array if a LineStyleListener has been set. | 4443 * Returns an empty array if a LineStyleListener has been set. |
4320 * Should not be called if a LineStyleListener has been set since the | 4444 * Should not be called if a LineStyleListener has been set since the |
4321 * listener maintains the styles. | 4445 * listener maintains the styles. |
4322 * <p></p> | 4446 * <p></p> |
4323 * Note: Because a StyleRange includes the start and length, the | 4447 * Note: Because a StyleRange includes the start and length, the |
4324 * same instance cannot occur multiple times in the array of styles. | 4448 * same instance cannot occur multiple times in the array of styles. |
4325 * If the same style attributes, such as font and color, occur in | 4449 * If the same style attributes, such as font and color, occur in |
4331 * | 4455 * |
4332 * @exception DWTException <ul> | 4456 * @exception DWTException <ul> |
4333 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4457 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4334 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4458 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4335 * </ul> | 4459 * </ul> |
4336 * | 4460 * |
4337 * @see #getStyleRanges(bool) | 4461 * @see #getStyleRanges(bool) |
4338 */ | 4462 */ |
4339 public StyleRange[] getStyleRanges() { | 4463 public StyleRange[] getStyleRanges() { |
4340 checkWidget(); | 4464 checkWidget(); |
4341 return getStyleRanges(0, content.getCharCount(), true); | 4465 return getStyleRanges(0, content.getCharCount(), true); |
4342 } | 4466 } |
4343 /** | 4467 /** |
4344 * Returns the styles. | 4468 * Returns the styles. |
4345 * <p> | 4469 * <p> |
4346 * Returns an empty array if a LineStyleListener has been set. | 4470 * Returns an empty array if a LineStyleListener has been set. |
4347 * Should not be called if a LineStyleListener has been set since the | 4471 * Should not be called if a LineStyleListener has been set since the |
4348 * listener maintains the styles. | 4472 * listener maintains the styles. |
4349 * </p><p> | 4473 * </p><p> |
4350 * Note: When <code>includeRanges</code> is true, the start and length | 4474 * Note: When <code>includeRanges</code> is true, the start and length |
4351 * fields of each StyleRange will be valid, however the StyleRange | 4475 * fields of each StyleRange will be valid, however the StyleRange |
4352 * objects may need to be cloned. When <code>includeRanges</code> is | 4476 * objects may need to be cloned. When <code>includeRanges</code> is |
4353 * false, <code>getRanges(int, int)</code> can be used to get the | 4477 * false, <code>getRanges(int, int)</code> can be used to get the |
4354 * associated ranges. | 4478 * associated ranges. |
4355 * </p> | 4479 * </p> |
4356 * | 4480 * |
4357 * @param includeRanges whether the start and length field of the StyleRanges should be set. | 4481 * @param includeRanges whether the start and length field of the StyleRanges should be set. |
4358 * | 4482 * |
4359 * @return the styles or an empty array if a LineStyleListener has been set. | 4483 * @return the styles or an empty array if a LineStyleListener has been set. |
4360 * | 4484 * |
4361 * @exception DWTException <ul> | 4485 * @exception DWTException <ul> |
4362 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4486 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4363 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4487 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4364 * </ul> | 4488 * </ul> |
4365 * | 4489 * |
4366 * @since 3.2 | 4490 * @since 3.2 |
4367 * | 4491 * |
4368 * @see #getRanges(int, int) | 4492 * @see #getRanges(int, int) |
4369 * @see #setStyleRanges(int[], StyleRange[]) | 4493 * @see #setStyleRanges(int[], StyleRange[]) |
4370 */ | 4494 */ |
4371 public StyleRange[] getStyleRanges(bool includeRanges) { | 4495 public StyleRange[] getStyleRanges(bool includeRanges) { |
4372 checkWidget(); | 4496 checkWidget(); |
4373 return getStyleRanges(0, content.getCharCount(), includeRanges); | 4497 return getStyleRanges(0, content.getCharCount(), includeRanges); |
4374 } | 4498 } |
4375 /** | 4499 /** |
4376 * Returns the styles for the given text range. | 4500 * Returns the styles for the given text range. |
4377 * <p> | 4501 * <p> |
4378 * Returns an empty array if a LineStyleListener has been set. | 4502 * Returns an empty array if a LineStyleListener has been set. |
4379 * Should not be called if a LineStyleListener has been set since the | 4503 * Should not be called if a LineStyleListener has been set since the |
4380 * listener maintains the styles. | 4504 * listener maintains the styles. |
4381 * </p><p> | 4505 * </p><p> |
4382 * Note: Because the StyleRange includes the start and length, the | 4506 * Note: Because the StyleRange includes the start and length, the |
4383 * same instance cannot occur multiple times in the array of styles. | 4507 * same instance cannot occur multiple times in the array of styles. |
4384 * If the same style attributes, such as font and color, occur in | 4508 * If the same style attributes, such as font and color, occur in |
4386 * can be used to get the styles without the ranges. | 4510 * can be used to get the styles without the ranges. |
4387 * </p> | 4511 * </p> |
4388 * @param start the start offset of the style ranges to return | 4512 * @param start the start offset of the style ranges to return |
4389 * @param length the number of style ranges to return | 4513 * @param length the number of style ranges to return |
4390 * | 4514 * |
4391 * @return the styles or an empty array if a LineStyleListener has | 4515 * @return the styles or an empty array if a LineStyleListener has |
4392 * been set. The returned styles will reflect the given range. The first | 4516 * been set. The returned styles will reflect the given range. The first |
4393 * returned <code>StyleRange</code> will have a starting offset >= start | 4517 * returned <code>StyleRange</code> will have a starting offset >= start |
4394 * and the last returned <code>StyleRange</code> will have an ending | 4518 * and the last returned <code>StyleRange</code> will have an ending |
4395 * offset <= start + length - 1 | 4519 * offset <= start + length - 1 |
4396 * | 4520 * |
4397 * @exception DWTException <ul> | 4521 * @exception DWTException <ul> |
4398 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4522 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4399 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4523 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4400 * </ul> | 4524 * </ul> |
4401 * @exception IllegalArgumentException <ul> | 4525 * @exception IllegalArgumentException <ul> |
4402 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> | 4526 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4403 * </ul> | 4527 * </ul> |
4404 * | 4528 * |
4405 * @see #getStyleRanges(int, int, bool) | 4529 * @see #getStyleRanges(int, int, bool) |
4406 * | 4530 * |
4407 * @since 3.0 | 4531 * @since 3.0 |
4408 */ | 4532 */ |
4409 public StyleRange[] getStyleRanges(int start, int length) { | 4533 public StyleRange[] getStyleRanges(int start, int length) { |
4410 checkWidget(); | 4534 checkWidget(); |
4411 return getStyleRanges(start, length, true); | 4535 return getStyleRanges(start, length, true); |
4412 } | 4536 } |
4413 /** | 4537 /** |
4414 * Returns the styles for the given text range. | 4538 * Returns the styles for the given text range. |
4415 * <p> | 4539 * <p> |
4416 * Returns an empty array if a LineStyleListener has been set. | 4540 * Returns an empty array if a LineStyleListener has been set. |
4417 * Should not be called if a LineStyleListener has been set since the | 4541 * Should not be called if a LineStyleListener has been set since the |
4418 * listener maintains the styles. | 4542 * listener maintains the styles. |
4419 * </p><p> | 4543 * </p><p> |
4420 * Note: When <code>includeRanges</code> is true, the start and length | 4544 * Note: When <code>includeRanges</code> is true, the start and length |
4421 * fields of each StyleRange will be valid, however the StyleRange | 4545 * fields of each StyleRange will be valid, however the StyleRange |
4422 * objects may need to be cloned. When <code>includeRanges</code> is | 4546 * objects may need to be cloned. When <code>includeRanges</code> is |
4423 * false, <code>getRanges(int, int)</code> can be used to get the | 4547 * false, <code>getRanges(int, int)</code> can be used to get the |
4424 * associated ranges. | 4548 * associated ranges. |
4425 * </p> | 4549 * </p> |
4426 * | 4550 * |
4427 * @param start the start offset of the style ranges to return | 4551 * @param start the start offset of the style ranges to return |
4428 * @param length the number of style ranges to return | 4552 * @param length the number of style ranges to return |
4429 * @param includeRanges whether the start and length field of the StyleRanges should be set. | 4553 * @param includeRanges whether the start and length field of the StyleRanges should be set. |
4430 * | 4554 * |
4431 * @return the styles or an empty array if a LineStyleListener has | 4555 * @return the styles or an empty array if a LineStyleListener has |
4432 * been set. The returned styles will reflect the given range. The first | 4556 * been set. The returned styles will reflect the given range. The first |
4433 * returned <code>StyleRange</code> will have a starting offset >= start | 4557 * returned <code>StyleRange</code> will have a starting offset >= start |
4434 * and the last returned <code>StyleRange</code> will have an ending | 4558 * and the last returned <code>StyleRange</code> will have an ending |
4435 * offset <= start + length - 1 | 4559 * offset <= start + length - 1 |
4436 * | 4560 * |
4437 * @exception DWTException <ul> | 4561 * @exception DWTException <ul> |
4438 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4562 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4439 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4563 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4440 * </ul> | 4564 * </ul> |
4441 * @exception IllegalArgumentException <ul> | 4565 * @exception IllegalArgumentException <ul> |
4442 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> | 4566 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4443 * </ul> | 4567 * </ul> |
4444 * | 4568 * |
4445 * @since 3.2 | 4569 * @since 3.2 |
4446 * | 4570 * |
4447 * @see #getRanges(int, int) | 4571 * @see #getRanges(int, int) |
4448 * @see #setStyleRanges(int[], StyleRange[]) | 4572 * @see #setStyleRanges(int[], StyleRange[]) |
4449 */ | 4573 */ |
4450 public StyleRange[] getStyleRanges(int start, int length, bool includeRanges) { | 4574 public StyleRange[] getStyleRanges(int start, int length, bool includeRanges) { |
4451 checkWidget(); | 4575 checkWidget(); |
4488 } | 4612 } |
4489 /** | 4613 /** |
4490 * Returns the widget content between the two offsets. | 4614 * Returns the widget content between the two offsets. |
4491 * | 4615 * |
4492 * @param start offset of the first character in the returned String | 4616 * @param start offset of the first character in the returned String |
4493 * @param end offset of the last character in the returned String | 4617 * @param end offset of the last character in the returned String |
4494 * @return widget content starting at start and ending at end | 4618 * @return widget content starting at start and ending at end |
4495 * @see #getTextRange(int,int) | 4619 * @see #getTextRange(int,int) |
4496 * @exception DWTException <ul> | 4620 * @exception DWTException <ul> |
4497 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4621 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4498 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4622 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4499 * </ul> | 4623 * </ul> |
4500 * @exception IllegalArgumentException <ul> | 4624 * @exception IllegalArgumentException <ul> |
4501 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> | 4625 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4502 * </ul> | 4626 * </ul> |
4503 */ | 4627 */ |
4504 public String getText(int start, int end) { | 4628 public String getText(int start, int end) { |
4505 checkWidget(); | 4629 checkWidget(); |
4506 int contentLength = getCharCount(); | 4630 int contentLength = getCharCount(); |
4511 } | 4635 } |
4512 /** | 4636 /** |
4513 * Returns the smallest bounding rectangle that includes the characters between two offsets. | 4637 * Returns the smallest bounding rectangle that includes the characters between two offsets. |
4514 * | 4638 * |
4515 * @param start offset of the first character included in the bounding box | 4639 * @param start offset of the first character included in the bounding box |
4516 * @param end offset of the last character included in the bounding box | 4640 * @param end offset of the last character included in the bounding box |
4517 * @return bounding box of the text between start and end | 4641 * @return bounding box of the text between start and end |
4518 * @exception DWTException <ul> | 4642 * @exception DWTException <ul> |
4519 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4643 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4520 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4644 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4521 * </ul> | 4645 * </ul> |
4522 * @exception IllegalArgumentException <ul> | 4646 * @exception IllegalArgumentException <ul> |
4523 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> | 4647 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4524 * </ul> | 4648 * </ul> |
4525 * @since 3.1 | 4649 * @since 3.1 |
4526 */ | 4650 */ |
4527 public Rectangle getTextBounds(int start, int end) { | 4651 public Rectangle getTextBounds(int start, int end) { |
4528 checkWidget(); | 4652 checkWidget(); |
4529 int contentLength = getCharCount(); | 4653 int contentLength = getCharCount(); |
4530 if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { | 4654 if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { |
4531 DWT.error(DWT.ERROR_INVALID_RANGE); | 4655 DWT.error(DWT.ERROR_INVALID_RANGE); |
4532 } | 4656 } |
4533 int lineStart = content.getLineAtOffset(start); | 4657 int lineStart = content.getLineAtOffset(start); |
4534 int lineEnd = content.getLineAtOffset(end); | 4658 int lineEnd = content.getLineAtOffset(end); |
4535 Rectangle rect; | 4659 Rectangle rect; |
4536 int y = getLinePixel(lineStart); | 4660 int y = getLinePixel(lineStart); |
4537 int height = 0; | 4661 int height = 0; |
4538 int left = 0x7fffffff, right = 0; | 4662 int left = 0x7fffffff, right = 0; |
4539 for (int i = lineStart; i <= lineEnd; i++) { | 4663 for (int i = lineStart; i <= lineEnd; i++) { |
4540 int lineOffset = content.getOffsetAtLine(i); | 4664 int lineOffset = content.getOffsetAtLine(i); |
4541 TextLayout layout = renderer.getTextLayout(i); | 4665 TextLayout layout = renderer.getTextLayout(i); |
4542 int length = layout.getText().length(); | 4666 int length = layout.getText().length; |
4543 if (length > 0) { | 4667 if (length > 0) { |
4544 if (i is lineStart) { | 4668 if (i is lineStart) { |
4545 if (i is lineEnd) { | 4669 if (i is lineEnd) { |
4546 rect = layout.getBounds(start - lineOffset, end - lineOffset); | 4670 rect = layout.getBounds(start - lineOffset, end - lineOffset); |
4547 } else { | 4671 } else { |
4567 } | 4691 } |
4568 /** | 4692 /** |
4569 * Returns the widget content starting at start for length characters. | 4693 * Returns the widget content starting at start for length characters. |
4570 * | 4694 * |
4571 * @param start offset of the first character in the returned String | 4695 * @param start offset of the first character in the returned String |
4572 * @param length number of characters to return | 4696 * @param length number of characters to return |
4573 * @return widget content starting at start and extending length characters. | 4697 * @return widget content starting at start and extending length characters. |
4574 * @exception DWTException <ul> | 4698 * @exception DWTException <ul> |
4575 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4699 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4576 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4700 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4577 * </ul> | 4701 * </ul> |
4578 * @exception IllegalArgumentException <ul> | 4702 * @exception IllegalArgumentException <ul> |
4579 * <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> | 4703 * <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> |
4580 * </ul> | 4704 * </ul> |
4581 */ | 4705 */ |
4582 public String getTextRange(int start, int length) { | 4706 public String getTextRange(int start, int length) { |
4583 checkWidget(); | 4707 checkWidget(); |
4584 int contentLength = getCharCount(); | 4708 int contentLength = getCharCount(); |
4585 int end = start + length; | 4709 int end = start + length; |
4586 if (start > end || start < 0 || end > contentLength) { | 4710 if (start > end || start < 0 || end > contentLength) { |
4587 DWT.error(DWT.ERROR_INVALID_RANGE); | 4711 DWT.error(DWT.ERROR_INVALID_RANGE); |
4588 } | 4712 } |
4589 return content.getTextRange(start, length); | 4713 return content.getTextRange(start, length); |
4590 } | 4714 } |
4591 /** | 4715 /** |
4592 * Returns the maximum number of characters that the receiver is capable of holding. | 4716 * Returns the maximum number of characters that the receiver is capable of holding. |
4593 * | 4717 * |
4594 * @return the text limit | 4718 * @return the text limit |
4595 * | 4719 * |
4596 * @exception DWTException <ul> | 4720 * @exception DWTException <ul> |
4597 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4721 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4598 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4722 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4603 return textLimit; | 4727 return textLimit; |
4604 } | 4728 } |
4605 /** | 4729 /** |
4606 * Gets the top index. | 4730 * Gets the top index. |
4607 * <p> | 4731 * <p> |
4608 * The top index is the index of the fully visible line that is currently | 4732 * The top index is the index of the fully visible line that is currently |
4609 * at the top of the widget or the topmost partially visible line if no line is fully visible. | 4733 * at the top of the widget or the topmost partially visible line if no line is fully visible. |
4610 * The top index changes when the widget is scrolled. Indexing is zero based. | 4734 * The top index changes when the widget is scrolled. Indexing is zero based. |
4611 * </p> | 4735 * </p> |
4612 * | 4736 * |
4613 * @return the index of the top line | 4737 * @return the index of the top line |
4614 * @exception DWTException <ul> | 4738 * @exception DWTException <ul> |
4621 return topIndex; | 4745 return topIndex; |
4622 } | 4746 } |
4623 /** | 4747 /** |
4624 * Gets the top pixel. | 4748 * Gets the top pixel. |
4625 * <p> | 4749 * <p> |
4626 * The top pixel is the pixel position of the line that is | 4750 * The top pixel is the pixel position of the line that is |
4627 * currently at the top of the widget. The text widget can be scrolled by pixels | 4751 * currently at the top of the widget. The text widget can be scrolled by pixels |
4628 * by dragging the scroll thumb so that a partial line may be displayed at the top | 4752 * by dragging the scroll thumb so that a partial line may be displayed at the top |
4629 * the widget. The top pixel changes when the widget is scrolled. The top pixel | 4753 * the widget. The top pixel changes when the widget is scrolled. The top pixel |
4630 * does not include the widget trimming. | 4754 * does not include the widget trimming. |
4631 * </p> | 4755 * </p> |
4632 * | 4756 * |
4633 * @return pixel position of the top line | 4757 * @return pixel position of the top line |
4634 * @exception DWTException <ul> | 4758 * @exception DWTException <ul> |
4638 */ | 4762 */ |
4639 public int getTopPixel() { | 4763 public int getTopPixel() { |
4640 checkWidget(); | 4764 checkWidget(); |
4641 return getVerticalScrollOffset(); | 4765 return getVerticalScrollOffset(); |
4642 } | 4766 } |
4643 /** | 4767 /** |
4644 * Returns the vertical scroll increment. | 4768 * Returns the vertical scroll increment. |
4645 * | 4769 * |
4646 * @return vertical scroll increment. | 4770 * @return vertical scroll increment. |
4647 */ | 4771 */ |
4648 int getVerticalIncrement() { | 4772 int getVerticalIncrement() { |
4677 updateCaretDirection = false; | 4801 updateCaretDirection = false; |
4678 int caretLine = getCaretLine(); | 4802 int caretLine = getCaretLine(); |
4679 int lineOffset = content.getOffsetAtLine(caretLine); | 4803 int lineOffset = content.getOffsetAtLine(caretLine); |
4680 String line = content.getLine(caretLine); | 4804 String line = content.getLine(caretLine); |
4681 int offset = caretOffset - lineOffset; | 4805 int offset = caretOffset - lineOffset; |
4682 int lineLength = line.length(); | 4806 int lineLength = line.length; |
4683 if (lineLength is 0) return isMirrored() ? DWT.RIGHT : DWT.LEFT; | 4807 if (lineLength is 0) return isMirrored() ? DWT.RIGHT : DWT.LEFT; |
4684 if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; | 4808 if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; |
4685 if (offset is lineLength && offset > 0) offset--; | 4809 if (offset is lineLength && offset > 0) offset--; |
4686 while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; | 4810 while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; |
4687 if (offset is 0 && Character.isDigit(line.charAt(offset))) { | 4811 if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { |
4688 return isMirrored() ? DWT.RIGHT : DWT.LEFT; | 4812 return isMirrored() ? DWT.RIGHT : DWT.LEFT; |
4689 } | 4813 } |
4690 TextLayout layout = renderer.getTextLayout(caretLine); | 4814 TextLayout layout = renderer.getTextLayout(caretLine); |
4691 int level = layout.getLevel(offset); | 4815 int level = layout.getLevel(offset); |
4692 renderer.disposeTextLayout(layout); | 4816 renderer.disposeTextLayout(layout); |
4715 lineText = content.getLine(lineIndex); | 4839 lineText = content.getLine(lineIndex); |
4716 } else { | 4840 } else { |
4717 int lineIndex = content.getLineAtOffset(offset); | 4841 int lineIndex = content.getLineAtOffset(offset); |
4718 lineOffset = content.getOffsetAtLine(lineIndex); | 4842 lineOffset = content.getOffsetAtLine(lineIndex); |
4719 lineText = content.getLine(lineIndex); | 4843 lineText = content.getLine(lineIndex); |
4720 int lineLength = lineText.length(); | 4844 int lineLength = lineText.length; |
4721 if (offset is lineOffset + lineLength) { | 4845 if (offset is lineOffset + lineLength) { |
4722 newOffset = content.getOffsetAtLine(lineIndex + 1); | 4846 newOffset = content.getOffsetAtLine(lineIndex + 1); |
4723 } else { | 4847 } else { |
4724 TextLayout layout = renderer.getTextLayout(lineIndex); | 4848 TextLayout layout = renderer.getTextLayout(lineIndex); |
4725 newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement); | 4849 newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement); |
4740 int lineIndex = content.getLineAtOffset(offset); | 4864 int lineIndex = content.getLineAtOffset(offset); |
4741 lineOffset = content.getOffsetAtLine(lineIndex); | 4865 lineOffset = content.getOffsetAtLine(lineIndex); |
4742 lineText = content.getLine(lineIndex); | 4866 lineText = content.getLine(lineIndex); |
4743 if (offset is lineOffset) { | 4867 if (offset is lineOffset) { |
4744 String nextLineText = content.getLine(lineIndex - 1); | 4868 String nextLineText = content.getLine(lineIndex - 1); |
4745 int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); | 4869 int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); |
4746 newOffset = nextLineOffset + nextLineText.length(); | 4870 newOffset = nextLineOffset + nextLineText.length; |
4747 } else { | 4871 } else { |
4748 TextLayout layout = renderer.getTextLayout(lineIndex); | 4872 TextLayout layout = renderer.getTextLayout(lineIndex); |
4749 newOffset = lineOffset + layout.getPreviousOffset(offset - lineOffset, movement); | 4873 newOffset = lineOffset + layout.getPreviousOffset(offset - lineOffset, movement); |
4750 renderer.disposeTextLayout(layout); | 4874 renderer.disposeTextLayout(layout); |
4751 } | 4875 } |
4752 } | 4876 } |
4753 return sendWordBoundaryEvent(WordPrevious, movement, offset, newOffset, lineText, lineOffset); | 4877 return sendWordBoundaryEvent(WordPrevious, movement, offset, newOffset, lineText, lineOffset); |
4754 } | 4878 } |
4755 /** | 4879 /** |
4760 */ | 4884 */ |
4761 public bool getWordWrap() { | 4885 public bool getWordWrap() { |
4762 checkWidget(); | 4886 checkWidget(); |
4763 return wordWrap; | 4887 return wordWrap; |
4764 } | 4888 } |
4765 /** | 4889 /** |
4766 * Returns the location of the given offset. | 4890 * Returns the location of the given offset. |
4767 * <p> | 4891 * <p> |
4768 * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts). | 4892 * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts). |
4769 * </p> | 4893 * </p> |
4770 * | 4894 * |
4773 Point getPointAtOffset(int offset) { | 4897 Point getPointAtOffset(int offset) { |
4774 int lineIndex = content.getLineAtOffset(offset); | 4898 int lineIndex = content.getLineAtOffset(offset); |
4775 String line = content.getLine(lineIndex); | 4899 String line = content.getLine(lineIndex); |
4776 int lineOffset = content.getOffsetAtLine(lineIndex); | 4900 int lineOffset = content.getOffsetAtLine(lineIndex); |
4777 int offsetInLine = offset - lineOffset; | 4901 int offsetInLine = offset - lineOffset; |
4778 int lineLength = line.length(); | 4902 int lineLength = line.length; |
4779 if (lineIndex < content.getLineCount() - 1) { | 4903 if (lineIndex < content.getLineCount() - 1) { |
4780 int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; | 4904 int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; |
4781 if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { | 4905 if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { |
4782 offsetInLine = lineLength; | 4906 offsetInLine = lineLength; |
4783 } | 4907 } |
4784 } | 4908 } |
4785 Point point; | 4909 Point point; |
4786 TextLayout layout = renderer.getTextLayout(lineIndex); | 4910 TextLayout layout = renderer.getTextLayout(lineIndex); |
4787 if (lineLength !is 0 && offsetInLine <= lineLength) { | 4911 if (lineLength !is 0 && offsetInLine <= lineLength) { |
4788 if (offsetInLine is lineLength) { | 4912 if (offsetInLine is lineLength) { |
4789 point = layout.getLocation(offsetInLine - 1, true); | 4913 // DWT: Instead of go back one byte, go back one codepoint |
4914 int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); | |
4915 point = layout.getLocation(offsetInLine_m1, true); | |
4790 } else { | 4916 } else { |
4791 switch (caretAlignment) { | 4917 switch (caretAlignment) { |
4792 case OFFSET_LEADING: | 4918 case OFFSET_LEADING: |
4793 point = layout.getLocation(offsetInLine, false); | 4919 point = layout.getLocation(offsetInLine, false); |
4794 break; | 4920 break; |
4795 case PREVIOUS_OFFSET_TRAILING: | 4921 case PREVIOUS_OFFSET_TRAILING: |
4796 default: | 4922 default: |
4797 if (offsetInLine is 0) { | 4923 if (offsetInLine is 0) { |
4798 point = layout.getLocation(offsetInLine, false); | 4924 point = layout.getLocation(offsetInLine, false); |
4799 } else { | 4925 } else { |
4800 point = layout.getLocation(offsetInLine - 1, true); | 4926 // DWT: Instead of go back one byte, go back one codepoint |
4927 int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); | |
4928 point = layout.getLocation(offsetInLine_m1, true); | |
4801 } | 4929 } |
4802 break; | 4930 break; |
4803 } | 4931 } |
4804 } | 4932 } |
4805 } else { | 4933 } else { |
4808 renderer.disposeTextLayout(layout); | 4936 renderer.disposeTextLayout(layout); |
4809 point.x += leftMargin - horizontalScrollOffset; | 4937 point.x += leftMargin - horizontalScrollOffset; |
4810 point.y += getLinePixel(lineIndex); | 4938 point.y += getLinePixel(lineIndex); |
4811 return point; | 4939 return point; |
4812 } | 4940 } |
4813 /** | 4941 /** |
4814 * Inserts a String. The old selection is replaced with the new text. | 4942 * Inserts a string. The old selection is replaced with the new text. |
4815 * | 4943 * |
4816 * @param String the String | 4944 * @param string the string |
4817 * @see #replaceTextRange(int,int,String) | 4945 * @see #replaceTextRange(int,int,String) |
4818 * @exception DWTException <ul> | 4946 * @exception DWTException <ul> |
4819 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 4947 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4820 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 4948 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4821 * </ul> | 4949 * </ul> |
4822 * @exception IllegalArgumentException <ul> | 4950 */ |
4823 * <li>ERROR_NULL_ARGUMENT when String is null</li> | 4951 public void insert(String string) { |
4824 * </ul> | 4952 checkWidget(); |
4825 */ | 4953 // DWT extension: allow null for zero length string |
4826 public void insert(String String) { | 4954 // if (string is null) { |
4827 checkWidget(); | 4955 // DWT.error(DWT.ERROR_NULL_ARGUMENT); |
4828 if (String is null) { | 4956 // } |
4829 DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
4830 } | |
4831 Point sel = getSelectionRange(); | 4957 Point sel = getSelectionRange(); |
4832 replaceTextRange(sel.x, sel.y, String); | 4958 replaceTextRange(sel.x, sel.y, string); |
4833 } | 4959 } |
4834 /** | 4960 /** |
4835 * Creates content change listeners and set the default content model. | 4961 * Creates content change listeners and set the default content model. |
4836 */ | 4962 */ |
4837 void installDefaultContent() { | 4963 void installDefaultContent() { |
4838 textChangeListener = new TextChangeListener() { | 4964 textChangeListener = new class() TextChangeListener { |
4839 public void textChanging(TextChangingEvent event) { | 4965 public void textChanging(TextChangingEvent event) { |
4840 handleTextChanging(event); | 4966 handleTextChanging(event); |
4841 } | 4967 } |
4842 public void textChanged(TextChangedEvent event) { | 4968 public void textChanged(TextChangedEvent event) { |
4843 handleTextChanged(event); | 4969 handleTextChanged(event); |
4847 } | 4973 } |
4848 }; | 4974 }; |
4849 content = new DefaultContent(); | 4975 content = new DefaultContent(); |
4850 content.addTextChangeListener(textChangeListener); | 4976 content.addTextChangeListener(textChangeListener); |
4851 } | 4977 } |
4852 /** | 4978 /** |
4853 * Adds event listeners | 4979 * Adds event listeners |
4854 */ | 4980 */ |
4855 void installListeners() { | 4981 void installListeners() { |
4856 ScrollBar verticalBar = getVerticalBar(); | 4982 ScrollBar verticalBar = getVerticalBar(); |
4857 ScrollBar horizontalBar = getHorizontalBar(); | 4983 ScrollBar horizontalBar = getHorizontalBar(); |
4858 | 4984 |
4859 listener = new Listener() { | 4985 listener = new class() Listener { |
4860 public void handleEvent(Event event) { | 4986 public void handleEvent(Event event) { |
4861 switch (event.type) { | 4987 switch (event.type) { |
4862 case DWT.Dispose: handleDispose(event); break; | 4988 case DWT.Dispose: handleDispose(event); break; |
4863 case DWT.KeyDown: handleKeyDown(event); break; | 4989 case DWT.KeyDown: handleKeyDown(event); break; |
4864 case DWT.KeyUp: handleKeyUp(event); break; | 4990 case DWT.KeyUp: handleKeyUp(event); break; |
4866 case DWT.MouseUp: handleMouseUp(event); break; | 4992 case DWT.MouseUp: handleMouseUp(event); break; |
4867 case DWT.MouseMove: handleMouseMove(event); break; | 4993 case DWT.MouseMove: handleMouseMove(event); break; |
4868 case DWT.Paint: handlePaint(event); break; | 4994 case DWT.Paint: handlePaint(event); break; |
4869 case DWT.Resize: handleResize(event); break; | 4995 case DWT.Resize: handleResize(event); break; |
4870 case DWT.Traverse: handleTraverse(event); break; | 4996 case DWT.Traverse: handleTraverse(event); break; |
4871 } | 4997 default: |
4872 } | 4998 } |
4999 } | |
4873 }; | 5000 }; |
4874 addListener(DWT.Dispose, listener); | 5001 addListener(DWT.Dispose, listener); |
4875 addListener(DWT.KeyDown, listener); | 5002 addListener(DWT.KeyDown, listener); |
4876 addListener(DWT.KeyUp, listener); | 5003 addListener(DWT.KeyUp, listener); |
4877 addListener(DWT.MouseDown, listener); | 5004 addListener(DWT.MouseDown, listener); |
4878 addListener(DWT.MouseUp, listener); | 5005 addListener(DWT.MouseUp, listener); |
4879 addListener(DWT.MouseMove, listener); | 5006 addListener(DWT.MouseMove, listener); |
4880 addListener(DWT.Paint, listener); | 5007 addListener(DWT.Paint, listener); |
4881 addListener(DWT.Resize, listener); | 5008 addListener(DWT.Resize, listener); |
4882 addListener(DWT.Traverse, listener); | 5009 addListener(DWT.Traverse, listener); |
4883 ime.addListener(DWT.ImeComposition, new Listener() { | 5010 ime.addListener(DWT.ImeComposition, new class() Listener { |
4884 public void handleEvent(Event event) { | 5011 public void handleEvent(Event event) { |
4885 switch (event.detail) { | 5012 switch (event.detail) { |
4886 case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; | 5013 case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; |
4887 case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; | 5014 case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; |
4888 case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; | 5015 case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; |
5016 default: | |
4889 } | 5017 } |
4890 } | 5018 } |
4891 }); | 5019 }); |
4892 if (verticalBar !is null) { | 5020 if (verticalBar !is null) { |
4893 verticalBar.addListener(DWT.Selection, new Listener() { | 5021 verticalBar.addListener(DWT.Selection, new class() Listener { |
4894 public void handleEvent(Event event) { | 5022 public void handleEvent(Event event) { |
4895 handleVerticalScroll(event); | 5023 handleVerticalScroll(event); |
4896 } | 5024 } |
4897 }); | 5025 }); |
4898 } | 5026 } |
4899 if (horizontalBar !is null) { | 5027 if (horizontalBar !is null) { |
4900 horizontalBar.addListener(DWT.Selection, new Listener() { | 5028 horizontalBar.addListener(DWT.Selection, new class() Listener { |
4901 public void handleEvent(Event event) { | 5029 public void handleEvent(Event event) { |
4902 handleHorizontalScroll(event); | 5030 handleHorizontalScroll(event); |
4903 } | 5031 } |
4904 }); | 5032 }); |
4905 } | 5033 } |
4928 } | 5056 } |
4929 | 5057 |
4930 TextLayout layout = renderer.getTextLayout(startLine); | 5058 TextLayout layout = renderer.getTextLayout(startLine); |
4931 int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); | 5059 int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); |
4932 int[] offsets = layout.getLineOffsets(); | 5060 int[] offsets = layout.getLineOffsets(); |
4933 int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); | 5061 int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length)); |
4934 | 5062 |
4935 /* Redraw end of line before start line if wrapped and start offset is first char */ | 5063 /* Redraw end of line before start line if wrapped and start offset is first char */ |
4936 if (wordWrap && startIndex > 0 && offsets[startIndex] is start) { | 5064 if (wordWrap && startIndex > 0 && offsets[startIndex] is start) { |
4937 Rectangle rect = layout.getLineBounds(startIndex - 1); | 5065 Rectangle rect = layout.getLineBounds(startIndex - 1); |
4938 rect.x = rect.width; | 5066 rect.x = rect.width; |
4939 rect.width = clientAreaWidth - rightMargin - rect.x; | 5067 rect.width = clientAreaWidth - rightMargin - rect.x; |
4940 rect.x += lineX; | 5068 rect.x += lineX; |
4941 rect.y += startLineY; | 5069 rect.y += startLineY; |
4942 super.redraw(rect.x, rect.y, rect.width, rect.height, false); | 5070 super.redraw(rect.x, rect.y, rect.width, rect.height, false); |
4943 } | 5071 } |
4944 | 5072 |
4945 if (startLine is endLine) { | 5073 if (startLine is endLine) { |
4946 int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); | 5074 int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); |
4947 if (startIndex is endIndex) { | 5075 if (startIndex is endIndex) { |
4948 /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ | 5076 /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ |
4949 Rectangle rect = layout.getBounds(start, end - 1); | 5077 Rectangle rect = layout.getBounds(start, end - 1); |
4950 rect.x += lineX; | 5078 rect.x += lineX; |
4951 rect.y += startLineY; | 5079 rect.y += startLineY; |
4972 if (startLine !is endLine) { | 5100 if (startLine !is endLine) { |
4973 renderer.disposeTextLayout(layout); | 5101 renderer.disposeTextLayout(layout); |
4974 layout = renderer.getTextLayout(endLine); | 5102 layout = renderer.getTextLayout(endLine); |
4975 offsets = layout.getLineOffsets(); | 5103 offsets = layout.getLineOffsets(); |
4976 } | 5104 } |
4977 int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); | 5105 int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); |
4978 Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); | 5106 Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); |
4979 if (endRect.height is 0) { | 5107 if (endRect.height is 0) { |
4980 Rectangle bounds = layout.getLineBounds(endIndex); | 5108 Rectangle bounds = layout.getLineBounds(endIndex); |
4981 endRect.y = bounds.y; | 5109 endRect.y = bounds.y; |
4982 endRect.height = bounds.height; | 5110 endRect.height = bounds.height; |
5004 } | 5132 } |
5005 void handleCompositionChanged(Event event) { | 5133 void handleCompositionChanged(Event event) { |
5006 String text = event.text; | 5134 String text = event.text; |
5007 int start = event.start; | 5135 int start = event.start; |
5008 int end = event.end; | 5136 int end = event.end; |
5009 int length = text.length(); | 5137 int length = text.length; |
5010 if (length is ime.getCommitCount()) { | 5138 if (length is ime.getCommitCount()) { |
5011 content.replaceTextRange(start, end - start, ""); | 5139 content.replaceTextRange(start, end - start, ""); |
5012 caretOffset = start; | 5140 caretOffset = ime.getCompositionOffset(); |
5013 caretWidth = 0; | 5141 caretWidth = 0; |
5014 caretDirection = DWT.NULL; | 5142 caretDirection = DWT.NULL; |
5015 } else { | 5143 } else { |
5016 content.replaceTextRange(start, end - start, text); | 5144 content.replaceTextRange(start, end - start, text); |
5017 caretOffset = ime.getCaretOffset(); | 5145 caretOffset = ime.getCaretOffset(); |
5018 if (ime.getWideCaret()) { | 5146 if (ime.getWideCaret()) { |
5147 start = ime.getCompositionOffset(); | |
5019 int lineIndex = getCaretLine(); | 5148 int lineIndex = getCaretLine(); |
5020 int lineOffset = content.getOffsetAtLine(lineIndex); | 5149 int lineOffset = content.getOffsetAtLine(lineIndex); |
5021 TextLayout layout = renderer.getTextLayout(lineIndex); | 5150 TextLayout layout = renderer.getTextLayout(lineIndex); |
5022 caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; | 5151 caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; |
5023 renderer.disposeTextLayout(layout); | 5152 renderer.disposeTextLayout(layout); |
5024 } | 5153 } |
5025 } | 5154 } |
5026 showCaret(); | 5155 showCaret(); |
5027 } | 5156 } |
5028 /** | 5157 /** |
5029 * Frees resources. | 5158 * Frees resources. |
5030 */ | 5159 */ |
5031 void handleDispose(Event event) { | 5160 void handleDispose(Event event) { |
5032 removeListener(DWT.Dispose, listener); | 5161 removeListener(DWT.Dispose, listener); |
5033 notifyListeners(DWT.Dispose, event); | 5162 notifyListeners(DWT.Dispose, event); |
5065 keyActionMap = null; | 5194 keyActionMap = null; |
5066 background = null; | 5195 background = null; |
5067 foreground = null; | 5196 foreground = null; |
5068 clipboard = null; | 5197 clipboard = null; |
5069 } | 5198 } |
5070 /** | 5199 /** |
5071 * Scrolls the widget horizontally. | 5200 * Scrolls the widget horizontally. |
5072 */ | 5201 */ |
5073 void handleHorizontalScroll(Event event) { | 5202 void handleHorizontalScroll(Event event) { |
5074 int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; | 5203 int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; |
5075 scrollHorizontal(scrollPixel, false); | 5204 scrollHorizontal(scrollPixel, false); |
5099 } | 5228 } |
5100 } | 5229 } |
5101 } | 5230 } |
5102 if (action is DWT.NULL) { | 5231 if (action is DWT.NULL) { |
5103 bool ignore = false; | 5232 bool ignore = false; |
5104 | 5233 |
5105 if (IS_CARBON) { | 5234 if (IS_CARBON) { |
5106 // Ignore accelerator key combinations (we do not want to | 5235 // Ignore accelerator key combinations (we do not want to |
5107 // insert a character in the text in this instance). Do not | 5236 // insert a character in the text in this instance). Do not |
5108 // ignore COMMAND+ALT combinations since that key sequence | 5237 // ignore COMMAND+ALT combinations since that key sequence |
5109 // produces characters on the mac. | 5238 // produces characters on the mac. |
5110 ignore = (event.stateMask ^ DWT.COMMAND) is 0 || | 5239 ignore = (event.stateMask ^ DWT.COMMAND) is 0 || |
5111 (event.stateMask ^ (DWT.COMMAND | DWT.SHIFT)) is 0; | 5240 (event.stateMask ^ (DWT.COMMAND | DWT.SHIFT)) is 0; |
5112 } else if (IS_MOTIF) { | 5241 } else if (IS_MOTIF) { |
5113 // Ignore accelerator key combinations (we do not want to | 5242 // Ignore accelerator key combinations (we do not want to |
5114 // insert a character in the text in this instance). Do not | 5243 // insert a character in the text in this instance). Do not |
5115 // ignore ALT combinations since this key sequence | 5244 // ignore ALT combinations since this key sequence |
5116 // produces characters on motif. | 5245 // produces characters on motif. |
5117 ignore = (event.stateMask ^ DWT.CTRL) is 0 || | 5246 ignore = (event.stateMask ^ DWT.CTRL) is 0 || |
5118 (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; | 5247 (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; |
5119 } else { | 5248 } else { |
5120 // Ignore accelerator key combinations (we do not want to | 5249 // Ignore accelerator key combinations (we do not want to |
5121 // insert a character in the text in this instance). Don't | 5250 // insert a character in the text in this instance). Don't |
5122 // ignore CTRL+ALT combinations since that is the Alt Gr | 5251 // ignore CTRL+ALT combinations since that is the Alt Gr |
5123 // key on some keyboards. See bug 20953. | 5252 // key on some keyboards. See bug 20953. |
5124 ignore = (event.stateMask ^ DWT.ALT) is 0 || | 5253 ignore = (event.stateMask ^ DWT.ALT) is 0 || |
5125 (event.stateMask ^ DWT.CTRL) is 0 || | 5254 (event.stateMask ^ DWT.CTRL) is 0 || |
5126 (event.stateMask ^ (DWT.ALT | DWT.SHIFT)) is 0 || | 5255 (event.stateMask ^ (DWT.ALT | DWT.SHIFT)) is 0 || |
5127 (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; | 5256 (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; |
5128 } | 5257 } |
5129 // -ignore anything below SPACE except for line delimiter keys and tab. | 5258 // -ignore anything below SPACE except for line delimiter keys and tab. |
5130 // -ignore DEL | 5259 // -ignore DEL |
5131 if (!ignore && event.character > 31 && event.character !is DWT.DEL || | 5260 if (!ignore && event.character > 31 && event.character !is DWT.DEL || |
5132 event.character is DWT.CR || event.character is DWT.LF || | 5261 event.character is DWT.CR || event.character is DWT.LF || |
5133 event.character is TAB) { | 5262 event.character is TAB) { |
5134 doContent(event.character); | 5263 doContent(event.character); |
5135 update(); | 5264 update(); |
5136 } | 5265 } |
5137 } else { | 5266 } else { |
5146 */ | 5275 */ |
5147 void handleKeyDown(Event event) { | 5276 void handleKeyDown(Event event) { |
5148 if (clipboardSelection is null) { | 5277 if (clipboardSelection is null) { |
5149 clipboardSelection = new Point(selection.x, selection.y); | 5278 clipboardSelection = new Point(selection.x, selection.y); |
5150 } | 5279 } |
5151 | 5280 |
5152 Event verifyEvent = new Event(); | 5281 Event verifyEvent = new Event(); |
5153 verifyEvent.character = event.character; | 5282 verifyEvent.character = event.character; |
5154 verifyEvent.keyCode = event.keyCode; | 5283 verifyEvent.keyCode = event.keyCode; |
5155 verifyEvent.stateMask = event.stateMask; | 5284 verifyEvent.stateMask = event.stateMask; |
5156 verifyEvent.doit = true; | 5285 verifyEvent.doit = true; |
5170 try { | 5299 try { |
5171 if (selection.y - selection.x > 0) { | 5300 if (selection.y - selection.x > 0) { |
5172 setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); | 5301 setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); |
5173 } | 5302 } |
5174 } catch (DWTError error) { | 5303 } catch (DWTError error) { |
5175 // Copy to clipboard failed. This happens when another application | 5304 // Copy to clipboard failed. This happens when another application |
5176 // is accessing the clipboard while we copy. Ignore the error. | 5305 // is accessing the clipboard while we copy. Ignore the error. |
5177 // Fixes 1GDQAVN | 5306 // Fixes 1GDQAVN |
5178 // Rethrow all other errors. Fixes bug 17578. | 5307 // Rethrow all other errors. Fixes bug 17578. |
5179 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { | 5308 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { |
5180 throw error; | 5309 throw error; |
5182 } | 5311 } |
5183 } | 5312 } |
5184 } | 5313 } |
5185 clipboardSelection = null; | 5314 clipboardSelection = null; |
5186 } | 5315 } |
5187 /** | 5316 /** |
5188 * Updates the caret location and selection if mouse button 1 has been | 5317 * Updates the caret location and selection if mouse button 1 has been |
5189 * pressed. | 5318 * pressed. |
5190 */ | 5319 */ |
5191 void handleMouseDown(Event event) { | 5320 void handleMouseDown(Event event) { |
5192 //force focus (object support) | 5321 //force focus (object support) |
5193 forceFocus(); | 5322 forceFocus(); |
5194 | 5323 |
5195 //drag detect | 5324 //drag detect |
5196 if (dragDetect && checkDragDetect(event)) return; | 5325 if (dragDetect_ && checkDragDetect(event)) return; |
5197 | 5326 |
5198 //paste clipboard selection | 5327 //paste clipboard selection |
5199 if (event.button is 2) { | 5328 if (event.button is 2) { |
5200 String text = cast(String)getClipboardContent(DND.SELECTION_CLIPBOARD); | 5329 auto o = cast(ArrayWrapperString)getClipboardContent(DND.SELECTION_CLIPBOARD); |
5201 if (text !is null && text.length() > 0) { | 5330 String text = o.array; |
5331 if (text !is null && text.length > 0) { | |
5202 // position cursor | 5332 // position cursor |
5203 doMouseLocationChange(event.x, event.y, false); | 5333 doMouseLocationChange(event.x, event.y, false); |
5204 // insert text | 5334 // insert text |
5205 Event e = new Event(); | 5335 Event e = new Event(); |
5206 e.start = selection.x; | 5336 e.start = selection.x; |
5207 e.end = selection.y; | 5337 e.end = selection.y; |
5208 e.text = getModelDelimitedText(text); | 5338 e.text = getModelDelimitedText(text); |
5209 sendKeyEvent(e); | 5339 sendKeyEvent(e); |
5210 } | 5340 } |
5211 } | 5341 } |
5212 | 5342 |
5213 //set selection | 5343 //set selection |
5214 if ((event.button !is 1) || (IS_CARBON && (event.stateMask & DWT.MOD4) !is 0)) { | 5344 if ((event.button !is 1) || (IS_CARBON && (event.stateMask & DWT.MOD4) !is 0)) { |
5215 return; | 5345 return; |
5216 } | 5346 } |
5217 clickCount = event.count; | 5347 clickCount = event.count; |
5218 if (clickCount is 1) { | 5348 if (clickCount is 1) { |
5219 bool select = (event.stateMask & DWT.MOD2) !is 0; | 5349 bool select = (event.stateMask & DWT.MOD2) !is 0; |
5220 doMouseLocationChange(event.x, event.y, select); | 5350 doMouseLocationChange(event.x, event.y, select); |
5243 doMouseSelection(); | 5373 doMouseSelection(); |
5244 doubleClickSelection = new Point(selection.x, selection.y); | 5374 doubleClickSelection = new Point(selection.x, selection.y); |
5245 } | 5375 } |
5246 } | 5376 } |
5247 } | 5377 } |
5248 /** | 5378 /** |
5249 * Updates the caret location and selection if mouse button 1 is pressed | 5379 * Updates the caret location and selection if mouse button 1 is pressed |
5250 * during the mouse move. | 5380 * during the mouse move. |
5251 */ | 5381 */ |
5252 void handleMouseMove(Event event) { | 5382 void handleMouseMove(Event event) { |
5253 if (clickCount is 0) return; | 5383 if (clickCount is 0) return; |
5254 doMouseLocationChange(event.x, event.y, true); | 5384 doMouseLocationChange(event.x, event.y, true); |
5255 update(); | 5385 update(); |
5256 doAutoScroll(event); | 5386 doAutoScroll(event); |
5257 } | 5387 } |
5258 /** | 5388 /** |
5259 * Autoscrolling ends when the mouse button is released. | 5389 * Autoscrolling ends when the mouse button is released. |
5260 */ | 5390 */ |
5261 void handleMouseUp(Event event) { | 5391 void handleMouseUp(Event event) { |
5262 clickCount = 0; | 5392 clickCount = 0; |
5263 endAutoScroll(); | 5393 endAutoScroll(); |
5265 try { | 5395 try { |
5266 if (selection.y - selection.x > 0) { | 5396 if (selection.y - selection.x > 0) { |
5267 setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); | 5397 setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); |
5268 } | 5398 } |
5269 } catch (DWTError error) { | 5399 } catch (DWTError error) { |
5270 // Copy to clipboard failed. This happens when another application | 5400 // Copy to clipboard failed. This happens when another application |
5271 // is accessing the clipboard while we copy. Ignore the error. | 5401 // is accessing the clipboard while we copy. Ignore the error. |
5272 // Fixes 1GDQAVN | 5402 // Fixes 1GDQAVN |
5273 // Rethrow all other errors. Fixes bug 17578. | 5403 // Rethrow all other errors. Fixes bug 17578. |
5274 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { | 5404 if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) { |
5275 throw error; | 5405 throw error; |
5317 if (rightMargin > 0) { | 5447 if (rightMargin > 0) { |
5318 drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight); | 5448 drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight); |
5319 } | 5449 } |
5320 } | 5450 } |
5321 /** | 5451 /** |
5322 * Recalculates the scroll bars. Rewraps all lines when in word | 5452 * Recalculates the scroll bars. Rewraps all lines when in word |
5323 * wrap mode. | 5453 * wrap mode. |
5324 * | 5454 * |
5325 * @param event resize event | 5455 * @param event resize event |
5326 */ | 5456 */ |
5327 void handleResize(Event event) { | 5457 void handleResize(Event event) { |
5331 clientAreaHeight = clientArea.height; | 5461 clientAreaHeight = clientArea.height; |
5332 clientAreaWidth = clientArea.width; | 5462 clientAreaWidth = clientArea.width; |
5333 /* Redraw the old or new right/bottom margin if needed */ | 5463 /* Redraw the old or new right/bottom margin if needed */ |
5334 if (oldWidth !is clientAreaWidth) { | 5464 if (oldWidth !is clientAreaWidth) { |
5335 if (rightMargin > 0) { | 5465 if (rightMargin > 0) { |
5336 int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; | 5466 int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; |
5337 super.redraw(x, 0, rightMargin, oldHeight, false); | 5467 super.redraw(x, 0, rightMargin, oldHeight, false); |
5338 } | 5468 } |
5339 } | 5469 } |
5340 if (oldHeight !is clientAreaHeight) { | 5470 if (oldHeight !is clientAreaHeight) { |
5341 if (bottomMargin > 0) { | 5471 if (bottomMargin > 0) { |
5342 int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; | 5472 int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; |
5343 super.redraw(0, y, oldWidth, bottomMargin, false); | 5473 super.redraw(0, y, oldWidth, bottomMargin, false); |
5344 } | 5474 } |
5345 } | 5475 } |
5346 if (wordWrap) { | 5476 if (wordWrap) { |
5347 if (oldWidth !is clientAreaWidth) { | 5477 if (oldWidth !is clientAreaWidth) { |
5376 // if (oldHeight !is clientAreaHeight || wordWrap) { | 5506 // if (oldHeight !is clientAreaHeight || wordWrap) { |
5377 // calculateTopIndex(0); | 5507 // calculateTopIndex(0); |
5378 // } | 5508 // } |
5379 } | 5509 } |
5380 /** | 5510 /** |
5381 * Updates the caret position and selection and the scroll bars to reflect | 5511 * Updates the caret position and selection and the scroll bars to reflect |
5382 * the content change. | 5512 * the content change. |
5383 */ | 5513 */ |
5384 void handleTextChanged(TextChangedEvent event) { | 5514 void handleTextChanged(TextChangedEvent event) { |
5515 int offset = ime.getCompositionOffset(); | |
5516 if (offset !is -1 && lastTextChangeStart < offset) { | |
5517 ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount); | |
5518 } | |
5385 int firstLine = content.getLineAtOffset(lastTextChangeStart); | 5519 int firstLine = content.getLineAtOffset(lastTextChangeStart); |
5386 resetCache(firstLine, 0); | 5520 resetCache(firstLine, 0); |
5387 if (!isFixedLineHeight() && topIndex > firstLine) { | 5521 if (!isFixedLineHeight() && topIndex > firstLine) { |
5388 topIndex = firstLine; | 5522 topIndex = firstLine; |
5389 topIndexY = 0; | 5523 topIndexY = 0; |
5392 int lastLine = firstLine + lastTextChangeNewLineCount; | 5526 int lastLine = firstLine + lastTextChangeNewLineCount; |
5393 int firstLineTop = getLinePixel(firstLine); | 5527 int firstLineTop = getLinePixel(firstLine); |
5394 int newLastLineBottom = getLinePixel(lastLine + 1); | 5528 int newLastLineBottom = getLinePixel(lastLine + 1); |
5395 if (lastLineBottom !is newLastLineBottom) { | 5529 if (lastLineBottom !is newLastLineBottom) { |
5396 super.redraw(); | 5530 super.redraw(); |
5397 if (wordWrap) setCaretLocation(); | |
5398 } else { | 5531 } else { |
5399 super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); | 5532 super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); |
5400 redrawLinesBullet(renderer.redrawLines); | 5533 redrawLinesBullet(renderer.redrawLines); |
5401 } | 5534 } |
5402 } | 5535 } |
5403 renderer.redrawLines = null; | 5536 renderer.redrawLines = null; |
5404 // update selection/caret location after styles have been changed. | 5537 // update selection/caret location after styles have been changed. |
5405 // otherwise any text measuring could be incorrect | 5538 // otherwise any text measuring could be incorrect |
5406 // | 5539 // |
5407 // also, this needs to be done after all scrolling. Otherwise, | 5540 // also, this needs to be done after all scrolling. Otherwise, |
5408 // selection redraw would be flushed during scroll which is wrong. | 5541 // selection redraw would be flushed during scroll which is wrong. |
5409 // in some cases new text would be drawn in scroll source area even | 5542 // in some cases new text would be drawn in scroll source area even |
5410 // though the intent is to scroll it. | 5543 // though the intent is to scroll it. |
5411 updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); | 5544 updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); |
5412 if (lastTextChangeReplaceLineCount > 0 || wordWrap) { | 5545 if (lastTextChangeReplaceLineCount > 0 || wordWrap) { |
5413 claimBottomFreeSpace(); | 5546 claimBottomFreeSpace(); |
5414 } | 5547 } |
5418 } | 5551 } |
5419 /** | 5552 /** |
5420 * Updates the screen to reflect a pending content change. | 5553 * Updates the screen to reflect a pending content change. |
5421 * | 5554 * |
5422 * @param event .start the start offset of the change | 5555 * @param event .start the start offset of the change |
5423 * @param event .newText text that is going to be inserted or empty String | 5556 * @param event .newText text that is going to be inserted or empty String |
5424 * if no text will be inserted | 5557 * if no text will be inserted |
5425 * @param event .replaceCharCount length of text that is going to be replaced | 5558 * @param event .replaceCharCount length of text that is going to be replaced |
5426 * @param event .newCharCount length of text that is going to be inserted | 5559 * @param event .newCharCount length of text that is going to be inserted |
5427 * @param event .replaceLineCount number of lines that are going to be replaced | 5560 * @param event .replaceLineCount number of lines that are going to be replaced |
5428 * @param event .newLineCount number of new lines that are going to be inserted | 5561 * @param event .newLineCount number of new lines that are going to be inserted |
5434 } | 5567 } |
5435 lastTextChangeStart = event.start; | 5568 lastTextChangeStart = event.start; |
5436 lastTextChangeNewLineCount = event.newLineCount; | 5569 lastTextChangeNewLineCount = event.newLineCount; |
5437 lastTextChangeNewCharCount = event.newCharCount; | 5570 lastTextChangeNewCharCount = event.newCharCount; |
5438 lastTextChangeReplaceLineCount = event.replaceLineCount; | 5571 lastTextChangeReplaceLineCount = event.replaceLineCount; |
5439 lastTextChangeReplaceCharCount = event.replaceCharCount; | 5572 lastTextChangeReplaceCharCount = event.replaceCharCount; |
5440 int lineIndex = content.getLineAtOffset(event.start); | 5573 int lineIndex = content.getLineAtOffset(event.start); |
5441 int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); | 5574 int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); |
5442 int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); | 5575 int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); |
5443 lastLineBottom = destY; | 5576 lastLineBottom = destY; |
5444 if (srcY < 0 && destY < 0) { | 5577 if (srcY < 0 && destY < 0) { |
5449 } else { | 5582 } else { |
5450 scrollText(srcY, destY); | 5583 scrollText(srcY, destY); |
5451 } | 5584 } |
5452 | 5585 |
5453 renderer.textChanging(event); | 5586 renderer.textChanging(event); |
5454 | 5587 |
5455 // Update the caret offset if it is greater than the length of the content. | 5588 // Update the caret offset if it is greater than the length of the content. |
5456 // This is necessary since style range API may be called between the | 5589 // This is necessary since style range API may be called between the |
5457 // handleTextChanging and handleTextChanged events and this API sets the | 5590 // handleTextChanging and handleTextChanged events and this API sets the |
5458 // caretOffset. | 5591 // caretOffset. |
5459 int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; | 5592 int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; |
5460 if (caretOffset > newEndOfText) caretOffset = newEndOfText; | 5593 if (caretOffset > newEndOfText) caretOffset = newEndOfText; |
5461 } | 5594 } |
5462 /** | 5595 /** |
5463 * Called when the widget content is set programmatically, overwriting | 5596 * Called when the widget content is set programmatically, overwriting |
5464 * the old content. Resets the caret position, selection and scroll offsets. | 5597 * the old content. Resets the caret position, selection and scroll offsets. |
5465 * Recalculates the content width and scroll bars. Redraws the widget. | 5598 * Recalculates the content width and scroll bars. Redraws the widget. |
5466 * | 5599 * |
5467 * @param event text change event. | 5600 * @param event text change event. |
5468 */ | 5601 */ |
5469 void handleTextSet(TextChangedEvent event) { | 5602 void handleTextSet(TextChangedEvent event) { |
5470 reset(); | 5603 reset(); |
5471 } | 5604 } |
5472 /** | 5605 /** |
5473 * Called when a traversal key is pressed. | 5606 * Called when a traversal key is pressed. |
5474 * Allow tab next traversal to occur when the widget is in single | 5607 * Allow tab next traversal to occur when the widget is in single |
5475 * line mode or in multi line and non-editable mode . | 5608 * line mode or in multi line and non-editable mode . |
5476 * When in editable multi line mode we want to prevent the tab | 5609 * When in editable multi line mode we want to prevent the tab |
5477 * traversal and receive the tab key event instead. | 5610 * traversal and receive the tab key event instead. |
5478 * | 5611 * |
5479 * @param event the event | 5612 * @param event the event |
5480 */ | 5613 */ |
5481 void handleTraverse(Event event) { | 5614 void handleTraverse(Event event) { |
5494 if (!editable || (event.stateMask & DWT.MODIFIER_MASK) !is 0) { | 5627 if (!editable || (event.stateMask & DWT.MODIFIER_MASK) !is 0) { |
5495 event.doit = true; | 5628 event.doit = true; |
5496 } | 5629 } |
5497 } | 5630 } |
5498 break; | 5631 break; |
5499 } | 5632 default: |
5500 } | 5633 } |
5501 /** | 5634 } |
5635 /** | |
5502 * Scrolls the widget vertically. | 5636 * Scrolls the widget vertically. |
5503 */ | 5637 */ |
5504 void handleVerticalScroll(Event event) { | 5638 void handleVerticalScroll(Event event) { |
5505 int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset(); | 5639 int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset(); |
5506 scrollVertical(scrollPixel, false); | 5640 scrollVertical(scrollPixel, false); |
5508 /** | 5642 /** |
5509 * Add accessibility support for the widget. | 5643 * Add accessibility support for the widget. |
5510 */ | 5644 */ |
5511 void initializeAccessible() { | 5645 void initializeAccessible() { |
5512 final Accessible accessible = getAccessible(); | 5646 final Accessible accessible = getAccessible(); |
5513 accessible.addAccessibleListener(new AccessibleAdapter() { | 5647 accessible.addAccessibleListener(new class() AccessibleAdapter { |
5514 public void getName (AccessibleEvent e) { | 5648 public void getName (AccessibleEvent e) { |
5515 String name = null; | 5649 String name = null; |
5516 Label label = getAssociatedLabel (); | 5650 Label label = getAssociatedLabel (); |
5517 if (label !is null) { | 5651 if (label !is null) { |
5518 name = stripMnemonic (label.getText()); | 5652 name = stripMnemonic (label.getText()); |
5526 String shortcut = null; | 5660 String shortcut = null; |
5527 Label label = getAssociatedLabel (); | 5661 Label label = getAssociatedLabel (); |
5528 if (label !is null) { | 5662 if (label !is null) { |
5529 String text = label.getText (); | 5663 String text = label.getText (); |
5530 if (text !is null) { | 5664 if (text !is null) { |
5531 char mnemonic = _findMnemonic (text); | 5665 dchar mnemonic = _findMnemonic (text); |
5532 if (mnemonic !is '\0') { | 5666 if (mnemonic !is '\0') { |
5533 shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ | 5667 shortcut = "Alt+"~tango.text.convert.Utf.toString( [mnemonic] ); //$NON-NLS-1$ |
5534 } | 5668 } |
5535 } | 5669 } |
5536 } | 5670 } |
5537 e.result = shortcut; | 5671 e.result = shortcut; |
5538 } | 5672 } |
5539 }); | 5673 }); |
5540 accessible.addAccessibleTextListener(new AccessibleTextAdapter() { | 5674 accessible.addAccessibleTextListener(new class() AccessibleTextAdapter { |
5541 public void getCaretOffset(AccessibleTextEvent e) { | 5675 public void getCaretOffset(AccessibleTextEvent e) { |
5542 e.offset = StyledText.this.getCaretOffset(); | 5676 e.offset = this.outer.getCaretOffset(); |
5543 } | 5677 } |
5544 public void getSelectionRange(AccessibleTextEvent e) { | 5678 public void getSelectionRange(AccessibleTextEvent e) { |
5545 Point selection = StyledText.this.getSelectionRange(); | 5679 Point selection = this.outer.getSelectionRange(); |
5546 e.offset = selection.x; | 5680 e.offset = selection.x; |
5547 e.length = selection.y; | 5681 e.length = selection.y; |
5548 } | 5682 } |
5549 }); | 5683 }); |
5550 accessible.addAccessibleControlListener(new AccessibleControlAdapter() { | 5684 accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { |
5551 public void getRole(AccessibleControlEvent e) { | 5685 public void getRole(AccessibleControlEvent e) { |
5552 e.detail = ACC.ROLE_TEXT; | 5686 e.detail = ACC.ROLE_TEXT; |
5553 } | 5687 } |
5554 public void getState(AccessibleControlEvent e) { | 5688 public void getState(AccessibleControlEvent e) { |
5555 int state = 0; | 5689 int state = 0; |
5558 if (!isVisible()) state |= ACC.STATE_INVISIBLE; | 5692 if (!isVisible()) state |= ACC.STATE_INVISIBLE; |
5559 if (!getEditable()) state |= ACC.STATE_READONLY; | 5693 if (!getEditable()) state |= ACC.STATE_READONLY; |
5560 e.detail = state; | 5694 e.detail = state; |
5561 } | 5695 } |
5562 public void getValue(AccessibleControlEvent e) { | 5696 public void getValue(AccessibleControlEvent e) { |
5563 e.result = StyledText.this.getText(); | 5697 e.result = this.outer.getText(); |
5564 } | 5698 } |
5565 }); | 5699 }); |
5566 addListener(DWT.FocusIn, new Listener() { | 5700 addListener(DWT.FocusIn, new class(accessible) Listener { |
5701 Accessible acc; | |
5702 this( Accessible acc ){ this.acc = acc; } | |
5567 public void handleEvent(Event event) { | 5703 public void handleEvent(Event event) { |
5568 accessible.setFocus(ACC.CHILDID_SELF); | 5704 acc.setFocus(ACC.CHILDID_SELF); |
5569 } | 5705 } |
5570 }); | 5706 }); |
5571 } | 5707 } |
5572 /* | 5708 /* |
5573 * Return the Label immediately preceding the receiver in the z-order, | 5709 * Return the Label immediately preceding the receiver in the z-order, |
5574 * or null if none. | 5710 * or null if none. |
5575 */ | 5711 */ |
5576 Label getAssociatedLabel () { | 5712 Label getAssociatedLabel () { |
5577 Control[] siblings = getParent ().getChildren (); | 5713 Control[] siblings = getParent ().getChildren (); |
5578 for (int i = 0; i < siblings.length; i++) { | 5714 for (int i = 0; i < siblings.length; i++) { |
5579 if (siblings [i] is StyledText.this) { | 5715 if (siblings [i] is this) { |
5580 if (i > 0 && siblings [i-1] instanceof Label) { | 5716 if (i > 0 && ( null !is cast(Label)siblings [i-1])) { |
5581 return cast(Label) siblings [i-1]; | 5717 return cast(Label) siblings [i-1]; |
5582 } | 5718 } |
5583 } | 5719 } |
5584 } | 5720 } |
5585 return null; | 5721 return null; |
5586 } | 5722 } |
5587 String stripMnemonic (String String) { | 5723 String stripMnemonic (String string) { |
5588 int index = 0; | 5724 int index = 0; |
5589 int length = String.length (); | 5725 int length_ = string.length; |
5590 do { | 5726 do { |
5591 while ((index < length) && (String.charAt (index) !is '&')) index++; | 5727 while ((index < length_) && (string[index] !is '&')) index++; |
5592 if (++index >= length) return String; | 5728 if (++index >= length_) return string; |
5593 if (String.charAt (index) !is '&') { | 5729 if (string[index] !is '&') { |
5594 return String.substring(0, index-1) + String.substring(index, length); | 5730 return string.substring(0, index-1) ~ string.substring(index, length_); |
5595 } | 5731 } |
5596 index++; | 5732 index++; |
5597 } while (index < length); | 5733 } while (index < length_); |
5598 return String; | 5734 return string; |
5599 } | 5735 } |
5600 /* | 5736 /* |
5601 * Return the lowercase of the first non-'&' character following | 5737 * Return the lowercase of the first non-'&' character following |
5602 * an '&' character in the given String. If there are no '&' | 5738 * an '&' character in the given string. If there are no '&' |
5603 * characters in the given String, return '\0'. | 5739 * characters in the given string, return '\0'. |
5604 */ | 5740 */ |
5605 char _findMnemonic (String String) { | 5741 dchar _findMnemonic (String string) { |
5606 if (String is null) return '\0'; | 5742 if (string is null) return '\0'; |
5607 int index = 0; | 5743 int index = 0; |
5608 int length = String.length (); | 5744 int length_ = string.length; |
5609 do { | 5745 do { |
5610 while (index < length && String.charAt (index) !is '&') index++; | 5746 while (index < length_ && string[index] !is '&') index++; |
5611 if (++index >= length) return '\0'; | 5747 if (++index >= length_) return '\0'; |
5612 if (String.charAt (index) !is '&') return Character.toLowerCase (String.charAt (index)); | 5748 if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] ); |
5613 index++; | 5749 index++; |
5614 } while (index < length); | 5750 } while (index < length_); |
5615 return '\0'; | 5751 return '\0'; |
5616 } | 5752 } |
5617 /** | 5753 /** |
5618 * Executes the action. | 5754 * Executes the action. |
5619 * | 5755 * |
5678 break; | 5814 break; |
5679 case ST.WINDOW_END: | 5815 case ST.WINDOW_END: |
5680 doPageEnd(); | 5816 doPageEnd(); |
5681 clearSelection(true); | 5817 clearSelection(true); |
5682 break; | 5818 break; |
5683 // Selection | 5819 // Selection |
5684 case ST.SELECT_LINE_UP: | 5820 case ST.SELECT_LINE_UP: |
5685 doSelectionLineUp(); | 5821 doSelectionLineUp(); |
5686 break; | 5822 break; |
5687 case ST.SELECT_ALL: | 5823 case ST.SELECT_ALL: |
5688 selectAll(); | 5824 selectAll(); |
5734 break; | 5870 break; |
5735 case ST.SELECT_WINDOW_END: | 5871 case ST.SELECT_WINDOW_END: |
5736 doPageEnd(); | 5872 doPageEnd(); |
5737 doSelection(ST.COLUMN_NEXT); | 5873 doSelection(ST.COLUMN_NEXT); |
5738 break; | 5874 break; |
5739 // Modification | 5875 // Modification |
5740 case ST.CUT: | 5876 case ST.CUT: |
5741 cut(); | 5877 cut(); |
5742 break; | 5878 break; |
5743 case ST.COPY: | 5879 case ST.COPY: |
5744 copy(); | 5880 copy(); |
5760 break; | 5896 break; |
5761 // Miscellaneous | 5897 // Miscellaneous |
5762 case ST.TOGGLE_OVERWRITE: | 5898 case ST.TOGGLE_OVERWRITE: |
5763 overwrite = !overwrite; // toggle insert/overwrite mode | 5899 overwrite = !overwrite; // toggle insert/overwrite mode |
5764 break; | 5900 break; |
5901 default: | |
5765 } | 5902 } |
5766 } | 5903 } |
5767 /** | 5904 /** |
5768 * Temporary until DWT provides this | 5905 * Temporary until DWT provides this |
5769 */ | 5906 */ |
5770 bool isBidi() { | 5907 bool isBidi() { |
5771 return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored; | 5908 return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_; |
5772 } | 5909 } |
5773 bool isBidiCaret() { | 5910 bool isBidiCaret() { |
5774 return BidiUtil.isBidiPlatform(); | 5911 return BidiUtil.isBidiPlatform(); |
5775 } | 5912 } |
5776 bool isFixedLineHeight() { | 5913 bool isFixedLineHeight() { |
5777 return fixedLineHeight; | 5914 return fixedLineHeight; |
5778 } | 5915 } |
5779 /** | 5916 /** |
5780 * Returns whether the given offset is inside a multi byte line delimiter. | 5917 * Returns whether the given offset is inside a multi byte line delimiter. |
5781 * Example: | 5918 * Example: |
5782 * "Line1\r\n" isLineDelimiter(5) is false but isLineDelimiter(6) is true | 5919 * "Line1\r\n" isLineDelimiter(5) is false but isLineDelimiter(6) is true |
5783 * | 5920 * |
5784 * @return true if the given offset is inside a multi byte line delimiter. | 5921 * @return true if the given offset is inside a multi byte line delimiter. |
5785 * false if the given offset is before or after a line delimiter. | 5922 * false if the given offset is before or after a line delimiter. |
5786 */ | 5923 */ |
5787 bool isLineDelimiter(int offset) { | 5924 bool isLineDelimiter(int offset) { |
5788 int line = content.getLineAtOffset(offset); | 5925 int line = content.getLineAtOffset(offset); |
5789 int lineOffset = content.getOffsetAtLine(line); | 5926 int lineOffset = content.getOffsetAtLine(line); |
5790 int offsetInLine = offset - lineOffset; | 5927 int offsetInLine = offset - lineOffset; |
5791 // offsetInLine will be greater than line length if the line | 5928 // offsetInLine will be greater than line length if the line |
5792 // delimiter is longer than one character and the offset is set | 5929 // delimiter is longer than one character and the offset is set |
5793 // in between parts of the line delimiter. | 5930 // in between parts of the line delimiter. |
5794 return offsetInLine > content.getLine(line).length(); | 5931 return offsetInLine > content.getLine(line).length; |
5795 } | 5932 } |
5796 /** | 5933 /** |
5797 * Returns whether the widget is mirrored (right oriented/right to left | 5934 * Returns whether the widget is mirrored (right oriented/right to left |
5798 * writing order). | 5935 * writing order). |
5799 * | 5936 * |
5800 * @return isMirrored true=the widget is right oriented, false=the widget | 5937 * @return isMirrored true=the widget is right oriented, false=the widget |
5801 * is left oriented | 5938 * is left oriented |
5802 */ | 5939 */ |
5803 bool isMirrored() { | 5940 bool isMirrored() { |
5804 return isMirrored; | 5941 return isMirrored_; |
5805 } | 5942 } |
5806 /** | 5943 /** |
5807 * Returns whether the widget can have only one line. | 5944 * Returns whether the widget can have only one line. |
5808 * | 5945 * |
5809 * @return true if widget can have only one line, false if widget can have | 5946 * @return true if widget can have only one line, false if widget can have |
5810 * multiple lines | 5947 * multiple lines |
5811 */ | 5948 */ |
5812 bool isSingleLine() { | 5949 bool isSingleLine() { |
5813 return (getStyle() & DWT.SINGLE) !is 0; | 5950 return (getStyle() & DWT.SINGLE) !is 0; |
5814 } | 5951 } |
5815 /** | 5952 /** |
5816 * Sends the specified verify event, replace/insert text as defined by | 5953 * Sends the specified verify event, replace/insert text as defined by |
5817 * the event and send a modify event. | 5954 * the event and send a modify event. |
5818 * | 5955 * |
5819 * @param event the text change event. | 5956 * @param event the text change event. |
5820 * <ul> | 5957 * <ul> |
5821 * <li>event.start - the replace start offset</li> | 5958 * <li>event.start - the replace start offset</li> |
5822 * <li>event.end - the replace end offset</li> | 5959 * <li>event.end - the replace end offset</li> |
5823 * <li>event.text - the new text</li> | 5960 * <li>event.text - the new text</li> |
5824 * </ul> | 5961 * </ul> |
5832 StyledTextEvent styledTextEvent = null; | 5969 StyledTextEvent styledTextEvent = null; |
5833 int replacedLength = event.end - event.start; | 5970 int replacedLength = event.end - event.start; |
5834 if (isListening(ExtendedModify)) { | 5971 if (isListening(ExtendedModify)) { |
5835 styledTextEvent = new StyledTextEvent(content); | 5972 styledTextEvent = new StyledTextEvent(content); |
5836 styledTextEvent.start = event.start; | 5973 styledTextEvent.start = event.start; |
5837 styledTextEvent.end = event.start + event.text.length(); | 5974 styledTextEvent.end = event.start + event.text.length; |
5838 styledTextEvent.text = content.getTextRange(event.start, replacedLength); | 5975 styledTextEvent.text = content.getTextRange(event.start, replacedLength); |
5839 } | 5976 } |
5840 if (updateCaret) { | 5977 if (updateCaret) { |
5841 //Fix advancing flag for delete/backspace key on direction boundary | 5978 //Fix advancing flag for delete/backspace key on direction boundary |
5842 if (event.text.length() is 0) { | 5979 if (event.text.length is 0) { |
5843 int lineIndex = content.getLineAtOffset(event.start); | 5980 int lineIndex = content.getLineAtOffset(event.start); |
5844 int lineOffset = content.getOffsetAtLine(lineIndex); | 5981 int lineOffset = content.getOffsetAtLine(lineIndex); |
5845 TextLayout layout = renderer.getTextLayout(lineIndex); | 5982 TextLayout layout = renderer.getTextLayout(lineIndex); |
5846 int levelStart = layout.getLevel(event.start - lineOffset); | 5983 int levelStart = layout.getLevel(event.start - lineOffset); |
5847 int lineIndexEnd = content.getLineAtOffset(event.end); | 5984 int lineIndexEnd = content.getLineAtOffset(event.end); |
5862 content.replaceTextRange(event.start, replacedLength, event.text); | 5999 content.replaceTextRange(event.start, replacedLength, event.text); |
5863 // set the caret position prior to sending the modify event. | 6000 // set the caret position prior to sending the modify event. |
5864 // fixes 1GBB8NJ | 6001 // fixes 1GBB8NJ |
5865 if (updateCaret) { | 6002 if (updateCaret) { |
5866 // always update the caret location. fixes 1G8FODP | 6003 // always update the caret location. fixes 1G8FODP |
5867 setSelection(event.start + event.text.length(), 0, true); | 6004 setSelection(event.start + event.text.length, 0, true); |
5868 showCaret(); | 6005 showCaret(); |
5869 } | 6006 } |
5870 sendModifyEvent(event); | 6007 sendModifyEvent(event); |
5871 if (isListening(ExtendedModify)) { | 6008 if (isListening(ExtendedModify)) { |
5872 notifyListeners(ExtendedModify, styledTextEvent); | 6009 notifyListeners(ExtendedModify, styledTextEvent); |
5885 event.bullet = bullet; | 6022 event.bullet = bullet; |
5886 event.bulletIndex = bulletIndex; | 6023 event.bulletIndex = bulletIndex; |
5887 notifyListeners(PaintObject, event); | 6024 notifyListeners(PaintObject, event); |
5888 } | 6025 } |
5889 } | 6026 } |
5890 /** | 6027 /** |
5891 * Replaces the selection with the text on the <code>DND.CLIPBOARD</code> | 6028 * Replaces the selection with the text on the <code>DND.CLIPBOARD</code> |
5892 * clipboard or, if there is no selection, inserts the text at the current | 6029 * clipboard or, if there is no selection, inserts the text at the current |
5893 * caret offset. If the widget has the DWT.SINGLE style and the | 6030 * caret offset. If the widget has the DWT.SINGLE style and the |
5894 * clipboard text contains more than one line, only the first line without | 6031 * clipboard text contains more than one line, only the first line without |
5895 * line delimiters is inserted in the widget. | 6032 * line delimiters is inserted in the widget. |
5896 * | 6033 * |
5897 * @exception DWTException <ul> | 6034 * @exception DWTException <ul> |
5898 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6035 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5899 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6036 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5900 * </ul> | 6037 * </ul> |
5901 */ | 6038 */ |
5902 public void paste(){ | 6039 public void paste(){ |
5903 checkWidget(); | 6040 checkWidget(); |
5904 String text = cast(String) getClipboardContent(DND.CLIPBOARD); | 6041 String text = null; |
5905 if (text !is null && text.length() > 0) { | 6042 if( auto o = cast(ArrayWrapperString) getClipboardContent(DND.CLIPBOARD)){ |
6043 text = o.array; | |
6044 } | |
6045 if (text !is null && text.length > 0) { | |
5906 Event event = new Event(); | 6046 Event event = new Event(); |
5907 event.start = selection.x; | 6047 event.start = selection.x; |
5908 event.end = selection.y; | 6048 event.end = selection.y; |
5909 event.text = getModelDelimitedText(text); | 6049 event.text = getModelDelimitedText(text); |
5910 sendKeyEvent(event); | 6050 sendKeyEvent(event); |
5911 } | 6051 } |
5912 } | 6052 } |
5913 /** | 6053 /** |
5914 * Prints the widget's text to the default printer. | 6054 * Prints the widget's text to the default printer. |
5915 * | 6055 * |
5916 * @exception DWTException <ul> | 6056 * @exception DWTException <ul> |
5917 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6057 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5918 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6058 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5923 Printer printer = new Printer(); | 6063 Printer printer = new Printer(); |
5924 StyledTextPrintOptions options = new StyledTextPrintOptions(); | 6064 StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5925 options.printTextForeground = true; | 6065 options.printTextForeground = true; |
5926 options.printTextBackground = true; | 6066 options.printTextBackground = true; |
5927 options.printTextFontStyle = true; | 6067 options.printTextFontStyle = true; |
5928 options.printLineBackground = true; | 6068 options.printLineBackground = true; |
5929 new Printing(this, printer, options).run(); | 6069 (new Printing(this, printer, options)).run(); |
5930 printer.dispose(); | 6070 printer.dispose(); |
5931 } | 6071 } |
5932 /** | 6072 /** |
5933 * Returns a runnable that will print the widget's text | 6073 * Returns a runnable that will print the widget's text |
5934 * to the specified printer. | 6074 * to the specified printer. |
5935 * <p> | 6075 * <p> |
5936 * The runnable may be run in a non-UI thread. | 6076 * The runnable may be run in a non-UI thread. |
5937 * </p> | 6077 * </p> |
5938 * | 6078 * |
5939 * @param printer the printer to print to | 6079 * @param printer the printer to print to |
6080 * | |
6081 * @return a <code>Runnable</code> for printing the receiver's text | |
6082 * | |
5940 * @exception DWTException <ul> | 6083 * @exception DWTException <ul> |
5941 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6084 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5942 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6085 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5943 * </ul> | 6086 * </ul> |
5944 * @exception IllegalArgumentException <ul> | 6087 * @exception IllegalArgumentException <ul> |
5945 * <li>ERROR_NULL_ARGUMENT when printer is null</li> | 6088 * <li>ERROR_NULL_ARGUMENT when printer is null</li> |
5946 * </ul> | 6089 * </ul> |
5947 */ | 6090 */ |
5948 public Runnable print(Printer printer) { | 6091 public Runnable print(Printer printer) { |
5949 checkWidget(); | 6092 checkWidget(); |
5950 if (printer is null) { | 6093 if (printer is null) { |
5951 DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6094 DWT.error(DWT.ERROR_NULL_ARGUMENT); |
5952 } | 6095 } |
5953 StyledTextPrintOptions options = new StyledTextPrintOptions(); | 6096 StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5954 options.printTextForeground = true; | 6097 options.printTextForeground = true; |
5955 options.printTextBackground = true; | 6098 options.printTextBackground = true; |
5956 options.printTextFontStyle = true; | 6099 options.printTextFontStyle = true; |
5957 options.printLineBackground = true; | 6100 options.printLineBackground = true; |
5958 return print(printer, options); | 6101 return print(printer, options); |
5959 } | 6102 } |
5960 /** | 6103 /** |
5961 * Returns a runnable that will print the widget's text | 6104 * Returns a runnable that will print the widget's text |
5962 * to the specified printer. | 6105 * to the specified printer. |
5963 * <p> | 6106 * <p> |
5964 * The runnable may be run in a non-UI thread. | 6107 * The runnable may be run in a non-UI thread. |
5965 * </p> | 6108 * </p> |
5966 * | 6109 * |
5967 * @param printer the printer to print to | 6110 * @param printer the printer to print to |
5968 * @param options print options to use during printing | 6111 * @param options print options to use during printing |
6112 * | |
6113 * @return a <code>Runnable</code> for printing the receiver's text | |
6114 * | |
5969 * @exception DWTException <ul> | 6115 * @exception DWTException <ul> |
5970 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6116 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5971 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6117 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5972 * </ul> | 6118 * </ul> |
5973 * @exception IllegalArgumentException <ul> | 6119 * @exception IllegalArgumentException <ul> |
5986 * Causes the entire bounds of the receiver to be marked | 6132 * Causes the entire bounds of the receiver to be marked |
5987 * as needing to be redrawn. The next time a paint request | 6133 * as needing to be redrawn. The next time a paint request |
5988 * is processed, the control will be completely painted. | 6134 * is processed, the control will be completely painted. |
5989 * <p> | 6135 * <p> |
5990 * Recalculates the content width for all lines in the bounds. | 6136 * Recalculates the content width for all lines in the bounds. |
5991 * When a <code>LineStyleListener</code> is used a redraw call | 6137 * When a <code>LineStyleListener</code> is used a redraw call |
5992 * is the only notification to the widget that styles have changed | 6138 * is the only notification to the widget that styles have changed |
5993 * and that the content width may have changed. | 6139 * and that the content width may have changed. |
5994 * </p> | 6140 * </p> |
5995 * | 6141 * |
5996 * @exception DWTException <ul> | 6142 * @exception DWTException <ul> |
5997 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6143 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5998 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6144 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5999 * </ul> | 6145 * </ul> |
6000 * | 6146 * |
6001 * @see Control#update() | 6147 * @see Control#update() |
6002 */ | 6148 */ |
6003 public void redraw() { | 6149 public override void redraw() { |
6004 super.redraw(); | 6150 super.redraw(); |
6005 int itemCount = getPartialBottomIndex() - topIndex + 1; | 6151 int itemCount = getPartialBottomIndex() - topIndex + 1; |
6006 renderer.reset(topIndex, itemCount); | 6152 renderer.reset(topIndex, itemCount); |
6007 renderer.calculate(topIndex, itemCount); | 6153 renderer.calculate(topIndex, itemCount); |
6008 setScrollBars(false); | 6154 setScrollBars(false); |
6009 } | 6155 } |
6010 /** | 6156 /** |
6011 * Causes the rectangular area of the receiver specified by | 6157 * Causes the rectangular area of the receiver specified by |
6012 * the arguments to be marked as needing to be redrawn. | 6158 * the arguments to be marked as needing to be redrawn. |
6013 * The next time a paint request is processed, that area of | 6159 * The next time a paint request is processed, that area of |
6014 * the receiver will be painted. If the <code>all</code> flag | 6160 * the receiver will be painted. If the <code>all</code> flag |
6015 * is <code>true</code>, any children of the receiver which | 6161 * is <code>true</code>, any children of the receiver which |
6016 * intersect with the specified area will also paint their | 6162 * intersect with the specified area will also paint their |
6017 * intersecting areas. If the <code>all</code> flag is | 6163 * intersecting areas. If the <code>all</code> flag is |
6018 * <code>false</code>, the children will not be painted. | 6164 * <code>false</code>, the children will not be painted. |
6019 * <p> | 6165 * <p> |
6020 * Marks the content width of all lines in the specified rectangle | 6166 * Marks the content width of all lines in the specified rectangle |
6021 * as unknown. Recalculates the content width of all visible lines. | 6167 * as unknown. Recalculates the content width of all visible lines. |
6022 * When a <code>LineStyleListener</code> is used a redraw call | 6168 * When a <code>LineStyleListener</code> is used a redraw call |
6023 * is the only notification to the widget that styles have changed | 6169 * is the only notification to the widget that styles have changed |
6024 * and that the content width may have changed. | 6170 * and that the content width may have changed. |
6025 * </p> | 6171 * </p> |
6026 * | 6172 * |
6027 * @param x the x coordinate of the area to draw | 6173 * @param x the x coordinate of the area to draw |
6028 * @param y the y coordinate of the area to draw | 6174 * @param y the y coordinate of the area to draw |
6035 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6181 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6036 * </ul> | 6182 * </ul> |
6037 * | 6183 * |
6038 * @see Control#update() | 6184 * @see Control#update() |
6039 */ | 6185 */ |
6040 public void redraw(int x, int y, int width, int height, bool all) { | 6186 public override void redraw(int x, int y, int width, int height, bool all) { |
6041 super.redraw(x, y, width, height, all); | 6187 super.redraw(x, y, width, height, all); |
6042 if (height > 0) { | 6188 if (height > 0) { |
6043 int firstLine = getLineIndex(y); | 6189 int firstLine = getLineIndex(y); |
6044 int lastLine = getLineIndex(y + height); | 6190 int lastLine = getLineIndex(y + height); |
6045 resetCache(firstLine, lastLine - firstLine + 1); | 6191 resetCache(firstLine, lastLine - firstLine + 1); |
6046 } | 6192 } |
6047 } | 6193 } |
6048 void redrawLines(int startLine, int lineCount) { | 6194 void redrawLines(int startLine, int lineCount) { |
6049 // do nothing if redraw range is completely invisible | 6195 // do nothing if redraw range is completely invisible |
6050 int partialBottomIndex = getPartialBottomIndex(); | 6196 int partialBottomIndex = getPartialBottomIndex(); |
6051 if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { | 6197 if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { |
6052 return; | 6198 return; |
6053 } | 6199 } |
6054 // only redraw visible lines | 6200 // only redraw visible lines |
6060 lineCount = partialBottomIndex - startLine + 1; | 6206 lineCount = partialBottomIndex - startLine + 1; |
6061 } | 6207 } |
6062 startLine -= topIndex; | 6208 startLine -= topIndex; |
6063 int redrawTop = getLinePixel(startLine); | 6209 int redrawTop = getLinePixel(startLine); |
6064 int redrawBottom = getLinePixel(startLine + lineCount); | 6210 int redrawBottom = getLinePixel(startLine + lineCount); |
6065 int redrawWidth = clientAreaWidth - leftMargin - rightMargin; | 6211 int redrawWidth = clientAreaWidth - leftMargin - rightMargin; |
6066 super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); | 6212 super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); |
6067 } | 6213 } |
6068 void redrawLinesBullet (int[] redrawLines) { | 6214 void redrawLinesBullet (int[] redrawLines) { |
6069 if (redrawLines is null) return; | 6215 if (redrawLines is null) return; |
6070 int topIndex = getPartialTopIndex(); | 6216 int topIndex = getPartialTopIndex(); |
6083 int height = renderer.getLineHeight(lineIndex); | 6229 int height = renderer.getLineHeight(lineIndex); |
6084 int y = getLinePixel(lineIndex); | 6230 int y = getLinePixel(lineIndex); |
6085 super.redraw(0, y, width, height, false); | 6231 super.redraw(0, y, width, height, false); |
6086 } | 6232 } |
6087 } | 6233 } |
6088 /** | 6234 /** |
6089 * Redraws the specified text range. | 6235 * Redraws the specified text range. |
6090 * | 6236 * |
6091 * @param start offset of the first character to redraw | 6237 * @param start offset of the first character to redraw |
6092 * @param length number of characters to redraw | 6238 * @param length number of characters to redraw |
6093 * @param clearBackground true if the background should be cleared as | 6239 * @param clearBackground true if the background should be cleared as |
6094 * part of the redraw operation. If true, the entire redraw range will | 6240 * part of the redraw operation. If true, the entire redraw range will |
6095 * be cleared before anything is redrawn. If the redraw range includes | 6241 * be cleared before anything is redrawn. If the redraw range includes |
6096 * the last character of a line (i.e., the entire line is redrawn) the | 6242 * the last character of a line (i.e., the entire line is redrawn) the |
6097 * line is cleared all the way to the right border of the widget. | 6243 * line is cleared all the way to the right border of the widget. |
6098 * The redraw operation will be faster and smoother if clearBackground | 6244 * The redraw operation will be faster and smoother if clearBackground |
6099 * is set to false. Whether or not the flag can be set to false depends | 6245 * is set to false. Whether or not the flag can be set to false depends |
6100 * on the type of change that has taken place. If font styles or | 6246 * on the type of change that has taken place. If font styles or |
6101 * background colors for the redraw range have changed, clearBackground | 6247 * background colors for the redraw range have changed, clearBackground |
6102 * should be set to true. If only foreground colors have changed for | 6248 * should be set to true. If only foreground colors have changed for |
6103 * the redraw range, clearBackground can be set to false. | 6249 * the redraw range, clearBackground can be set to false. |
6104 * @exception DWTException <ul> | 6250 * @exception DWTException <ul> |
6105 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6251 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6106 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6252 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6107 * </ul> | 6253 * </ul> |
6108 * @exception IllegalArgumentException <ul> | 6254 * @exception IllegalArgumentException <ul> |
6109 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> | 6255 * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
6110 * </ul> | 6256 * </ul> |
6111 */ | 6257 */ |
6112 public void redrawRange(int start, int length, bool clearBackground) { | 6258 public void redrawRange(int start, int length, bool clearBackground) { |
6113 checkWidget(); | 6259 checkWidget(); |
6114 int end = start + length; | 6260 int end = start + length; |
6122 internalRedrawRange(start, length); | 6268 internalRedrawRange(start, length); |
6123 } | 6269 } |
6124 /** | 6270 /** |
6125 * Removes the specified bidirectional segment listener. | 6271 * Removes the specified bidirectional segment listener. |
6126 * | 6272 * |
6127 * @param listener the listener | 6273 * @param listener the listener which should no longer be notified |
6274 * | |
6128 * @exception DWTException <ul> | 6275 * @exception DWTException <ul> |
6129 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6276 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6130 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6277 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6131 * </ul> | 6278 * </ul> |
6132 * @exception IllegalArgumentException <ul> | 6279 * @exception IllegalArgumentException <ul> |
6133 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 6280 * <li>ERROR_NULL_ARGUMENT when listener is null</li> |
6134 * </ul> | 6281 * </ul> |
6282 * | |
6135 * @since 2.0 | 6283 * @since 2.0 |
6136 */ | 6284 */ |
6137 public void removeBidiSegmentListener(BidiSegmentListener listener) { | 6285 public void removeBidiSegmentListener(BidiSegmentListener listener) { |
6138 checkWidget(); | 6286 checkWidget(); |
6139 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6287 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
6140 removeListener(LineGetSegments, listener); | 6288 removeListener(LineGetSegments, listener); |
6141 } | 6289 } |
6142 /** | 6290 /** |
6143 * Removes the specified extended modify listener. | 6291 * Removes the specified extended modify listener. |
6144 * | 6292 * |
6145 * @param extendedModifyListener the listener | 6293 * @param extendedModifyListener the listener which should no longer be notified |
6294 * | |
6146 * @exception DWTException <ul> | 6295 * @exception DWTException <ul> |
6147 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6296 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6148 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6297 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6149 * </ul> | 6298 * </ul> |
6150 * @exception IllegalArgumentException <ul> | 6299 * @exception IllegalArgumentException <ul> |
6152 * </ul> | 6301 * </ul> |
6153 */ | 6302 */ |
6154 public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { | 6303 public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { |
6155 checkWidget(); | 6304 checkWidget(); |
6156 if (extendedModifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6305 if (extendedModifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
6157 removeListener(ExtendedModify, extendedModifyListener); | 6306 removeListener(ExtendedModify, extendedModifyListener); |
6158 } | 6307 } |
6159 /** | 6308 /** |
6160 * Removes the specified line background listener. | 6309 * Removes the specified line background listener. |
6161 * | 6310 * |
6162 * @param listener the listener | 6311 * @param listener the listener which should no longer be notified |
6312 * | |
6163 * @exception DWTException <ul> | 6313 * @exception DWTException <ul> |
6164 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6314 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6165 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6315 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6166 * </ul> | 6316 * </ul> |
6167 * @exception IllegalArgumentException <ul> | 6317 * @exception IllegalArgumentException <ul> |
6174 removeListener(LineGetBackground, listener); | 6324 removeListener(LineGetBackground, listener); |
6175 } | 6325 } |
6176 /** | 6326 /** |
6177 * Removes the specified line style listener. | 6327 * Removes the specified line style listener. |
6178 * | 6328 * |
6179 * @param listener the listener | 6329 * @param listener the listener which should no longer be notified |
6330 * | |
6180 * @exception DWTException <ul> | 6331 * @exception DWTException <ul> |
6181 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6332 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6182 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6333 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6183 * </ul> | 6334 * </ul> |
6184 * @exception IllegalArgumentException <ul> | 6335 * @exception IllegalArgumentException <ul> |
6191 removeListener(LineGetStyle, listener); | 6342 removeListener(LineGetStyle, listener); |
6192 } | 6343 } |
6193 /** | 6344 /** |
6194 * Removes the specified modify listener. | 6345 * Removes the specified modify listener. |
6195 * | 6346 * |
6196 * @param modifyListener the listener | 6347 * @param modifyListener the listener which should no longer be notified |
6348 * | |
6197 * @exception DWTException <ul> | 6349 * @exception DWTException <ul> |
6198 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6350 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6199 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6351 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6200 * </ul> | 6352 * </ul> |
6201 * @exception IllegalArgumentException <ul> | 6353 * @exception IllegalArgumentException <ul> |
6208 removeListener(DWT.Modify, modifyListener); | 6360 removeListener(DWT.Modify, modifyListener); |
6209 } | 6361 } |
6210 /** | 6362 /** |
6211 * Removes the specified listener. | 6363 * Removes the specified listener. |
6212 * | 6364 * |
6213 * @param listener the listener | 6365 * @param listener the listener which should no longer be notified |
6366 * | |
6214 * @exception DWTException <ul> | 6367 * @exception DWTException <ul> |
6215 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6368 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6216 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6369 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6217 * </ul> | 6370 * </ul> |
6218 * @exception IllegalArgumentException <ul> | 6371 * @exception IllegalArgumentException <ul> |
6248 removeListener(DWT.Selection, listener); | 6401 removeListener(DWT.Selection, listener); |
6249 } | 6402 } |
6250 /** | 6403 /** |
6251 * Removes the specified verify listener. | 6404 * Removes the specified verify listener. |
6252 * | 6405 * |
6253 * @param verifyListener the listener | 6406 * @param verifyListener the listener which should no longer be notified |
6407 * | |
6254 * @exception DWTException <ul> | 6408 * @exception DWTException <ul> |
6255 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6409 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6256 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6410 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6257 * </ul> | 6411 * </ul> |
6258 * @exception IllegalArgumentException <ul> | 6412 * @exception IllegalArgumentException <ul> |
6265 removeListener(DWT.Verify, verifyListener); | 6419 removeListener(DWT.Verify, verifyListener); |
6266 } | 6420 } |
6267 /** | 6421 /** |
6268 * Removes the specified key verify listener. | 6422 * Removes the specified key verify listener. |
6269 * | 6423 * |
6270 * @param listener the listener | 6424 * @param listener the listener which should no longer be notified |
6425 * | |
6271 * @exception DWTException <ul> | 6426 * @exception DWTException <ul> |
6272 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6427 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6273 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6428 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6274 * </ul> | 6429 * </ul> |
6275 * @exception IllegalArgumentException <ul> | 6430 * @exception IllegalArgumentException <ul> |
6281 removeListener(VerifyKey, listener); | 6436 removeListener(VerifyKey, listener); |
6282 } | 6437 } |
6283 /** | 6438 /** |
6284 * Removes the specified word movement listener. | 6439 * Removes the specified word movement listener. |
6285 * | 6440 * |
6286 * @param listener the listener | 6441 * @param listener the listener which should no longer be notified |
6442 * | |
6287 * @exception DWTException <ul> | 6443 * @exception DWTException <ul> |
6288 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6444 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6289 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6445 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6290 * </ul> | 6446 * </ul> |
6291 * @exception IllegalArgumentException <ul> | 6447 * @exception IllegalArgumentException <ul> |
6292 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 6448 * <li>ERROR_NULL_ARGUMENT when listener is null</li> |
6293 * </ul> | 6449 * </ul> |
6294 * | 6450 * |
6295 * @see MovementEvent | 6451 * @see MovementEvent |
6296 * @see MovementListener | 6452 * @see MovementListener |
6297 * @see #addWordMovementListener | 6453 * @see #addWordMovementListener |
6298 * | 6454 * |
6299 * @since 3.3 | 6455 * @since 3.3 |
6300 */ | 6456 */ |
6301 | 6457 |
6302 public void removeWordMovementListener(MovementListener listener) { | 6458 public void removeWordMovementListener(MovementListener listener) { |
6303 checkWidget(); | 6459 checkWidget(); |
6304 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6460 if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); |
6305 removeListener(WordNext, listener); | 6461 removeListener(WordNext, listener); |
6306 removeListener(WordPrevious, listener); | 6462 removeListener(WordPrevious, listener); |
6307 } | 6463 } |
6308 /** | 6464 /** |
6309 * Replaces the styles in the given range with new styles. This method | 6465 * Replaces the styles in the given range with new styles. This method |
6310 * effectively deletes the styles in the given range and then adds the | 6466 * effectively deletes the styles in the given range and then adds the |
6311 * the new styles. | 6467 * the new styles. |
6312 * <p> | 6468 * <p> |
6313 * Note: Because a StyleRange includes the start and length, the | 6469 * Note: Because a StyleRange includes the start and length, the |
6314 * same instance cannot occur multiple times in the array of styles. | 6470 * same instance cannot occur multiple times in the array of styles. |
6315 * If the same style attributes, such as font and color, occur in | 6471 * If the same style attributes, such as font and color, occur in |
6316 * multiple StyleRanges, <code>setStyleRanges(int, int, int[], StyleRange[])</code> | 6472 * multiple StyleRanges, <code>setStyleRanges(int, int, int[], StyleRange[])</code> |
6317 * can be used to share styles and reduce memory usage. | 6473 * can be used to share styles and reduce memory usage. |
6318 * </p><p> | 6474 * </p><p> |
6319 * Should not be called if a LineStyleListener has been set since the | 6475 * Should not be called if a LineStyleListener has been set since the |
6320 * listener maintains the styles. | 6476 * listener maintains the styles. |
6321 * </p> | 6477 * </p> |
6322 * | 6478 * |
6323 * @param start offset of first character where styles will be deleted | 6479 * @param start offset of first character where styles will be deleted |
6324 * @param length length of the range to delete styles in | 6480 * @param length length of the range to delete styles in |
6325 * @param ranges StyleRange objects containing the new style information. | 6481 * @param ranges StyleRange objects containing the new style information. |
6326 * The ranges should not overlap and should be within the specified start | 6482 * The ranges should not overlap and should be within the specified start |
6327 * and length. The style rendering is undefined if the ranges do overlap | 6483 * and length. The style rendering is undefined if the ranges do overlap |
6328 * or are ill-defined. Must not be null. | 6484 * or are ill-defined. Must not be null. |
6329 * @exception DWTException <ul> | 6485 * @exception DWTException <ul> |
6330 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6486 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6331 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6487 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6332 * </ul> | 6488 * </ul> |
6333 * @exception IllegalArgumentException <ul> | 6489 * @exception IllegalArgumentException <ul> |
6334 * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> | 6490 * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6335 * <li>ERROR_NULL_ARGUMENT when ranges is null</li> | 6491 * </ul> |
6336 * </ul> | 6492 * |
6337 * | |
6338 * @since 2.0 | 6493 * @since 2.0 |
6339 * | 6494 * |
6340 * @see #setStyleRanges(int, int, int[], StyleRange[]) | 6495 * @see #setStyleRanges(int, int, int[], StyleRange[]) |
6341 */ | 6496 */ |
6342 public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { | 6497 public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { |
6343 checkWidget(); | 6498 checkWidget(); |
6344 if (isListening(LineGetStyle)) return; | 6499 if (isListening(LineGetStyle)) return; |
6345 if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6500 // DWT extension: allow null for zero length string |
6501 //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
6346 setStyleRanges(start, length, null, ranges, false); | 6502 setStyleRanges(start, length, null, ranges, false); |
6347 } | 6503 } |
6348 /** | 6504 /** |
6349 * Replaces the given text range with new text. | 6505 * Replaces the given text range with new text. |
6350 * If the widget has the DWT.SINGLE style and "text" contains more than | 6506 * If the widget has the DWT.SINGLE style and "text" contains more than |
6351 * one line, only the first line is rendered but the text is stored | 6507 * one line, only the first line is rendered but the text is stored |
6352 * unchanged. A subsequent call to getText will return the same text | 6508 * unchanged. A subsequent call to getText will return the same text |
6353 * that was set. Note that only a single line of text should be set when | 6509 * that was set. Note that only a single line of text should be set when |
6354 * the DWT.SINGLE style is used. | 6510 * the DWT.SINGLE style is used. |
6355 * <p> | 6511 * <p> |
6356 * <b>NOTE:</b> During the replace operation the current selection is | 6512 * <b>NOTE:</b> During the replace operation the current selection is |
6357 * changed as follows: | 6513 * changed as follows: |
6358 * <ul> | 6514 * <ul> |
6359 * <li>selection before replaced text: selection unchanged | 6515 * <li>selection before replaced text: selection unchanged |
6360 * <li>selection after replaced text: adjust the selection so that same text | 6516 * <li>selection after replaced text: adjust the selection so that same text |
6361 * remains selected | 6517 * remains selected |
6362 * <li>selection intersects replaced text: selection is cleared and caret | 6518 * <li>selection intersects replaced text: selection is cleared and caret |
6363 * is placed after inserted text | 6519 * is placed after inserted text |
6364 * </ul> | 6520 * </ul> |
6365 * </p> | 6521 * </p> |
6370 * @exception DWTException <ul> | 6526 * @exception DWTException <ul> |
6371 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6527 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6372 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6528 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6373 * </ul> | 6529 * </ul> |
6374 * @exception IllegalArgumentException <ul> | 6530 * @exception IllegalArgumentException <ul> |
6375 * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> | 6531 * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6376 * <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. | 6532 * <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. |
6377 * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported</li> | 6533 * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported</li> |
6378 * <li>ERROR_NULL_ARGUMENT when String is null</li> | |
6379 * </ul> | 6534 * </ul> |
6380 */ | 6535 */ |
6381 public void replaceTextRange(int start, int length, String text) { | 6536 public void replaceTextRange(int start, int length, String text) { |
6382 checkWidget(); | 6537 checkWidget(); |
6383 if (text is null) { | 6538 // DWT extension: allow null for zero length string |
6384 DWT.error(DWT.ERROR_NULL_ARGUMENT); | 6539 // if (text is null) { |
6385 } | 6540 // DWT.error(DWT.ERROR_NULL_ARGUMENT); |
6541 // } | |
6386 int contentLength = getCharCount(); | 6542 int contentLength = getCharCount(); |
6387 int end = start + length; | 6543 int end = start + length; |
6388 if (start > end || start < 0 || end > contentLength) { | 6544 if (start > end || start < 0 || end > contentLength) { |
6389 DWT.error(DWT.ERROR_INVALID_RANGE); | 6545 DWT.error(DWT.ERROR_INVALID_RANGE); |
6390 } | 6546 } |
6403 ScrollBar horizontalBar = getHorizontalBar(); | 6559 ScrollBar horizontalBar = getHorizontalBar(); |
6404 caretOffset = 0; | 6560 caretOffset = 0; |
6405 topIndex = 0; | 6561 topIndex = 0; |
6406 topIndexY = 0; | 6562 topIndexY = 0; |
6407 verticalScrollOffset = 0; | 6563 verticalScrollOffset = 0; |
6408 horizontalScrollOffset = 0; | 6564 horizontalScrollOffset = 0; |
6409 resetSelection(); | 6565 resetSelection(); |
6410 renderer.setContent(content); | 6566 renderer.setContent(content); |
6411 if (verticalBar !is null) { | 6567 if (verticalBar !is null) { |
6412 verticalBar.setSelection(0); | 6568 verticalBar.setSelection(0); |
6413 } | 6569 } |
6414 if (horizontalBar !is null) { | 6570 if (horizontalBar !is null) { |
6415 horizontalBar.setSelection(0); | 6571 horizontalBar.setSelection(0); |
6416 } | 6572 } |
6417 resetCache(0, 0); | 6573 resetCache(0, 0); |
6418 setCaretLocation(); | 6574 setCaretLocation(); |
6419 super.redraw(); | 6575 super.redraw(); |
6420 } | 6576 } |
6439 void resetSelection() { | 6595 void resetSelection() { |
6440 selection.x = selection.y = caretOffset; | 6596 selection.x = selection.y = caretOffset; |
6441 selectionAnchor = -1; | 6597 selectionAnchor = -1; |
6442 } | 6598 } |
6443 | 6599 |
6444 public void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { | 6600 public override void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { |
6445 super.scroll(destX, destY, x, y, width, height, false); | 6601 super.scroll(destX, destY, x, y, width, height, false); |
6446 if (all) { | 6602 if (all) { |
6447 int deltaX = destX - x, deltaY = destY - y; | 6603 int deltaX = destX - x, deltaY = destY - y; |
6448 Control[] children = getChildren(); | 6604 Control[] children = getChildren(); |
6449 for (int i=0; i<children.length; i++) { | 6605 for (int i=0; i<children.length; i++) { |
6457 /** | 6613 /** |
6458 * Scrolls the widget horizontally. | 6614 * Scrolls the widget horizontally. |
6459 * | 6615 * |
6460 * @param pixels number of pixels to scroll, > 0 = scroll left, | 6616 * @param pixels number of pixels to scroll, > 0 = scroll left, |
6461 * < 0 scroll right | 6617 * < 0 scroll right |
6462 * @param adjustScrollBar | 6618 * @param adjustScrollBar |
6463 * true= the scroll thumb will be moved to reflect the new scroll offset. | 6619 * true= the scroll thumb will be moved to reflect the new scroll offset. |
6464 * false = the scroll thumb will not be moved | 6620 * false = the scroll thumb will not be moved |
6465 * @return | 6621 * @return |
6466 * true=the widget was scrolled | 6622 * true=the widget was scrolled |
6467 * false=the widget was not scrolled, the given offset is not valid. | 6623 * false=the widget was not scrolled, the given offset is not valid. |
6468 */ | 6624 */ |
6469 bool scrollHorizontal(int pixels, bool adjustScrollBar) { | 6625 bool scrollHorizontal(int pixels, bool adjustScrollBar) { |
6470 if (pixels is 0) { | 6626 if (pixels is 0) { |
6471 return false; | 6627 return false; |
6500 } | 6656 } |
6501 /** | 6657 /** |
6502 * Scrolls the widget vertically. | 6658 * Scrolls the widget vertically. |
6503 * | 6659 * |
6504 * @param pixel the new vertical scroll offset | 6660 * @param pixel the new vertical scroll offset |
6505 * @param adjustScrollBar | 6661 * @param adjustScrollBar |
6506 * true= the scroll thumb will be moved to reflect the new scroll offset. | 6662 * true= the scroll thumb will be moved to reflect the new scroll offset. |
6507 * false = the scroll thumb will not be moved | 6663 * false = the scroll thumb will not be moved |
6508 * @return | 6664 * @return |
6509 * true=the widget was scrolled | 6665 * true=the widget was scrolled |
6510 * false=the widget was not scrolled | 6666 * false=the widget was not scrolled |
6511 */ | 6667 */ |
6512 bool scrollVertical(int pixels, bool adjustScrollBar) { | 6668 bool scrollVertical(int pixels, bool adjustScrollBar) { |
6513 if (pixels is 0) { | 6669 if (pixels is 0) { |
6514 return false; | 6670 return false; |
6572 } | 6728 } |
6573 if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) { | 6729 if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) { |
6574 super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); | 6730 super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); |
6575 } | 6731 } |
6576 } | 6732 } |
6577 /** | 6733 /** |
6578 * Selects all the text. | 6734 * Selects all the text. |
6579 * | 6735 * |
6580 * @exception DWTException <ul> | 6736 * @exception DWTException <ul> |
6581 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6737 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6582 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6738 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6587 setSelection(0, Math.max(getCharCount(),0)); | 6743 setSelection(0, Math.max(getCharCount(),0)); |
6588 } | 6744 } |
6589 /** | 6745 /** |
6590 * Replaces/inserts text as defined by the event. | 6746 * Replaces/inserts text as defined by the event. |
6591 * | 6747 * |
6592 * @param event the text change event. | 6748 * @param event the text change event. |
6593 * <ul> | 6749 * <ul> |
6594 * <li>event.start - the replace start offset</li> | 6750 * <li>event.start - the replace start offset</li> |
6595 * <li>event.end - the replace end offset</li> | 6751 * <li>event.end - the replace end offset</li> |
6596 * <li>event.text - the new text</li> | 6752 * <li>event.text - the new text</li> |
6597 * </ul> | 6753 * </ul> |
6600 if (editable) { | 6756 if (editable) { |
6601 modifyContent(event, true); | 6757 modifyContent(event, true); |
6602 } | 6758 } |
6603 } | 6759 } |
6604 /** | 6760 /** |
6605 * Returns a StyledTextEvent that can be used to request data such | 6761 * Returns a StyledTextEvent that can be used to request data such |
6606 * as styles and background color for a line. | 6762 * as styles and background color for a line. |
6607 * <p> | 6763 * <p> |
6608 * The specified line may be a visual (wrapped) line if in word | 6764 * The specified line may be a visual (wrapped) line if in word |
6609 * wrap mode. The returned object will always be for a logical | 6765 * wrap mode. The returned object will always be for a logical |
6610 * (unwrapped) line. | 6766 * (unwrapped) line. |
6611 * </p> | 6767 * </p> |
6612 * | 6768 * |
6613 * @param lineOffset offset of the line. This may be the offset of | 6769 * @param lineOffset offset of the line. This may be the offset of |
6614 * a visual line if the widget is in word wrap mode. | 6770 * a visual line if the widget is in word wrap mode. |
6615 * @param line line text. This may be the text of a visual line if | 6771 * @param line line text. This may be the text of a visual line if |
6616 * the widget is in word wrap mode. | 6772 * the widget is in word wrap mode. |
6617 * @return StyledTextEvent that can be used to request line data | 6773 * @return StyledTextEvent that can be used to request line data |
6618 * for the given line. | 6774 * for the given line. |
6619 */ | 6775 */ |
6620 StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { | 6776 StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { |
6621 StyledTextEvent event = null; | 6777 StyledTextEvent event = null; |
6622 if (isListening(eventType)) { | 6778 if (isListening(eventType)) { |
6630 } | 6786 } |
6631 return event; | 6787 return event; |
6632 } | 6788 } |
6633 void sendModifyEvent(Event event) { | 6789 void sendModifyEvent(Event event) { |
6634 Accessible accessible = getAccessible(); | 6790 Accessible accessible = getAccessible(); |
6635 if (event.text.length() is 0) { | 6791 if (event.text.length is 0) { |
6636 accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); | 6792 accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); |
6637 } else { | 6793 } else { |
6638 if (event.start is event.end) { | 6794 if (event.start is event.end) { |
6639 accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length()); | 6795 accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length); |
6640 } else { | 6796 } else { |
6641 accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); | 6797 accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); |
6642 accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length()); | 6798 accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length); |
6643 } | 6799 } |
6644 } | 6800 } |
6645 notifyListeners(DWT.Modify, event); | 6801 notifyListeners(DWT.Modify, event); |
6646 } | 6802 } |
6647 /** | 6803 /** |
6679 return offset; | 6835 return offset; |
6680 } | 6836 } |
6681 return newOffset; | 6837 return newOffset; |
6682 } | 6838 } |
6683 /** | 6839 /** |
6684 * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>, | 6840 * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>, |
6685 * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. The alignment applies for all lines. | 6841 * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. The alignment applies for all lines. |
6686 * </p><p> | 6842 * </p><p> |
6687 * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set | 6843 * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set |
6688 * in order to stabilize the right edge before setting alignment. | 6844 * in order to stabilize the right edge before setting alignment. |
6689 * </p> | 6845 * </p> |
6690 * | 6846 * |
6691 * @param alignment the new alignment | 6847 * @param alignment the new alignment |
6692 * | 6848 * |
6693 * @exception DWTException <ul> | 6849 * @exception DWTException <ul> |
6694 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6850 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6695 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6851 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6696 * </ul> | 6852 * </ul> |
6697 * | 6853 * |
6698 * @see #setLineAlignment(int, int, int) | 6854 * @see #setLineAlignment(int, int, int) |
6699 * | 6855 * |
6700 * @since 3.2 | 6856 * @since 3.2 |
6701 */ | 6857 */ |
6702 public void setAlignment(int alignment) { | 6858 public void setAlignment(int alignment) { |
6703 checkWidget(); | 6859 checkWidget(); |
6704 alignment &= (DWT.LEFT | DWT.RIGHT | DWT.CENTER); | 6860 alignment &= (DWT.LEFT | DWT.RIGHT | DWT.CENTER); |
6709 super.redraw(); | 6865 super.redraw(); |
6710 } | 6866 } |
6711 /** | 6867 /** |
6712 * @see Control#setBackground(Color) | 6868 * @see Control#setBackground(Color) |
6713 */ | 6869 */ |
6714 public void setBackground(Color color) { | 6870 public override void setBackground(Color color) { |
6715 checkWidget(); | 6871 checkWidget(); |
6716 background = color; | 6872 background = color; |
6717 super.setBackground(color); | 6873 super.setBackground(color); |
6718 super.redraw(); | 6874 super.redraw(); |
6719 } | 6875 } |
6720 /** | 6876 /** |
6721 * Sets the receiver's caret. Set the caret's height and location. | 6877 * Sets the receiver's caret. Set the caret's height and location. |
6722 * | 6878 * |
6723 * </p> | 6879 * </p> |
6724 * @param caret the new caret for the receiver | 6880 * @param caret the new caret for the receiver |
6725 * | 6881 * |
6726 * @exception DWTException <ul> | 6882 * @exception DWTException <ul> |
6727 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6883 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6728 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6884 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6729 * </ul> | 6885 * </ul> |
6730 */ | 6886 */ |
6731 public void setCaret(Caret caret) { | 6887 public override void setCaret(Caret caret) { |
6732 checkWidget (); | 6888 checkWidget (); |
6733 super.setCaret(caret); | 6889 super.setCaret(caret); |
6734 caretDirection = DWT.NULL; | 6890 caretDirection = DWT.NULL; |
6735 if (caret !is null) { | 6891 if (caret !is null) { |
6736 setCaretLocation(); | 6892 setCaretLocation(); |
6744 * @param mode the new coloring mode | 6900 * @param mode the new coloring mode |
6745 * @exception DWTException <ul> | 6901 * @exception DWTException <ul> |
6746 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6902 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6747 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6903 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6748 * </ul> | 6904 * </ul> |
6749 * | 6905 * |
6750 * @deprecated use BidiSegmentListener instead. | 6906 * @deprecated use BidiSegmentListener instead. |
6751 */ | 6907 */ |
6752 public void setBidiColoring(bool mode) { | 6908 public void setBidiColoring(bool mode) { |
6753 checkWidget(); | 6909 checkWidget(); |
6754 bidiColoring = mode; | 6910 bidiColoring = mode; |
6816 * @exception DWTException <ul> | 6972 * @exception DWTException <ul> |
6817 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 6973 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6818 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 6974 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6819 * </ul> | 6975 * </ul> |
6820 * @exception IllegalArgumentException <ul> | 6976 * @exception IllegalArgumentException <ul> |
6821 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a | 6977 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
6822 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) | 6978 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
6823 * </ul> | 6979 * </ul> |
6824 */ | 6980 */ |
6825 public void setCaretOffset(int offset) { | 6981 public void setCaretOffset(int offset) { |
6826 checkWidget(); | 6982 checkWidget(); |
6830 caretOffset = 0; | 6986 caretOffset = 0; |
6831 } else if (offset > length) { | 6987 } else if (offset > length) { |
6832 caretOffset = length; | 6988 caretOffset = length; |
6833 } else { | 6989 } else { |
6834 if (isLineDelimiter(offset)) { | 6990 if (isLineDelimiter(offset)) { |
6835 // offset is inside a multi byte line delimiter. This is an | 6991 // offset is inside a multi byte line delimiter. This is an |
6836 // illegal operation and an exception is thrown. Fixes 1GDKK3R | 6992 // illegal operation and an exception is thrown. Fixes 1GDKK3R |
6837 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 6993 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
6838 } | 6994 } |
6839 caretOffset = offset; | 6995 caretOffset = offset; |
6840 } | 6996 } |
6842 // clear the selection if the caret is moved. | 6998 // clear the selection if the caret is moved. |
6843 // don't notify listeners about the selection change. | 6999 // don't notify listeners about the selection change. |
6844 clearSelection(false); | 7000 clearSelection(false); |
6845 } | 7001 } |
6846 setCaretLocation(); | 7002 setCaretLocation(); |
6847 } | 7003 } |
6848 /** | 7004 /** |
6849 * Copies the specified text range to the clipboard. The text will be placed | 7005 * Copies the specified text range to the clipboard. The text will be placed |
6850 * in the clipboard in plain text format and RTF format. | 7006 * in the clipboard in plain text format and RTF format. |
6851 * | 7007 * |
6852 * @param start start index of the text | 7008 * @param start start index of the text |
6853 * @param length length of text to place in clipboard | 7009 * @param length length of text to place in clipboard |
6854 * | 7010 * |
6855 * @exception DWTError, see Clipboard.setContents | 7011 * @exception DWTError, see Clipboard.setContents |
6856 * @see dwt.dnd.Clipboard#setContents | 7012 * @see dwt.dnd.Clipboard#setContents |
6857 */ | 7013 */ |
6858 void setClipboardContent(int start, int length, int clipboardType) { | 7014 void setClipboardContent(int start, int length, int clipboardType) { |
6859 if (clipboardType is DND.SELECTION_CLIPBOARD && !(IS_MOTIF || IS_GTK)) return; | 7015 if (clipboardType is DND.SELECTION_CLIPBOARD && !(IS_MOTIF || IS_GTK)) return; |
6861 TextWriter plainTextWriter = new TextWriter(start, length); | 7017 TextWriter plainTextWriter = new TextWriter(start, length); |
6862 String plainText = getPlatformDelimitedText(plainTextWriter); | 7018 String plainText = getPlatformDelimitedText(plainTextWriter); |
6863 Object[] data; | 7019 Object[] data; |
6864 Transfer[] types; | 7020 Transfer[] types; |
6865 if (clipboardType is DND.SELECTION_CLIPBOARD) { | 7021 if (clipboardType is DND.SELECTION_CLIPBOARD) { |
6866 data = new Object[]{plainText}; | 7022 data = [ cast(Object) new ArrayWrapperString(plainText) ]; |
6867 types = new Transfer[]{plainTextTransfer}; | 7023 types = [plainTextTransfer]; |
6868 } else { | 7024 } else { |
6869 RTFTransfer rtfTransfer = RTFTransfer.getInstance(); | 7025 RTFTransfer rtfTransfer = RTFTransfer.getInstance(); |
6870 RTFWriter rtfWriter = new RTFWriter(start, length); | 7026 RTFWriter rtfWriter = new RTFWriter(start, length); |
6871 String rtfText = getPlatformDelimitedText(rtfWriter); | 7027 String rtfText = getPlatformDelimitedText(rtfWriter); |
6872 data = new Object[]{rtfText, plainText}; | 7028 data = [ cast(Object) new ArrayWrapperString(rtfText), new ArrayWrapperString(plainText) ]; |
6873 types = new Transfer[]{rtfTransfer, plainTextTransfer}; | 7029 types = [ cast(Transfer)rtfTransfer, plainTextTransfer]; |
6874 } | 7030 } |
6875 clipboard.setContents(data, types, clipboardType); | 7031 clipboard.setContents(data, types, clipboardType); |
6876 } | 7032 } |
6877 /** | 7033 /** |
6878 * Sets the content implementation to use for text storage. | 7034 * Sets the content implementation to use for text storage. |
6885 * @exception IllegalArgumentException <ul> | 7041 * @exception IllegalArgumentException <ul> |
6886 * <li>ERROR_NULL_ARGUMENT when listener is null</li> | 7042 * <li>ERROR_NULL_ARGUMENT when listener is null</li> |
6887 * </ul> | 7043 * </ul> |
6888 */ | 7044 */ |
6889 public void setContent(StyledTextContent newContent) { | 7045 public void setContent(StyledTextContent newContent) { |
6890 checkWidget(); | 7046 checkWidget(); |
6891 if (newContent is null) { | 7047 if (newContent is null) { |
6892 DWT.error(DWT.ERROR_NULL_ARGUMENT); | 7048 DWT.error(DWT.ERROR_NULL_ARGUMENT); |
6893 } | 7049 } |
6894 if (content !is null) { | 7050 if (content !is null) { |
6895 content.removeTextChangeListener(textChangeListener); | 7051 content.removeTextChangeListener(textChangeListener); |
6898 content.addTextChangeListener(textChangeListener); | 7054 content.addTextChangeListener(textChangeListener); |
6899 reset(); | 7055 reset(); |
6900 } | 7056 } |
6901 /** | 7057 /** |
6902 * Sets the receiver's cursor to the cursor specified by the | 7058 * Sets the receiver's cursor to the cursor specified by the |
6903 * argument. Overridden to handle the null case since the | 7059 * argument. Overridden to handle the null case since the |
6904 * StyledText widget uses an ibeam as its default cursor. | 7060 * StyledText widget uses an ibeam as its default cursor. |
6905 * | 7061 * |
6906 * @see Control#setCursor(Cursor) | 7062 * @see Control#setCursor(Cursor) |
6907 */ | 7063 */ |
6908 public void setCursor (Cursor cursor) { | 7064 public override void setCursor (Cursor cursor) { |
6909 if (cursor is null) { | 7065 if (cursor is null) { |
6910 Display display = getDisplay(); | 7066 Display display = getDisplay(); |
6911 super.setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); | 7067 super.setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); |
6912 } else { | 7068 } else { |
6913 super.setCursor(cursor); | 7069 super.setCursor(cursor); |
6914 } | 7070 } |
6915 } | 7071 } |
6916 /** | 7072 /** |
6917 * Sets whether the widget : double click mouse behavior. | 7073 * Sets whether the widget : double click mouse behavior. |
6918 * </p> | 7074 * </p> |
6919 * | 7075 * |
6920 * @param enable if true double clicking a word selects the word, if false | 7076 * @param enable if true double clicking a word selects the word, if false |
6921 * double clicks have the same effect as regular mouse clicks. | 7077 * double clicks have the same effect as regular mouse clicks. |
6926 */ | 7082 */ |
6927 public void setDoubleClickEnabled(bool enable) { | 7083 public void setDoubleClickEnabled(bool enable) { |
6928 checkWidget(); | 7084 checkWidget(); |
6929 doubleClickEnabled = enable; | 7085 doubleClickEnabled = enable; |
6930 } | 7086 } |
6931 public void setDragDetect (bool dragDetect) { | 7087 public override void setDragDetect (bool dragDetect_) { |
6932 checkWidget (); | 7088 checkWidget (); |
6933 this.dragDetect = dragDetect; | 7089 this.dragDetect_ = dragDetect_; |
6934 } | 7090 } |
6935 /** | 7091 /** |
6936 * Sets whether the widget content can be edited. | 7092 * Sets whether the widget content can be edited. |
6937 * </p> | 7093 * </p> |
6938 * | 7094 * |
6939 * @param editable if true content can be edited, if false content can not be | 7095 * @param editable if true content can be edited, if false content can not be |
6940 * edited | 7096 * edited |
6941 * @exception DWTException <ul> | 7097 * @exception DWTException <ul> |
6942 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7098 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6943 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7099 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6944 * </ul> | 7100 * </ul> |
6958 * @exception DWTException <ul> | 7114 * @exception DWTException <ul> |
6959 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7115 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6960 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7116 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6961 * </ul> | 7117 * </ul> |
6962 */ | 7118 */ |
6963 public void setFont(Font font) { | 7119 public override void setFont(Font font) { |
6964 checkWidget(); | 7120 checkWidget(); |
6965 int oldLineHeight = renderer.getLineHeight(); | 7121 int oldLineHeight = renderer.getLineHeight(); |
6966 super.setFont(font); | 7122 super.setFont(font); |
6967 renderer.setFont(getFont(), tabLength); | 7123 renderer.setFont(getFont(), tabLength); |
6968 // keep the same top line visible. fixes 5815 | 7124 // keep the same top line visible. fixes 5815 |
6969 if (isFixedLineHeight()) { | 7125 if (isFixedLineHeight()) { |
6970 int lineHeight = renderer.getLineHeight(); | 7126 int lineHeight = renderer.getLineHeight(); |
6971 if (lineHeight !is oldLineHeight) { | 7127 if (lineHeight !is oldLineHeight) { |
6972 int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset(); | 7128 int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset(); |
6973 scrollVertical(vscroll, true); | 7129 scrollVertical(vscroll, true); |
6974 } | 7130 } |
6975 } | 7131 } |
6976 resetCache(0, content.getLineCount()); | 7132 resetCache(0, content.getLineCount()); |
6977 claimBottomFreeSpace(); | 7133 claimBottomFreeSpace(); |
6978 calculateScrollBars(); | 7134 calculateScrollBars(); |
6979 if (isBidiCaret()) createCaretBitmaps(); | 7135 if (isBidiCaret()) createCaretBitmaps(); |
6980 caretDirection = DWT.NULL; | 7136 caretDirection = DWT.NULL; |
6981 setCaretLocation(); | 7137 setCaretLocation(); |
6982 super.redraw(); | 7138 super.redraw(); |
6983 } | 7139 } |
6984 /** | 7140 public override void setForeground(Color color) { |
6985 * @see dwt.widgets.Control#setForeground | |
6986 */ | |
6987 public void setForeground(Color color) { | |
6988 checkWidget(); | 7141 checkWidget(); |
6989 foreground = color; | 7142 foreground = color; |
6990 super.setForeground(getForeground()); | 7143 super.setForeground(getForeground()); |
6991 super.redraw(); | 7144 super.redraw(); |
6992 } | 7145 } |
6993 /** | 7146 /** |
6994 * Sets the horizontal scroll offset relative to the start of the line. | 7147 * Sets the horizontal scroll offset relative to the start of the line. |
6995 * Do nothing if there is no text set. | 7148 * Do nothing if there is no text set. |
6996 * <p> | 7149 * <p> |
6997 * <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the | 7150 * <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the |
6998 * widget. | 7151 * widget. |
6999 * </p> | 7152 * </p> |
7000 * | 7153 * |
7001 * @param offset horizontal scroll offset relative to the start | 7154 * @param offset horizontal scroll offset relative to the start |
7002 * of the line, measured in character increments starting at 0, if | 7155 * of the line, measured in character increments starting at 0, if |
7003 * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. | 7156 * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. |
7004 * @exception DWTException <ul> | 7157 * @exception DWTException <ul> |
7005 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7158 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7006 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7159 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7007 * </ul> | 7160 * </ul> |
7008 */ | 7161 */ |
7009 public void setHorizontalIndex(int offset) { | 7162 public void setHorizontalIndex(int offset) { |
7010 checkWidget(); | 7163 checkWidget(); |
7011 if (getCharCount() is 0) { | 7164 if (getCharCount() is 0) { |
7012 return; | 7165 return; |
7013 } | 7166 } |
7014 if (offset < 0) { | 7167 if (offset < 0) { |
7015 offset = 0; | 7168 offset = 0; |
7016 } | 7169 } |
7017 offset *= getHorizontalIncrement(); | 7170 offset *= getHorizontalIncrement(); |
7018 // allow any value if client area width is unknown or 0. | 7171 // allow any value if client area width is unknown or 0. |
7019 // offset will be checked in resize handler. | 7172 // offset will be checked in resize handler. |
7020 // don't use isVisible since width is known even if widget | 7173 // don't use isVisible since width is known even if widget |
7021 // is temporarily invisible | 7174 // is temporarily invisible |
7022 if (clientAreaWidth > 0) { | 7175 if (clientAreaWidth > 0) { |
7023 int width = renderer.getWidth(); | 7176 int width = renderer.getWidth(); |
7024 // prevent scrolling if the content fits in the client area. | 7177 // prevent scrolling if the content fits in the client area. |
7025 // align end of longest line with right border of client area | 7178 // align end of longest line with right border of client area |
7028 offset = Math.max(0, width - clientAreaWidth); | 7181 offset = Math.max(0, width - clientAreaWidth); |
7029 } | 7182 } |
7030 } | 7183 } |
7031 scrollHorizontal(offset - horizontalScrollOffset, true); | 7184 scrollHorizontal(offset - horizontalScrollOffset, true); |
7032 } | 7185 } |
7033 /** | 7186 /** |
7034 * Sets the horizontal pixel offset relative to the start of the line. | 7187 * Sets the horizontal pixel offset relative to the start of the line. |
7035 * Do nothing if there is no text set. | 7188 * Do nothing if there is no text set. |
7036 * <p> | 7189 * <p> |
7037 * <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text | 7190 * <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text |
7038 * is set in the widget. | 7191 * is set in the widget. |
7039 * </p> | 7192 * </p> |
7040 * | 7193 * |
7041 * @param pixel horizontal pixel offset relative to the start | 7194 * @param pixel horizontal pixel offset relative to the start |
7042 * of the line. | 7195 * of the line. |
7043 * @exception DWTException <ul> | 7196 * @exception DWTException <ul> |
7044 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7197 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7045 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7198 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7046 * </ul> | 7199 * </ul> |
7048 */ | 7201 */ |
7049 public void setHorizontalPixel(int pixel) { | 7202 public void setHorizontalPixel(int pixel) { |
7050 checkWidget(); | 7203 checkWidget(); |
7051 if (getCharCount() is 0) { | 7204 if (getCharCount() is 0) { |
7052 return; | 7205 return; |
7053 } | 7206 } |
7054 if (pixel < 0) { | 7207 if (pixel < 0) { |
7055 pixel = 0; | 7208 pixel = 0; |
7056 } | 7209 } |
7057 // allow any value if client area width is unknown or 0. | 7210 // allow any value if client area width is unknown or 0. |
7058 // offset will be checked in resize handler. | 7211 // offset will be checked in resize handler. |
7059 // don't use isVisible since width is known even if widget | 7212 // don't use isVisible since width is known even if widget |
7060 // is temporarily invisible | 7213 // is temporarily invisible |
7061 if (clientAreaWidth > 0) { | 7214 if (clientAreaWidth > 0) { |
7062 int width = renderer.getWidth(); | 7215 int width = renderer.getWidth(); |
7063 // prevent scrolling if the content fits in the client area. | 7216 // prevent scrolling if the content fits in the client area. |
7064 // align end of longest line with right border of client area | 7217 // align end of longest line with right border of client area |
7070 scrollHorizontal(pixel - horizontalScrollOffset, true); | 7223 scrollHorizontal(pixel - horizontalScrollOffset, true); |
7071 } | 7224 } |
7072 /** | 7225 /** |
7073 * Sets the line indentation of the widget. | 7226 * Sets the line indentation of the widget. |
7074 * <p> | 7227 * <p> |
7075 * It is the amount of blank space, in pixels, at the beginning of each line. | 7228 * It is the amount of blank space, in pixels, at the beginning of each line. |
7076 * When a line wraps in several lines only the first one is indented. | 7229 * When a line wraps in several lines only the first one is indented. |
7077 * </p> | 7230 * </p> |
7078 * | 7231 * |
7079 * @param indent the new indent | 7232 * @param indent the new indent |
7080 * | 7233 * |
7081 * @exception DWTException <ul> | 7234 * @exception DWTException <ul> |
7082 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7235 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7083 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7236 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7084 * </ul> | 7237 * </ul> |
7085 * | 7238 * |
7086 * @see #setLineIndent(int, int, int) | 7239 * @see #setLineIndent(int, int, int) |
7087 * | 7240 * |
7088 * @since 3.2 | 7241 * @since 3.2 |
7089 */ | 7242 */ |
7090 public void setIndent(int indent) { | 7243 public void setIndent(int indent) { |
7091 checkWidget(); | 7244 checkWidget(); |
7092 if (this.indent is indent || indent < 0) return; | 7245 if (this.indent is indent || indent < 0) return; |
7093 this.indent = indent; | 7246 this.indent = indent; |
7094 resetCache(0, content.getLineCount()); | 7247 resetCache(0, content.getLineCount()); |
7095 setCaretLocation(); | 7248 setCaretLocation(); |
7096 super.redraw(); | 7249 super.redraw(); |
7097 } | 7250 } |
7098 /** | 7251 /** |
7099 * Sets whether the widget should justify lines. | 7252 * Sets whether the widget should justify lines. |
7100 * | 7253 * |
7101 * @param justify whether lines should be justified | 7254 * @param justify whether lines should be justified |
7102 * | 7255 * |
7103 * @exception DWTException <ul> | 7256 * @exception DWTException <ul> |
7104 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7257 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7105 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7258 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7106 * </ul> | 7259 * </ul> |
7107 * | 7260 * |
7108 * @see #setLineJustify(int, int, bool) | 7261 * @see #setLineJustify(int, int, bool) |
7109 * | 7262 * |
7110 * @since 3.2 | 7263 * @since 3.2 |
7111 */ | 7264 */ |
7112 public void setJustify(bool justify) { | 7265 public void setJustify(bool justify) { |
7113 checkWidget(); | 7266 checkWidget(); |
7114 if (this.justify is justify) return; | 7267 if (this.justify is justify) return; |
7115 this.justify = justify; | 7268 this.justify = justify; |
7116 resetCache(0, content.getLineCount()); | 7269 resetCache(0, content.getLineCount()); |
7117 setCaretLocation(); | 7270 setCaretLocation(); |
7118 super.redraw(); | 7271 super.redraw(); |
7119 } | 7272 } |
7120 /** | 7273 /** |
7121 * Maps a key to an action. | 7274 * Maps a key to an action. |
7122 * <p> | 7275 * <p> |
7123 * One action can be associated with N keys. However, each key can only | 7276 * One action can be associated with N keys. However, each key can only |
7124 * have one action (key:action is N:1 relation). | 7277 * have one action (key:action is N:1 relation). |
7125 * </p> | 7278 * </p> |
7126 * | 7279 * |
7127 * @param key a key code defined in DWT.java or a character. | 7280 * @param key a key code defined in DWT.java or a character. |
7128 * Optionally ORd with a state mask. Preferred state masks are one or more of | 7281 * Optionally ORd with a state mask. Preferred state masks are one or more of |
7129 * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform | 7282 * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform |
7130 * differences. However, there may be cases where using the specific state masks | 7283 * differences. However, there may be cases where using the specific state masks |
7131 * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. | 7284 * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. |
7132 * @param action one of the predefined actions defined in ST.java. | 7285 * @param action one of the predefined actions defined in ST.java. |
7133 * Use DWT.NULL to remove a key binding. | 7286 * Use DWT.NULL to remove a key binding. |
7134 * @exception DWTException <ul> | 7287 * @exception DWTException <ul> |
7135 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7288 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7136 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7289 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7137 * </ul> | 7290 * </ul> |
7138 */ | 7291 */ |
7139 public void setKeyBinding(int key, int action) { | 7292 public void setKeyBinding(int key, int action) { |
7140 checkWidget(); | 7293 checkWidget(); |
7141 int modifierValue = key & DWT.MODIFIER_MASK; | 7294 int modifierValue = key & DWT.MODIFIER_MASK; |
7142 char keyChar = cast(wchar)(key & DWT.KEY_MASK); | 7295 char keyChar = cast(char)(key & DWT.KEY_MASK); |
7143 if (Compatibility.isLetter(keyChar)) { | 7296 if (Compatibility.isLetter(keyChar)) { |
7144 // make the keybinding case insensitive by adding it | 7297 // make the keybinding case insensitive by adding it |
7145 // in its upper and lower case form | 7298 // in its upper and lower case form |
7146 char ch = Character.toUpperCase(keyChar); | 7299 char ch = CharacterToUpper(keyChar); |
7147 int newKey = ch | modifierValue; | 7300 int newKey = ch | modifierValue; |
7148 if (action is DWT.NULL) { | 7301 if (action is DWT.NULL) { |
7149 keyActionMap.remove(new Integer(newKey)); | 7302 keyActionMap.remove(newKey); |
7150 } else { | 7303 } else { |
7151 keyActionMap.put(new Integer(newKey), new Integer(action)); | 7304 keyActionMap[newKey] = action; |
7152 } | 7305 } |
7153 ch = Character.toLowerCase(keyChar); | 7306 ch = CharacterToLower(keyChar); |
7154 newKey = ch | modifierValue; | 7307 newKey = ch | modifierValue; |
7155 if (action is DWT.NULL) { | 7308 if (action is DWT.NULL) { |
7156 keyActionMap.remove(new Integer(newKey)); | 7309 keyActionMap.remove(newKey); |
7157 } else { | 7310 } else { |
7158 keyActionMap.put(new Integer(newKey), new Integer(action)); | 7311 keyActionMap[newKey] = action; |
7159 } | 7312 } |
7160 } else { | 7313 } else { |
7161 if (action is DWT.NULL) { | 7314 if (action is DWT.NULL) { |
7162 keyActionMap.remove(new Integer(key)); | 7315 keyActionMap.remove(key); |
7163 } else { | 7316 } else { |
7164 keyActionMap.put(new Integer(key), new Integer(action)); | 7317 keyActionMap[key]=action; |
7165 } | 7318 } |
7166 } | 7319 } |
7167 } | 7320 } |
7168 /** | 7321 /** |
7169 * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>, | 7322 * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>, |
7170 * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. | 7323 * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. |
7171 * <p><p> | 7324 * <p><p> |
7172 * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set | 7325 * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set |
7173 * in order to stabilize the right edge before setting alignment. | 7326 * in order to stabilize the right edge before setting alignment. |
7174 * </p> | 7327 * </p> |
7175 * Should not be called if a LineStyleListener has been set since the listener | 7328 * Should not be called if a LineStyleListener has been set since the listener |
7176 * maintains the line attributes. | 7329 * maintains the line attributes. |
7177 * </p><p> | 7330 * </p><p> |
7178 * All line attributes are maintained relative to the line text, not the | 7331 * All line attributes are maintained relative to the line text, not the |
7179 * line index that is specified in this method call. | 7332 * line index that is specified in this method call. |
7180 * During text changes, when entire lines are inserted or removed, the line | 7333 * During text changes, when entire lines are inserted or removed, the line |
7181 * attributes that are associated with the lines after the change | 7334 * attributes that are associated with the lines after the change |
7182 * will "move" with their respective text. An entire line is defined as | 7335 * will "move" with their respective text. An entire line is defined as |
7183 * extending from the first character on a line to the last and including the | 7336 * extending from the first character on a line to the last and including the |
7184 * line delimiter. | 7337 * line delimiter. |
7185 * </p><p> | 7338 * </p><p> |
7186 * When two lines are joined by deleting a line delimiter, the top line | 7339 * When two lines are joined by deleting a line delimiter, the top line |
7187 * attributes take precedence and the attributes of the bottom line are deleted. | 7340 * attributes take precedence and the attributes of the bottom line are deleted. |
7188 * For all other text changes line attributes will remain unchanged. | 7341 * For all other text changes line attributes will remain unchanged. |
7189 * | 7342 * |
7190 * @param startLine first line the alignment is applied to, 0 based | 7343 * @param startLine first line the alignment is applied to, 0 based |
7191 * @param lineCount number of lines the alignment applies to. | 7344 * @param lineCount number of lines the alignment applies to. |
7192 * @param alignment line alignment | 7345 * @param alignment line alignment |
7193 * | 7346 * |
7194 * @exception DWTException <ul> | 7347 * @exception DWTException <ul> |
7195 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7348 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7196 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7349 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7197 * </ul> | 7350 * </ul> |
7198 * @exception IllegalArgumentException <ul> | 7351 * @exception IllegalArgumentException <ul> |
7214 int caretLine = getCaretLine(); | 7367 int caretLine = getCaretLine(); |
7215 if (startLine <= caretLine && caretLine < startLine + lineCount) { | 7368 if (startLine <= caretLine && caretLine < startLine + lineCount) { |
7216 setCaretLocation(); | 7369 setCaretLocation(); |
7217 } | 7370 } |
7218 } | 7371 } |
7219 /** | 7372 /** |
7220 * Sets the background color of the specified lines. | 7373 * Sets the background color of the specified lines. |
7221 * <p> | 7374 * <p> |
7222 * The background color is drawn for the width of the widget. All | 7375 * The background color is drawn for the width of the widget. All |
7223 * line background colors are discarded when setText is called. | 7376 * line background colors are discarded when setText is called. |
7224 * The text background color if defined in a StyleRange overlays the | 7377 * The text background color if defined in a StyleRange overlays the |
7225 * line background color. | 7378 * line background color. |
7226 * </p><p> | 7379 * </p><p> |
7227 * Should not be called if a LineBackgroundListener has been set since the | 7380 * Should not be called if a LineBackgroundListener has been set since the |
7228 * listener maintains the line backgrounds. | 7381 * listener maintains the line backgrounds. |
7229 * </p><p> | 7382 * </p><p> |
7230 * All line attributes are maintained relative to the line text, not the | 7383 * All line attributes are maintained relative to the line text, not the |
7231 * line index that is specified in this method call. | 7384 * line index that is specified in this method call. |
7232 * During text changes, when entire lines are inserted or removed, the line | 7385 * During text changes, when entire lines are inserted or removed, the line |
7233 * attributes that are associated with the lines after the change | 7386 * attributes that are associated with the lines after the change |
7234 * will "move" with their respective text. An entire line is defined as | 7387 * will "move" with their respective text. An entire line is defined as |
7235 * extending from the first character on a line to the last and including the | 7388 * extending from the first character on a line to the last and including the |
7236 * line delimiter. | 7389 * line delimiter. |
7237 * </p><p> | 7390 * </p><p> |
7238 * When two lines are joined by deleting a line delimiter, the top line | 7391 * When two lines are joined by deleting a line delimiter, the top line |
7239 * attributes take precedence and the attributes of the bottom line are deleted. | 7392 * attributes take precedence and the attributes of the bottom line are deleted. |
7240 * For all other text changes line attributes will remain unchanged. | 7393 * For all other text changes line attributes will remain unchanged. |
7241 * </p> | 7394 * </p> |
7242 * | 7395 * |
7243 * @param startLine first line the color is applied to, 0 based | 7396 * @param startLine first line the color is applied to, 0 based |
7244 * @param lineCount number of lines the color applies to. | 7397 * @param lineCount number of lines the color applies to. |
7245 * @param background line background color | 7398 * @param background line background color |
7246 * @exception DWTException <ul> | 7399 * @exception DWTException <ul> |
7247 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7400 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7250 * @exception IllegalArgumentException <ul> | 7403 * @exception IllegalArgumentException <ul> |
7251 * <li>ERROR_INVALID_ARGUMENT when the specified line range is invalid</li> | 7404 * <li>ERROR_INVALID_ARGUMENT when the specified line range is invalid</li> |
7252 * </ul> | 7405 * </ul> |
7253 */ | 7406 */ |
7254 public void setLineBackground(int startLine, int lineCount, Color background) { | 7407 public void setLineBackground(int startLine, int lineCount, Color background) { |
7255 checkWidget(); | 7408 checkWidget(); |
7256 if (isListening(LineGetBackground)) return; | 7409 if (isListening(LineGetBackground)) return; |
7257 if (startLine < 0 || startLine + lineCount > content.getLineCount()) { | 7410 if (startLine < 0 || startLine + lineCount > content.getLineCount()) { |
7258 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 7411 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7259 } | 7412 } |
7260 if (background !is null) { | 7413 if (background !is null) { |
7265 redrawLines(startLine, lineCount); | 7418 redrawLines(startLine, lineCount); |
7266 } | 7419 } |
7267 /** | 7420 /** |
7268 * Sets the bullet of the specified lines. | 7421 * Sets the bullet of the specified lines. |
7269 * <p> | 7422 * <p> |
7270 * Should not be called if a LineStyleListener has been set since the listener | 7423 * Should not be called if a LineStyleListener has been set since the listener |
7271 * maintains the line attributes. | 7424 * maintains the line attributes. |
7272 * </p><p> | 7425 * </p><p> |
7273 * All line attributes are maintained relative to the line text, not the | 7426 * All line attributes are maintained relative to the line text, not the |
7274 * line index that is specified in this method call. | 7427 * line index that is specified in this method call. |
7275 * During text changes, when entire lines are inserted or removed, the line | 7428 * During text changes, when entire lines are inserted or removed, the line |
7276 * attributes that are associated with the lines after the change | 7429 * attributes that are associated with the lines after the change |
7277 * will "move" with their respective text. An entire line is defined as | 7430 * will "move" with their respective text. An entire line is defined as |
7278 * extending from the first character on a line to the last and including the | 7431 * extending from the first character on a line to the last and including the |
7279 * line delimiter. | 7432 * line delimiter. |
7280 * </p><p> | 7433 * </p><p> |
7281 * When two lines are joined by deleting a line delimiter, the top line | 7434 * When two lines are joined by deleting a line delimiter, the top line |
7282 * attributes take precedence and the attributes of the bottom line are deleted. | 7435 * attributes take precedence and the attributes of the bottom line are deleted. |
7283 * For all other text changes line attributes will remain unchanged. | 7436 * For all other text changes line attributes will remain unchanged. |
7284 * </p> | 7437 * </p> |
7285 * | 7438 * |
7286 * @param startLine first line the bullet is applied to, 0 based | 7439 * @param startLine first line the bullet is applied to, 0 based |
7287 * @param lineCount number of lines the bullet applies to. | 7440 * @param lineCount number of lines the bullet applies to. |
7288 * @param bullet line bullet | 7441 * @param bullet line bullet |
7289 * | 7442 * |
7290 * @exception DWTException <ul> | 7443 * @exception DWTException <ul> |
7291 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7444 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7292 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7445 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7293 * </ul> | 7446 * </ul> |
7294 * @exception IllegalArgumentException <ul> | 7447 * @exception IllegalArgumentException <ul> |
7296 * </ul> | 7449 * </ul> |
7297 * @since 3.2 | 7450 * @since 3.2 |
7298 */ | 7451 */ |
7299 public void setLineBullet(int startLine, int lineCount, Bullet bullet) { | 7452 public void setLineBullet(int startLine, int lineCount, Bullet bullet) { |
7300 checkWidget(); | 7453 checkWidget(); |
7301 if (isListening(LineGetStyle)) return; | 7454 if (isListening(LineGetStyle)) return; |
7302 if (startLine < 0 || startLine + lineCount > content.getLineCount()) { | 7455 if (startLine < 0 || startLine + lineCount > content.getLineCount()) { |
7303 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 7456 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7304 } | 7457 } |
7305 | 7458 |
7306 renderer.setLineBullet(startLine, lineCount, bullet); | 7459 renderer.setLineBullet(startLine, lineCount, bullet); |
7317 renderer.calculateIdle(); | 7470 renderer.calculateIdle(); |
7318 } | 7471 } |
7319 /** | 7472 /** |
7320 * Sets the indent of the specified lines. | 7473 * Sets the indent of the specified lines. |
7321 * <p> | 7474 * <p> |
7322 * Should not be called if a LineStyleListener has been set since the listener | 7475 * Should not be called if a LineStyleListener has been set since the listener |
7323 * maintains the line attributes. | 7476 * maintains the line attributes. |
7324 * </p><p> | 7477 * </p><p> |
7325 * All line attributes are maintained relative to the line text, not the | 7478 * All line attributes are maintained relative to the line text, not the |
7326 * line index that is specified in this method call. | 7479 * line index that is specified in this method call. |
7327 * During text changes, when entire lines are inserted or removed, the line | 7480 * During text changes, when entire lines are inserted or removed, the line |
7328 * attributes that are associated with the lines after the change | 7481 * attributes that are associated with the lines after the change |
7329 * will "move" with their respective text. An entire line is defined as | 7482 * will "move" with their respective text. An entire line is defined as |
7330 * extending from the first character on a line to the last and including the | 7483 * extending from the first character on a line to the last and including the |
7331 * line delimiter. | 7484 * line delimiter. |
7332 * </p><p> | 7485 * </p><p> |
7333 * When two lines are joined by deleting a line delimiter, the top line | 7486 * When two lines are joined by deleting a line delimiter, the top line |
7334 * attributes take precedence and the attributes of the bottom line are deleted. | 7487 * attributes take precedence and the attributes of the bottom line are deleted. |
7335 * For all other text changes line attributes will remain unchanged. | 7488 * For all other text changes line attributes will remain unchanged. |
7336 * </p> | 7489 * </p> |
7337 * | 7490 * |
7338 * @param startLine first line the indent is applied to, 0 based | 7491 * @param startLine first line the indent is applied to, 0 based |
7339 * @param lineCount number of lines the indent applies to. | 7492 * @param lineCount number of lines the indent applies to. |
7340 * @param indent line indent | 7493 * @param indent line indent |
7341 * | 7494 * |
7342 * @exception DWTException <ul> | 7495 * @exception DWTException <ul> |
7343 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7496 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7344 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7497 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7345 * </ul> | 7498 * </ul> |
7346 * @exception IllegalArgumentException <ul> | 7499 * @exception IllegalArgumentException <ul> |
7365 } | 7518 } |
7366 } | 7519 } |
7367 /** | 7520 /** |
7368 * Sets the justify of the specified lines. | 7521 * Sets the justify of the specified lines. |
7369 * <p> | 7522 * <p> |
7370 * Should not be called if a LineStyleListener has been set since the listener | 7523 * Should not be called if a LineStyleListener has been set since the listener |
7371 * maintains the line attributes. | 7524 * maintains the line attributes. |
7372 * </p><p> | 7525 * </p><p> |
7373 * All line attributes are maintained relative to the line text, not the | 7526 * All line attributes are maintained relative to the line text, not the |
7374 * line index that is specified in this method call. | 7527 * line index that is specified in this method call. |
7375 * During text changes, when entire lines are inserted or removed, the line | 7528 * During text changes, when entire lines are inserted or removed, the line |
7376 * attributes that are associated with the lines after the change | 7529 * attributes that are associated with the lines after the change |
7377 * will "move" with their respective text. An entire line is defined as | 7530 * will "move" with their respective text. An entire line is defined as |
7378 * extending from the first character on a line to the last and including the | 7531 * extending from the first character on a line to the last and including the |
7379 * line delimiter. | 7532 * line delimiter. |
7380 * </p><p> | 7533 * </p><p> |
7381 * When two lines are joined by deleting a line delimiter, the top line | 7534 * When two lines are joined by deleting a line delimiter, the top line |
7382 * attributes take precedence and the attributes of the bottom line are deleted. | 7535 * attributes take precedence and the attributes of the bottom line are deleted. |
7383 * For all other text changes line attributes will remain unchanged. | 7536 * For all other text changes line attributes will remain unchanged. |
7384 * </p> | 7537 * </p> |
7385 * | 7538 * |
7386 * @param startLine first line the justify is applied to, 0 based | 7539 * @param startLine first line the justify is applied to, 0 based |
7387 * @param lineCount number of lines the justify applies to. | 7540 * @param lineCount number of lines the justify applies to. |
7388 * @param justify true if lines should be justified | 7541 * @param justify true if lines should be justified |
7389 * | 7542 * |
7390 * @exception DWTException <ul> | 7543 * @exception DWTException <ul> |
7391 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7544 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7392 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7545 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7393 * </ul> | 7546 * </ul> |
7394 * @exception IllegalArgumentException <ul> | 7547 * @exception IllegalArgumentException <ul> |
7412 setCaretLocation(); | 7565 setCaretLocation(); |
7413 } | 7566 } |
7414 } | 7567 } |
7415 /** | 7568 /** |
7416 * Sets the line spacing of the widget. The line spacing applies for all lines. | 7569 * Sets the line spacing of the widget. The line spacing applies for all lines. |
7417 * | 7570 * |
7418 * @param lineSpacing the line spacing | 7571 * @param lineSpacing the line spacing |
7419 * @exception DWTException <ul> | 7572 * @exception DWTException <ul> |
7420 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7573 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7421 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7574 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7422 * </ul> | 7575 * </ul> |
7423 * @since 3.2 | 7576 * @since 3.2 |
7424 */ | 7577 */ |
7425 public void setLineSpacing(int lineSpacing) { | 7578 public void setLineSpacing(int lineSpacing) { |
7426 checkWidget(); | 7579 checkWidget(); |
7427 if (this.lineSpacing is lineSpacing || lineSpacing < 0) return; | 7580 if (this.lineSpacing is lineSpacing || lineSpacing < 0) return; |
7428 this.lineSpacing = lineSpacing; | 7581 this.lineSpacing = lineSpacing; |
7429 setVariableLineHeight(); | 7582 setVariableLineHeight(); |
7430 resetCache(0, content.getLineCount()); | 7583 resetCache(0, content.getLineCount()); |
7431 setCaretLocation(); | 7584 setCaretLocation(); |
7432 super.redraw(); | 7585 super.redraw(); |
7433 } | 7586 } |
7454 /** | 7607 /** |
7455 * Sets the orientation of the receiver, which must be one | 7608 * Sets the orientation of the receiver, which must be one |
7456 * of the constants <code>DWT.LEFT_TO_RIGHT</code> or <code>DWT.RIGHT_TO_LEFT</code>. | 7609 * of the constants <code>DWT.LEFT_TO_RIGHT</code> or <code>DWT.RIGHT_TO_LEFT</code>. |
7457 * | 7610 * |
7458 * @param orientation new orientation style | 7611 * @param orientation new orientation style |
7459 * | 7612 * |
7460 * @exception DWTException <ul> | 7613 * @exception DWTException <ul> |
7461 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7614 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7462 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7615 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7463 * </ul> | 7616 * </ul> |
7464 * | 7617 * |
7465 * @since 2.1.2 | 7618 * @since 2.1.2 |
7466 */ | 7619 */ |
7467 public void setOrientation(int orientation) { | 7620 public void setOrientation(int orientation) { |
7468 if ((orientation & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { | 7621 if ((orientation & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { |
7469 return; | 7622 return; |
7470 } | 7623 } |
7471 if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && (orientation & DWT.LEFT_TO_RIGHT) !is 0) { | 7624 if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && (orientation & DWT.LEFT_TO_RIGHT) !is 0) { |
7472 return; | 7625 return; |
7473 } | 7626 } |
7474 if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && isMirrored()) { | 7627 if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && isMirrored()) { |
7475 return; | 7628 return; |
7476 } | 7629 } |
7477 if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) { | 7630 if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) { |
7478 return; | 7631 return; |
7479 } | 7632 } |
7480 if (!BidiUtil.setOrientation(this, orientation)) { | 7633 if (!BidiUtil.setOrientation(this, orientation)) { |
7481 return; | 7634 return; |
7482 } | 7635 } |
7483 isMirrored = (orientation & DWT.RIGHT_TO_LEFT) !is 0; | 7636 isMirrored_ = (orientation & DWT.RIGHT_TO_LEFT) !is 0; |
7484 caretDirection = DWT.NULL; | 7637 caretDirection = DWT.NULL; |
7485 resetCache(0, content.getLineCount()); | 7638 resetCache(0, content.getLineCount()); |
7486 setCaretLocation(); | 7639 setCaretLocation(); |
7487 keyActionMap.clear(); | 7640 keyActionMap = null; |
7488 createKeyBindings(); | 7641 createKeyBindings(); |
7489 super.redraw(); | 7642 super.redraw(); |
7490 } | 7643 } |
7491 /** | 7644 /** |
7492 * Adjusts the maximum and the page size of the scroll bars to | 7645 * Adjusts the maximum and the page size of the scroll bars to |
7493 * reflect content width/length changes. | 7646 * reflect content width/length changes. |
7494 * | 7647 * |
7495 * @param vertical indicates if the vertical scrollbar also needs to be set | 7648 * @param vertical indicates if the vertical scrollbar also needs to be set |
7496 */ | 7649 */ |
7497 void setScrollBars(bool vertical) { | 7650 void setScrollBars(bool vertical) { |
7498 int inactive = 1; | 7651 int inactive = 1; |
7499 if (vertical || !isFixedLineHeight()) { | 7652 if (vertical || !isFixedLineHeight()) { |
7500 ScrollBar verticalBar = getVerticalBar(); | 7653 ScrollBar verticalBar = getVerticalBar(); |
7501 if (verticalBar !is null) { | 7654 if (verticalBar !is null) { |
7502 int maximum = renderer.getHeight(); | 7655 int maximum = renderer.getHeight(); |
7503 // only set the real values if the scroll bar can be used | 7656 // only set the real values if the scroll bar can be used |
7504 // (ie. because the thumb size is less than the scroll maximum) | 7657 // (ie. because the thumb size is less than the scroll maximum) |
7505 // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 | 7658 // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7506 if (clientAreaHeight < maximum) { | 7659 if (clientAreaHeight < maximum) { |
7507 verticalBar.setMaximum(maximum); | 7660 verticalBar.setMaximum(maximum); |
7508 verticalBar.setThumb(clientAreaHeight); | 7661 verticalBar.setThumb(clientAreaHeight); |
7519 } | 7672 } |
7520 } | 7673 } |
7521 ScrollBar horizontalBar = getHorizontalBar(); | 7674 ScrollBar horizontalBar = getHorizontalBar(); |
7522 if (horizontalBar !is null && horizontalBar.getVisible()) { | 7675 if (horizontalBar !is null && horizontalBar.getVisible()) { |
7523 int maximum = renderer.getWidth(); | 7676 int maximum = renderer.getWidth(); |
7524 // only set the real values if the scroll bar can be used | 7677 // only set the real values if the scroll bar can be used |
7525 // (ie. because the thumb size is less than the scroll maximum) | 7678 // (ie. because the thumb size is less than the scroll maximum) |
7526 // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 | 7679 // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7527 if (clientAreaWidth < maximum) { | 7680 if (clientAreaWidth < maximum) { |
7528 horizontalBar.setMaximum(maximum); | 7681 horizontalBar.setMaximum(maximum); |
7529 horizontalBar.setThumb(clientAreaWidth - leftMargin - rightMargin); | 7682 horizontalBar.setThumb(clientAreaWidth - leftMargin - rightMargin); |
7537 horizontalBar.getIncrement(), | 7690 horizontalBar.getIncrement(), |
7538 inactive); | 7691 inactive); |
7539 } | 7692 } |
7540 } | 7693 } |
7541 } | 7694 } |
7542 /** | 7695 /** |
7543 * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). | 7696 * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). |
7544 * | 7697 * |
7545 * @param start new caret position | 7698 * @param start new caret position |
7546 * @see #setSelection(int,int) | 7699 * @see #setSelection(int,int) |
7547 * @exception DWTException <ul> | 7700 * @exception DWTException <ul> |
7548 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7701 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7549 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7702 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7550 * </ul> | 7703 * </ul> |
7551 * @exception IllegalArgumentException <ul> | 7704 * @exception IllegalArgumentException <ul> |
7552 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a | 7705 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7553 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) | 7706 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7554 * </ul> | 7707 * </ul> |
7555 */ | 7708 */ |
7556 public void setSelection(int start) { | 7709 public void setSelection(int start) { |
7557 // checkWidget test done in setSelectionRange | 7710 // checkWidget test done in setSelectionRange |
7558 setSelection(start, start); | 7711 setSelection(start, start); |
7559 } | 7712 } |
7560 /** | 7713 /** |
7561 * Sets the selection and scrolls it into view. | 7714 * Sets the selection and scrolls it into view. |
7562 * <p> | 7715 * <p> |
7563 * Indexing is zero based. Text selections are specified in terms of | 7716 * Indexing is zero based. Text selections are specified in terms of |
7564 * caret positions. In a text widget that contains N characters, there are | 7717 * caret positions. In a text widget that contains N characters, there are |
7565 * N+1 caret positions, ranging from 0..N | 7718 * N+1 caret positions, ranging from 0..N |
7566 * </p> | 7719 * </p> |
7567 * | 7720 * |
7568 * @param point x=selection start offset, y=selection end offset | 7721 * @param point x=selection start offset, y=selection end offset |
7569 * The caret will be placed at the selection start when x > y. | 7722 * The caret will be placed at the selection start when x > y. |
7572 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7725 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7573 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7726 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7574 * </ul> | 7727 * </ul> |
7575 * @exception IllegalArgumentException <ul> | 7728 * @exception IllegalArgumentException <ul> |
7576 * <li>ERROR_NULL_ARGUMENT when point is null</li> | 7729 * <li>ERROR_NULL_ARGUMENT when point is null</li> |
7577 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a | 7730 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7578 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) | 7731 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7579 * </ul> | 7732 * </ul> |
7580 */ | 7733 */ |
7581 public void setSelection(Point point) { | 7734 public void setSelection(Point point) { |
7582 checkWidget(); | 7735 checkWidget(); |
7583 if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); | 7736 if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); |
7584 setSelection(point.x, point.y); | 7737 setSelection(point.x, point.y); |
7585 } | 7738 } |
7586 /** | 7739 /** |
7587 * Sets the receiver's selection background color to the color specified | 7740 * Sets the receiver's selection background color to the color specified |
7588 * by the argument, or to the default system color for the control | 7741 * by the argument, or to the default system color for the control |
7589 * if the argument is null. | 7742 * if the argument is null. |
7590 * | 7743 * |
7591 * @param color the new color (or null) | 7744 * @param color the new color (or null) |
7592 * | 7745 * |
7593 * @exception IllegalArgumentException <ul> | 7746 * @exception IllegalArgumentException <ul> |
7594 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> | 7747 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7595 * </ul> | 7748 * </ul> |
7596 * @exception DWTException <ul> | 7749 * @exception DWTException <ul> |
7597 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7750 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7598 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7751 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7599 * </ul> | 7752 * </ul> |
7608 super.redraw(); | 7761 super.redraw(); |
7609 } | 7762 } |
7610 /** | 7763 /** |
7611 * Sets the receiver's selection foreground color to the color specified | 7764 * Sets the receiver's selection foreground color to the color specified |
7612 * by the argument, or to the default system color for the control | 7765 * by the argument, or to the default system color for the control |
7613 * if the argument is null. | 7766 * if the argument is null. |
7614 * <p> | 7767 * <p> |
7615 * Note that this is a <em>HINT</em>. Some platforms do not allow the application | 7768 * Note that this is a <em>HINT</em>. Some platforms do not allow the application |
7616 * to change the selection foreground color. | 7769 * to change the selection foreground color. |
7617 * </p> | 7770 * </p> |
7618 * @param color the new color (or null) | 7771 * @param color the new color (or null) |
7619 * | 7772 * |
7620 * @exception IllegalArgumentException <ul> | 7773 * @exception IllegalArgumentException <ul> |
7621 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> | 7774 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7622 * </ul> | 7775 * </ul> |
7623 * @exception DWTException <ul> | 7776 * @exception DWTException <ul> |
7624 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7777 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7625 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7778 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7626 * </ul> | 7779 * </ul> |
7632 if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 7785 if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7633 } | 7786 } |
7634 selectionForeground = color; | 7787 selectionForeground = color; |
7635 super.redraw(); | 7788 super.redraw(); |
7636 } | 7789 } |
7637 /** | 7790 /** |
7638 * Sets the selection and scrolls it into view. | 7791 * Sets the selection and scrolls it into view. |
7639 * <p> | 7792 * <p> |
7640 * Indexing is zero based. Text selections are specified in terms of | 7793 * Indexing is zero based. Text selections are specified in terms of |
7641 * caret positions. In a text widget that contains N characters, there are | 7794 * caret positions. In a text widget that contains N characters, there are |
7642 * N+1 caret positions, ranging from 0..N | 7795 * N+1 caret positions, ranging from 0..N |
7643 * </p> | 7796 * </p> |
7644 * | 7797 * |
7645 * @param start selection start offset. The caret will be placed at the | 7798 * @param start selection start offset. The caret will be placed at the |
7646 * selection start when start > end. | 7799 * selection start when start > end. |
7647 * @param end selection end offset | 7800 * @param end selection end offset |
7648 * @see #setSelectionRange(int,int) | 7801 * @see #setSelectionRange(int,int) |
7649 * @exception DWTException <ul> | 7802 * @exception DWTException <ul> |
7650 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7803 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7651 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7804 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7652 * </ul> | 7805 * </ul> |
7653 * @exception IllegalArgumentException <ul> | 7806 * @exception IllegalArgumentException <ul> |
7654 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a | 7807 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7655 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) | 7808 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7656 * </ul> | 7809 * </ul> |
7657 */ | 7810 */ |
7658 public void setSelection(int start, int end) { | 7811 public void setSelection(int start, int end) { |
7659 setSelectionRange(start, end - start); | 7812 setSelectionRange(start, end - start); |
7660 showSelection(); | 7813 showSelection(); |
7661 } | 7814 } |
7662 /** | 7815 /** |
7663 * Sets the selection. | 7816 * Sets the selection. |
7664 * <p> | 7817 * <p> |
7665 * The new selection may not be visible. Call showSelection to scroll | 7818 * The new selection may not be visible. Call showSelection to scroll |
7666 * the selection into view. | 7819 * the selection into view. |
7667 * </p> | 7820 * </p> |
7668 * | 7821 * |
7669 * @param start offset of the first selected character, start >= 0 must be true. | 7822 * @param start offset of the first selected character, start >= 0 must be true. |
7670 * @param length number of characters to select, 0 <= start + length | 7823 * @param length number of characters to select, 0 <= start + length |
7671 * <= getCharCount() must be true. | 7824 * <= getCharCount() must be true. |
7672 * A negative length places the caret at the selection start. | 7825 * A negative length places the caret at the selection start. |
7673 * @param sendEvent a Selection event is sent when set to true and when | 7826 * @param sendEvent a Selection event is sent when set to true and when |
7674 * the selection is reset. | 7827 * the selection is reset. |
7675 */ | 7828 */ |
7676 void setSelection(int start, int length, bool sendEvent) { | 7829 void setSelection(int start, int length, bool sendEvent) { |
7677 int end = start + length; | 7830 int end = start + length; |
7831 start = content.utf8AdjustOffset(start); | |
7832 end = content.utf8AdjustOffset(end); | |
7678 if (start > end) { | 7833 if (start > end) { |
7679 int temp = end; | 7834 int temp = end; |
7680 end = start; | 7835 end = start; |
7681 start = temp; | 7836 start = temp; |
7682 } | 7837 } |
7683 // is the selection range different or is the selection direction | 7838 // is the selection range different or is the selection direction |
7684 // different? | 7839 // different? |
7685 if (selection.x !is start || selection.y !is end || | 7840 if (selection.x !is start || selection.y !is end || |
7686 (length > 0 && selectionAnchor !is selection.x) || | 7841 (length > 0 && selectionAnchor !is selection.x) || |
7687 (length < 0 && selectionAnchor !is selection.y)) { | 7842 (length < 0 && selectionAnchor !is selection.y)) { |
7688 clearSelection(sendEvent); | 7843 clearSelection(sendEvent); |
7689 if (length < 0) { | 7844 if (length < 0) { |
7690 selectionAnchor = selection.y = end; | 7845 selectionAnchor = selection.y = end; |
7691 caretOffset = selection.x = start; | 7846 caretOffset = selection.x = start; |
7695 } | 7850 } |
7696 caretAlignment = PREVIOUS_OFFSET_TRAILING; | 7851 caretAlignment = PREVIOUS_OFFSET_TRAILING; |
7697 internalRedrawRange(selection.x, selection.y - selection.x); | 7852 internalRedrawRange(selection.x, selection.y - selection.x); |
7698 } | 7853 } |
7699 } | 7854 } |
7700 /** | 7855 /** |
7701 * Sets the selection. | 7856 * Sets the selection. |
7702 * <p> | 7857 * <p> |
7703 * The new selection may not be visible. Call showSelection to scroll the selection | 7858 * The new selection may not be visible. Call showSelection to scroll the selection |
7704 * into view. A negative length places the caret at the visual start of the selection. | 7859 * into view. A negative length places the caret at the visual start of the selection. |
7705 * </p> | 7860 * </p> |
7706 * | 7861 * |
7707 * @param start offset of the first selected character | 7862 * @param start offset of the first selected character |
7708 * @param length number of characters to select | 7863 * @param length number of characters to select |
7709 * | 7864 * |
7710 * @exception DWTException <ul> | 7865 * @exception DWTException <ul> |
7711 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7866 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7712 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7867 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7713 * </ul> | 7868 * </ul> |
7714 * @exception IllegalArgumentException <ul> | 7869 * @exception IllegalArgumentException <ul> |
7715 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a | 7870 * <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7716 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) | 7871 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7717 * </ul> | 7872 * </ul> |
7718 */ | 7873 */ |
7719 public void setSelectionRange(int start, int length) { | 7874 public void setSelectionRange(int start, int length) { |
7720 checkWidget(); | 7875 checkWidget(); |
7725 length = -start; | 7880 length = -start; |
7726 } else { | 7881 } else { |
7727 if (end > contentLength) length = contentLength - start; | 7882 if (end > contentLength) length = contentLength - start; |
7728 } | 7883 } |
7729 if (isLineDelimiter(start) || isLineDelimiter(start + length)) { | 7884 if (isLineDelimiter(start) || isLineDelimiter(start + length)) { |
7730 // the start offset or end offset of the selection range is inside a | 7885 // the start offset or end offset of the selection range is inside a |
7731 // multi byte line delimiter. This is an illegal operation and an exception | 7886 // multi byte line delimiter. This is an illegal operation and an exception |
7732 // is thrown. Fixes 1GDKK3R | 7887 // is thrown. Fixes 1GDKK3R |
7733 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 7888 DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7734 } | 7889 } |
7735 setSelection(start, length, false); | 7890 setSelection(start, length, false); |
7736 setCaretLocation(); | 7891 setCaretLocation(); |
7737 } | 7892 } |
7738 /** | 7893 /** |
7739 * Adds the specified style. | 7894 * Adds the specified style. |
7740 * <p> | 7895 * <p> |
7741 * The new style overwrites existing styles for the specified range. | 7896 * The new style overwrites existing styles for the specified range. |
7742 * Existing style ranges are adjusted if they partially overlap with | 7897 * Existing style ranges are adjusted if they partially overlap with |
7743 * the new style. To clear an individual style, call setStyleRange | 7898 * the new style. To clear an individual style, call setStyleRange |
7744 * with a StyleRange that has null attributes. | 7899 * with a StyleRange that has null attributes. |
7745 * </p><p> | 7900 * </p><p> |
7746 * Should not be called if a LineStyleListener has been set since the | 7901 * Should not be called if a LineStyleListener has been set since the |
7747 * listener maintains the styles. | 7902 * listener maintains the styles. |
7748 * </p> | 7903 * </p> |
7749 * | 7904 * |
7750 * @param range StyleRange object containing the style information. | 7905 * @param range StyleRange object containing the style information. |
7751 * Overwrites the old style in the given range. May be null to delete | 7906 * Overwrites the old style in the given range. May be null to delete |
7753 * @exception DWTException <ul> | 7908 * @exception DWTException <ul> |
7754 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7909 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7755 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7910 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7756 * </ul> | 7911 * </ul> |
7757 * @exception IllegalArgumentException <ul> | 7912 * @exception IllegalArgumentException <ul> |
7758 * <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> | 7913 * <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> |
7759 * </ul> | 7914 * </ul> |
7760 */ | 7915 */ |
7761 public void setStyleRange(StyleRange range) { | 7916 public void setStyleRange(StyleRange range) { |
7762 checkWidget(); | 7917 checkWidget(); |
7763 if (isListening(LineGetStyle)) return; | 7918 if (isListening(LineGetStyle)) return; |
7764 if (range !is null) { | 7919 if (range !is null) { |
7765 if (range.isUnstyled()) { | 7920 if (range.isUnstyled()) { |
7766 setStyleRanges(range.start, range.length, null, null, false); | 7921 setStyleRanges(range.start, range.length, null, null, false); |
7767 } else { | 7922 } else { |
7768 setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); | 7923 setStyleRanges(range.start, 0, null, [range], false); |
7769 } | 7924 } |
7770 } else { | 7925 } else { |
7771 setStyleRanges(0, 0, null, null, true); | 7926 setStyleRanges(0, 0, null, null, true); |
7772 } | 7927 } |
7773 } | 7928 } |
7774 /** | 7929 /** |
7775 * Clears the styles in the range specified by <code>start</code> and | 7930 * Clears the styles in the range specified by <code>start</code> and |
7776 * <code>length</code> and adds the new styles. | 7931 * <code>length</code> and adds the new styles. |
7777 * <p> | 7932 * <p> |
7778 * The ranges array contains start and length pairs. Each pair refers to | 7933 * The ranges array contains start and length pairs. Each pair refers to |
7779 * the corresponding style in the styles array. For example, the pair | 7934 * the corresponding style in the styles array. For example, the pair |
7780 * that starts at ranges[n] with length ranges[n+1] uses the style | 7935 * that starts at ranges[n] with length ranges[n+1] uses the style |
7782 * If ranges or styles is null, the specified range is cleared. | 7937 * If ranges or styles is null, the specified range is cleared. |
7783 * </p><p> | 7938 * </p><p> |
7784 * Note: It is expected that the same instance of a StyleRange will occur | 7939 * Note: It is expected that the same instance of a StyleRange will occur |
7785 * multiple times within the styles array, reducing memory usage. | 7940 * multiple times within the styles array, reducing memory usage. |
7786 * </p><p> | 7941 * </p><p> |
7787 * Should not be called if a LineStyleListener has been set since the | 7942 * Should not be called if a LineStyleListener has been set since the |
7788 * listener maintains the styles. | 7943 * listener maintains the styles. |
7789 * </p> | 7944 * </p> |
7790 * | 7945 * |
7791 * @param start offset of first character where styles will be deleted | 7946 * @param start offset of first character where styles will be deleted |
7792 * @param length length of the range to delete styles in | 7947 * @param length length of the range to delete styles in |
7793 * @param ranges the array of ranges. The ranges must not overlap and must be in order. | 7948 * @param ranges the array of ranges. The ranges must not overlap and must be in order. |
7794 * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. | 7949 * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. |
7795 * | 7950 * |
7796 * @exception DWTException <ul> | 7951 * @exception DWTException <ul> |
7797 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7952 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7798 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7953 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7799 * </ul> | 7954 * </ul> |
7800 * @exception IllegalArgumentException <ul> | 7955 * @exception IllegalArgumentException <ul> |
7801 * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> | 7956 * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> |
7802 * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> | 7957 * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> |
7803 * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> | 7958 * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> |
7804 * <li>ERROR_INVALID_RANGE when a range overlaps</li> | 7959 * <li>ERROR_INVALID_RANGE when a range overlaps</li> |
7805 * </ul> | 7960 * </ul> |
7806 * | 7961 * |
7807 * @since 3.2 | 7962 * @since 3.2 |
7808 */ | 7963 */ |
7809 public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { | 7964 public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { |
7810 checkWidget(); | 7965 checkWidget(); |
7811 if (isListening(LineGetStyle)) return; | 7966 if (isListening(LineGetStyle)) return; |
7812 if (ranges is null || styles is null) { | 7967 if (ranges is null || styles is null) { |
7813 setStyleRanges(start, length, null, null, false); | 7968 setStyleRanges(start, length, null, null, false); |
7814 } else { | 7969 } else { |
7815 setStyleRanges(start, length, ranges, styles, false); | 7970 setStyleRanges(start, length, ranges, styles, false); |
7816 } | 7971 } |
7817 } | 7972 } |
7818 /** | 7973 /** |
7819 * Sets styles to be used for rendering the widget content. | 7974 * Sets styles to be used for rendering the widget content. |
7820 * <p> | 7975 * <p> |
7821 * All styles in the widget will be replaced with the given set of ranges and styles. | 7976 * All styles in the widget will be replaced with the given set of ranges and styles. |
7822 * The ranges array contains start and length pairs. Each pair refers to | 7977 * The ranges array contains start and length pairs. Each pair refers to |
7823 * the corresponding style in the styles array. For example, the pair | 7978 * the corresponding style in the styles array. For example, the pair |
7826 * If either argument is null, the styles are cleared. | 7981 * If either argument is null, the styles are cleared. |
7827 * </p><p> | 7982 * </p><p> |
7828 * Note: It is expected that the same instance of a StyleRange will occur | 7983 * Note: It is expected that the same instance of a StyleRange will occur |
7829 * multiple times within the styles array, reducing memory usage. | 7984 * multiple times within the styles array, reducing memory usage. |
7830 * </p><p> | 7985 * </p><p> |
7831 * Should not be called if a LineStyleListener has been set since the | 7986 * Should not be called if a LineStyleListener has been set since the |
7832 * listener maintains the styles. | 7987 * listener maintains the styles. |
7833 * </p> | 7988 * </p> |
7834 * | 7989 * |
7835 * @param ranges the array of ranges. The ranges must not overlap and must be in order. | 7990 * @param ranges the array of ranges. The ranges must not overlap and must be in order. |
7836 * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. | 7991 * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. |
7837 * | 7992 * |
7838 * @exception DWTException <ul> | 7993 * @exception DWTException <ul> |
7839 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 7994 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7840 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 7995 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7841 * </ul> | 7996 * </ul> |
7842 * @exception IllegalArgumentException <ul> | 7997 * @exception IllegalArgumentException <ul> |
7843 * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> | 7998 * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> |
7844 * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> | 7999 * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> |
7845 * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> | 8000 * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> |
7846 * <li>ERROR_INVALID_RANGE when a range overlaps</li> | 8001 * <li>ERROR_INVALID_RANGE when a range overlaps</li> |
7847 * </ul> | 8002 * </ul> |
7848 * | 8003 * |
7849 * @since 3.2 | 8004 * @since 3.2 |
7850 */ | 8005 */ |
7851 public void setStyleRanges(int[] ranges, StyleRange[] styles) { | 8006 public void setStyleRanges(int[] ranges, StyleRange[] styles) { |
7852 checkWidget(); | 8007 checkWidget(); |
7853 if (isListening(LineGetStyle)) return; | 8008 if (isListening(LineGetStyle)) return; |
7854 if (ranges is null || styles is null) { | 8009 if (ranges is null || styles is null) { |
7869 } | 8024 } |
7870 if (ranges !is null) { | 8025 if (ranges !is null) { |
7871 if (ranges.length !is styles.length << 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 8026 if (ranges.length !is styles.length << 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7872 } | 8027 } |
7873 int lastOffset = 0; | 8028 int lastOffset = 0; |
7874 bool variableHeight = false; | 8029 bool variableHeight = false; |
7875 for (int i = 0; i < styles.length; i ++) { | 8030 for (int i = 0; i < styles.length; i ++) { |
7876 if (styles[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 8031 if (styles[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7877 int rangeStart, rangeLength; | 8032 int rangeStart, rangeLength; |
7878 if (ranges !is null) { | 8033 if (ranges !is null) { |
7879 rangeStart = ranges[i << 1]; | 8034 rangeStart = ranges[i << 1]; |
7880 rangeLength = ranges[(i << 1) + 1]; | 8035 rangeLength = ranges[(i << 1) + 1]; |
7881 } else { | 8036 } else { |
7882 rangeStart = styles[i].start; | 8037 rangeStart = styles[i].start; |
7883 rangeLength = styles[i].length; | 8038 rangeLength = styles[i].length; |
7884 } | 8039 } |
7885 if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 8040 if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7886 if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 8041 if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7887 if (lastOffset > rangeStart) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 8042 if (lastOffset > rangeStart) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
7888 variableHeight |= styles[i].isVariableHeight(); | 8043 variableHeight |= styles[i].isVariableHeight(); |
7889 lastOffset = rangeStart + rangeLength; | 8044 lastOffset = rangeStart + rangeLength; |
7890 } | 8045 } |
7939 if (!isFixedLineHeight()) { | 8094 if (!isFixedLineHeight()) { |
7940 scrollText(lastLineBottom, newLastLineBottom); | 8095 scrollText(lastLineBottom, newLastLineBottom); |
7941 } | 8096 } |
7942 height = newLastLineBottom - y; | 8097 height = newLastLineBottom - y; |
7943 } | 8098 } |
7944 super.redraw(0, y, clientAreaWidth, height, false); | 8099 super.redraw(0, y, clientAreaWidth, height, false); |
7945 } | 8100 } |
7946 } | 8101 } |
7947 setCaretLocation(); | 8102 setCaretLocation(); |
7948 } | 8103 } |
7949 /** | 8104 /** |
7950 * Sets styles to be used for rendering the widget content. All styles | 8105 * Sets styles to be used for rendering the widget content. All styles |
7951 * in the widget will be replaced with the given set of styles. | 8106 * in the widget will be replaced with the given set of styles. |
7952 * <p> | 8107 * <p> |
7953 * Note: Because a StyleRange includes the start and length, the | 8108 * Note: Because a StyleRange includes the start and length, the |
7954 * same instance cannot occur multiple times in the array of styles. | 8109 * same instance cannot occur multiple times in the array of styles. |
7955 * If the same style attributes, such as font and color, occur in | 8110 * If the same style attributes, such as font and color, occur in |
7956 * multiple StyleRanges, <code>setStyleRanges(int[], StyleRange[])</code> | 8111 * multiple StyleRanges, <code>setStyleRanges(int[], StyleRange[])</code> |
7957 * can be used to share styles and reduce memory usage. | 8112 * can be used to share styles and reduce memory usage. |
7958 * </p><p> | 8113 * </p><p> |
7959 * Should not be called if a LineStyleListener has been set since the | 8114 * Should not be called if a LineStyleListener has been set since the |
7960 * listener maintains the styles. | 8115 * listener maintains the styles. |
7961 * </p> | 8116 * </p> |
7962 * | 8117 * |
7963 * @param ranges StyleRange objects containing the style information. | 8118 * @param ranges StyleRange objects containing the style information. |
7964 * The ranges should not overlap. The style rendering is undefined if | 8119 * The ranges should not overlap. The style rendering is undefined if |
7965 * the ranges do overlap. Must not be null. The styles need to be in order. | 8120 * the ranges do overlap. Must not be null. The styles need to be in order. |
7966 * @exception DWTException <ul> | 8121 * @exception DWTException <ul> |
7967 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 8122 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7968 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 8123 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7969 * </ul> | 8124 * </ul> |
7970 * @exception IllegalArgumentException <ul> | 8125 * @exception IllegalArgumentException <ul> |
7971 * <li>ERROR_NULL_ARGUMENT when the list of ranges is null</li> | 8126 * <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> |
7972 * <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> | 8127 * </ul> |
7973 * </ul> | 8128 * |
7974 * | |
7975 * @see #setStyleRanges(int[], StyleRange[]) | 8129 * @see #setStyleRanges(int[], StyleRange[]) |
7976 */ | 8130 */ |
7977 public void setStyleRanges(StyleRange[] ranges) { | 8131 public void setStyleRanges(StyleRange[] ranges) { |
7978 checkWidget(); | 8132 checkWidget(); |
7979 if (isListening(LineGetStyle)) return; | 8133 if (isListening(LineGetStyle)) return; |
7980 if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | 8134 // DWT extension: allow null for zero length string |
8135 //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); | |
7981 setStyleRanges(0, 0, null, ranges, true); | 8136 setStyleRanges(0, 0, null, ranges, true); |
7982 } | 8137 } |
7983 /** | 8138 /** |
7984 * Sets the tab width. | 8139 * Sets the tab width. |
7985 * | 8140 * |
7986 * @param tabs tab width measured in characters. | 8141 * @param tabs tab width measured in characters. |
7987 * @exception DWTException <ul> | 8142 * @exception DWTException <ul> |
7988 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 8143 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7989 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 8144 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7990 * </ul> | 8145 * </ul> |
7991 */ | 8146 */ |
7992 public void setTabs(int tabs) { | 8147 public void setTabs(int tabs) { |
7993 checkWidget(); | 8148 checkWidget(); |
7994 tabLength = tabs; | 8149 tabLength = tabs; |
7995 renderer.setFont(null, tabs); | 8150 renderer.setFont(null, tabs); |
7996 resetCache(0, content.getLineCount()); | 8151 resetCache(0, content.getLineCount()); |
7997 setCaretLocation(); | 8152 setCaretLocation(); |
7998 super.redraw(); | 8153 super.redraw(); |
7999 } | 8154 } |
8000 /** | 8155 /** |
8001 * Sets the widget content. | 8156 * Sets the widget content. |
8002 * If the widget has the DWT.SINGLE style and "text" contains more than | 8157 * If the widget has the DWT.SINGLE style and "text" contains more than |
8003 * one line, only the first line is rendered but the text is stored | 8158 * one line, only the first line is rendered but the text is stored |
8004 * unchanged. A subsequent call to getText will return the same text | 8159 * unchanged. A subsequent call to getText will return the same text |
8005 * that was set. | 8160 * that was set. |
8006 * <p> | 8161 * <p> |
8007 * <b>Note:</b> Only a single line of text should be set when the DWT.SINGLE | 8162 * <b>Note:</b> Only a single line of text should be set when the DWT.SINGLE |
8008 * style is used. | 8163 * style is used. |
8009 * </p> | 8164 * </p> |
8010 * | 8165 * |
8011 * @param text new widget content. Replaces existing content. Line styles | 8166 * @param text new widget content. Replaces existing content. Line styles |
8012 * that were set using StyledText API are discarded. The | 8167 * that were set using StyledText API are discarded. The |
8013 * current selection is also discarded. | 8168 * current selection is also discarded. |
8014 * @exception DWTException <ul> | 8169 * @exception DWTException <ul> |
8015 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 8170 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
8016 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 8171 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
8017 * </ul> | 8172 * </ul> |
8018 * @exception IllegalArgumentException <ul> | |
8019 * <li>ERROR_NULL_ARGUMENT when String is null</li> | |
8020 * </ul> | |
8021 */ | 8173 */ |
8022 public void setText(String text) { | 8174 public void setText(String text) { |
8023 checkWidget(); | 8175 checkWidget(); |
8024 if (text is null) { | 8176 // DWT extension: allow null for zero length string |
8025 DWT.error(DWT.ERROR_NULL_ARGUMENT); | 8177 // if (text is null) { |
8026 } | 8178 // DWT.error(DWT.ERROR_NULL_ARGUMENT); |
8179 // } | |
8027 Event event = new Event(); | 8180 Event event = new Event(); |
8028 event.start = 0; | 8181 event.start = 0; |
8029 event.end = getCharCount(); | 8182 event.end = getCharCount(); |
8030 event.text = text; | 8183 event.text = text; |
8031 event.doit = true; | 8184 event.doit = true; |
8032 notifyListeners(DWT.Verify, event); | 8185 notifyListeners(DWT.Verify, event); |
8033 if (event.doit) { | 8186 if (event.doit) { |
8034 StyledTextEvent styledTextEvent = null; | 8187 StyledTextEvent styledTextEvent = null; |
8035 if (isListening(ExtendedModify)) { | 8188 if (isListening(ExtendedModify)) { |
8036 styledTextEvent = new StyledTextEvent(content); | 8189 styledTextEvent = new StyledTextEvent(content); |
8037 styledTextEvent.start = event.start; | 8190 styledTextEvent.start = event.start; |
8038 styledTextEvent.end = event.start + event.text.length(); | 8191 styledTextEvent.end = event.start + event.text.length; |
8039 styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); | 8192 styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); |
8040 } | 8193 } |
8041 content.setText(event.text); | 8194 content.setText(event.text); |
8042 sendModifyEvent(event); | 8195 sendModifyEvent(event); |
8043 if (styledTextEvent !is null) { | 8196 if (styledTextEvent !is null) { |
8044 notifyListeners(ExtendedModify, styledTextEvent); | 8197 notifyListeners(ExtendedModify, styledTextEvent); |
8045 } | 8198 } |
8046 } | 8199 } |
8047 } | 8200 } |
8069 textLimit = limit; | 8222 textLimit = limit; |
8070 } | 8223 } |
8071 /** | 8224 /** |
8072 * Sets the top index. Do nothing if there is no text set. | 8225 * Sets the top index. Do nothing if there is no text set. |
8073 * <p> | 8226 * <p> |
8074 * The top index is the index of the line that is currently at the top | 8227 * The top index is the index of the line that is currently at the top |
8075 * of the widget. The top index changes when the widget is scrolled. | 8228 * of the widget. The top index changes when the widget is scrolled. |
8076 * Indexing starts from zero. | 8229 * Indexing starts from zero. |
8077 * Note: The top index is reset to 0 when new text is set in the widget. | 8230 * Note: The top index is reset to 0 when new text is set in the widget. |
8078 * </p> | 8231 * </p> |
8079 * | 8232 * |
8080 * @param topIndex new top index. Must be between 0 and | 8233 * @param topIndex new top index. Must be between 0 and |
8081 * getLineCount() - fully visible lines per page. If no lines are fully | 8234 * getLineCount() - fully visible lines per page. If no lines are fully |
8082 * visible the maximum value is getLineCount() - 1. An out of range | 8235 * visible the maximum value is getLineCount() - 1. An out of range |
8083 * index will be adjusted accordingly. | 8236 * index will be adjusted accordingly. |
8084 * @exception DWTException <ul> | 8237 * @exception DWTException <ul> |
8085 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 8238 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
8086 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 8239 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
8087 * </ul> | 8240 * </ul> |
8106 if (pixel > 0) { | 8259 if (pixel > 0) { |
8107 pixel = getAvailableHeightBellow(pixel); | 8260 pixel = getAvailableHeightBellow(pixel); |
8108 } else { | 8261 } else { |
8109 pixel = getAvailableHeightAbove(pixel); | 8262 pixel = getAvailableHeightAbove(pixel); |
8110 } | 8263 } |
8111 } | 8264 } |
8112 scrollVertical(pixel, true); | 8265 scrollVertical(pixel, true); |
8113 } | 8266 } |
8114 /** | 8267 /** |
8115 * Sets the top pixel offset. Do nothing if there is no text set. | 8268 * Sets the top pixel offset. Do nothing if there is no text set. |
8116 * <p> | 8269 * <p> |
8118 * widget is scrolled so that the given pixel position is at the top. | 8271 * widget is scrolled so that the given pixel position is at the top. |
8119 * The top index is adjusted to the corresponding top line. | 8272 * The top index is adjusted to the corresponding top line. |
8120 * Note: The top pixel is reset to 0 when new text is set in the widget. | 8273 * Note: The top pixel is reset to 0 when new text is set in the widget. |
8121 * </p> | 8274 * </p> |
8122 * | 8275 * |
8123 * @param pixel new top pixel offset. Must be between 0 and | 8276 * @param pixel new top pixel offset. Must be between 0 and |
8124 * (getLineCount() - visible lines per page) / getLineHeight()). An out | 8277 * (getLineCount() - visible lines per page) / getLineHeight()). An out |
8125 * of range offset will be adjusted accordingly. | 8278 * of range offset will be adjusted accordingly. |
8126 * @exception DWTException <ul> | 8279 * @exception DWTException <ul> |
8127 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | 8280 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
8128 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | 8281 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
8131 */ | 8284 */ |
8132 public void setTopPixel(int pixel) { | 8285 public void setTopPixel(int pixel) { |
8133 checkWidget(); | 8286 checkWidget(); |
8134 if (getCharCount() is 0) { | 8287 if (getCharCount() is 0) { |
8135 return; | 8288 return; |
8136 } | 8289 } |
8137 if (pixel < 0) pixel = 0; | 8290 if (pixel < 0) pixel = 0; |
8138 int lineCount = content.getLineCount(); | 8291 int lineCount = content.getLineCount(); |
8139 int height = clientAreaHeight - topMargin - bottomMargin; | 8292 int height = clientAreaHeight - topMargin - bottomMargin; |
8140 int verticalOffset = getVerticalScrollOffset(); | 8293 int verticalOffset = getVerticalScrollOffset(); |
8141 if (isFixedLineHeight()) { | 8294 if (isFixedLineHeight()) { |
8142 int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); | 8295 int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); |
8143 if (pixel > maxTopPixel) pixel = maxTopPixel; | 8296 if (pixel > maxTopPixel) pixel = maxTopPixel; |
8144 pixel -= verticalOffset; | 8297 pixel -= verticalOffset; |
8145 } else { | 8298 } else { |
8146 pixel -= verticalOffset; | 8299 pixel -= verticalOffset; |
8147 if (pixel > 0) { | 8300 if (pixel > 0) { |
8148 pixel = getAvailableHeightBellow(pixel); | 8301 pixel = getAvailableHeightBellow(pixel); |
8149 } | 8302 } |
8173 } | 8326 } |
8174 setScrollBars(true); | 8327 setScrollBars(true); |
8175 setCaretLocation(); | 8328 setCaretLocation(); |
8176 super.redraw(); | 8329 super.redraw(); |
8177 } | 8330 } |
8331 // DWT: If necessary, scroll to show the location | |
8178 bool showLocation(Rectangle rect, bool scrollPage) { | 8332 bool showLocation(Rectangle rect, bool scrollPage) { |
8179 int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; | 8333 int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; |
8180 int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; | 8334 int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; |
8181 bool scrolled = false; | 8335 bool scrolled = false; |
8182 if (rect.y <= topMargin) { | 8336 if (rect.y <= topMargin) { |
8234 endOffset = selection.x; | 8388 endOffset = selection.x; |
8235 } else { | 8389 } else { |
8236 startOffset = selection.x; | 8390 startOffset = selection.x; |
8237 endOffset = selection.y; | 8391 endOffset = selection.y; |
8238 } | 8392 } |
8239 | 8393 |
8240 Rectangle startBounds = getBoundsAtOffset(startOffset); | 8394 Rectangle startBounds = getBoundsAtOffset(startOffset); |
8241 Rectangle endBounds = getBoundsAtOffset(endOffset); | 8395 Rectangle endBounds = getBoundsAtOffset(endOffset); |
8242 | 8396 |
8243 // can the selection be fully displayed within the widget's visible width? | 8397 // can the selection be fully displayed within the widget's visible width? |
8244 int w = clientAreaWidth - leftMargin - rightMargin; | 8398 int w = clientAreaWidth - leftMargin - rightMargin; |
8245 bool selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; | 8399 bool selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; |
8246 if (selectionFits) { | 8400 if (selectionFits) { |
8247 // show as much of the selection as possible by first showing | 8401 // show as much of the selection as possible by first showing |
8252 } | 8406 } |
8253 // the character at endOffset is not part of the selection | 8407 // the character at endOffset is not part of the selection |
8254 endBounds.width = 0; | 8408 endBounds.width = 0; |
8255 showLocation(endBounds, false); | 8409 showLocation(endBounds, false); |
8256 } else { | 8410 } else { |
8257 // just show the end of the selection since the selection start | 8411 // just show the end of the selection since the selection start |
8258 // will not be visible | 8412 // will not be visible |
8259 showLocation(endBounds, true); | 8413 showLocation(endBounds, true); |
8260 } | 8414 } |
8261 } | 8415 } |
8262 /** | 8416 /** |
8263 * Updates the selection and caret position depending on the text change. | 8417 * Updates the selection and caret position depending on the text change. |
8264 * <p> | 8418 * <p> |
8265 * If the selection intersects with the replaced text, the selection is | 8419 * If the selection intersects with the replaced text, the selection is |
8266 * reset and the caret moved to the end of the new text. | 8420 * reset and the caret moved to the end of the new text. |
8267 * If the selection is behind the replaced text it is moved so that the | 8421 * If the selection is behind the replaced text it is moved so that the |
8268 * same text remains selected. If the selection is before the replaced text | 8422 * same text remains selected. If the selection is before the replaced text |
8269 * it is left unchanged. | 8423 * it is left unchanged. |
8270 * </p> | 8424 * </p> |
8271 * | 8425 * |
8272 * @param startOffset offset of the text change | 8426 * @param startOffset offset of the text change |
8273 * @param replacedLength length of text being replaced | 8427 * @param replacedLength length of text being replaced |
8274 * @param newLength length of new text | 8428 * @param newLength length of new text |
8275 */ | 8429 */ |
8276 void updateSelection(int startOffset, int replacedLength, int newLength) { | 8430 void updateSelection(int startOffset, int replacedLength, int newLength) { |
8277 if (selection.y <= startOffset) { | 8431 if (selection.y <= startOffset) { |
8278 // selection ends before text change | 8432 // selection ends before text change |
8433 if (wordWrap) setCaretLocation(); | |
8279 return; | 8434 return; |
8280 } | 8435 } |
8281 if (selection.x < startOffset) { | 8436 if (selection.x < startOffset) { |
8282 // clear selection fragment before text change | 8437 // clear selection fragment before text change |
8283 internalRedrawRange(selection.x, startOffset - selection.x); | 8438 internalRedrawRange(selection.x, startOffset - selection.x); |
8284 } | 8439 } |
8285 if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { | 8440 if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { |
8286 // clear selection fragment after text change. | 8441 // clear selection fragment after text change. |
8287 // do this only when the selection is actually affected by the | 8442 // do this only when the selection is actually affected by the |
8288 // change. Selection is only affected if it intersects the change (1GDY217). | 8443 // change. Selection is only affected if it intersects the change (1GDY217). |
8289 int netNewLength = newLength - replacedLength; | 8444 int netNewLength = newLength - replacedLength; |
8290 int redrawStart = startOffset + newLength; | 8445 int redrawStart = startOffset + newLength; |
8291 internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart); | 8446 internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart); |
8292 } | 8447 } |