Lines 1-9
Link Here
|
1 |
package org.eclipse.swt.custom; |
1 |
package org.eclipse.swt.custom; |
2 |
|
2 |
|
3 |
/* |
3 |
/* |
4 |
* Copyright (c) 2000, 2002 IBM Corp. All rights reserved. |
4 |
* Copyright (c) 2000, 2002 IBM Corp. All rights reserved. |
5 |
* This file is made available under the terms of the Common Public License v1.0 |
5 |
* This file is made available under the terms of the Common Public License v1.0 |
6 |
* which accompanies this distribution, and is available at |
6 |
* which accompanies this distribution, and is available at |
7 |
* http://www.eclipse.org/legal/cpl-v10.html |
7 |
* http://www.eclipse.org/legal/cpl-v10.html |
8 |
*/ |
8 |
*/ |
9 |
|
9 |
|
Lines 18-39
Link Here
|
18 |
import org.eclipse.swt.widgets.*; |
18 |
import org.eclipse.swt.widgets.*; |
19 |
|
19 |
|
20 |
/** |
20 |
/** |
21 |
* A StyledText is an editable user interface object that displays lines |
21 |
* A StyledText is an editable user interface object that displays lines |
22 |
* of text. The following style attributes can be defined for the text: |
22 |
* of text. The following style attributes can be defined for the text: |
23 |
* <ul> |
23 |
* <ul> |
24 |
* <li>foreground color |
24 |
* <li>foreground color |
25 |
* <li>background color |
25 |
* <li>background color |
26 |
* <li>font style (bold, regular) |
26 |
* <li>font style (bold, regular) |
27 |
* </ul> |
27 |
* </ul> |
28 |
* <p> |
28 |
* <p> |
29 |
* In addition to text style attributes, the background color of a line may |
29 |
* In addition to text style attributes, the background color of a line may |
30 |
* be specified. |
30 |
* be specified. |
31 |
* </p> |
31 |
* </p> |
32 |
* <p> |
32 |
* <p> |
33 |
* There are two ways to use this widget when specifying text style information. |
33 |
* There are two ways to use this widget when specifying text style information. |
34 |
* You may use the API that is defined for StyledText or you may define your own |
34 |
* You may use the API that is defined for StyledText or you may define your own |
35 |
* LineStyleListener. If you define your own listener, you will be responsible |
35 |
* LineStyleListener. If you define your own listener, you will be responsible |
36 |
* for maintaining the text style information for the widget. IMPORTANT: You may |
36 |
* for maintaining the text style information for the widget. IMPORTANT: You may |
37 |
* not define your own listener and use the StyledText API. The following |
37 |
* not define your own listener and use the StyledText API. The following |
38 |
* StyledText API is not supported if you have defined a LineStyleListener: |
38 |
* StyledText API is not supported if you have defined a LineStyleListener: |
39 |
* <ul> |
39 |
* <ul> |
Lines 46-56
Link Here
|
46 |
* </p> |
46 |
* </p> |
47 |
* <p> |
47 |
* <p> |
48 |
* There are two ways to use this widget when specifying line background colors. |
48 |
* There are two ways to use this widget when specifying line background colors. |
49 |
* You may use the API that is defined for StyledText or you may define your own |
49 |
* You may use the API that is defined for StyledText or you may define your own |
50 |
* LineBackgroundListener. If you define your own listener, you will be responsible |
50 |
* LineBackgroundListener. If you define your own listener, you will be responsible |
51 |
* for maintaining the line background color information for the widget. |
51 |
* for maintaining the line background color information for the widget. |
52 |
* IMPORTANT: You may not define your own listener and use the StyledText API. |
52 |
* IMPORTANT: You may not define your own listener and use the StyledText API. |
53 |
* The following StyledText API is not supported if you have defined a |
53 |
* The following StyledText API is not supported if you have defined a |
54 |
* LineBackgroundListener: |
54 |
* LineBackgroundListener: |
55 |
* <ul> |
55 |
* <ul> |
56 |
* <li>getLineBackground(int) |
56 |
* <li>getLineBackground(int) |
Lines 60-66
Link Here
|
60 |
* <p> |
60 |
* <p> |
61 |
* The content implementation for this widget may also be user-defined. To do so, |
61 |
* The content implementation for this widget may also be user-defined. To do so, |
62 |
* you must implement the StyledTextContent interface and use the StyledText API |
62 |
* you must implement the StyledTextContent interface and use the StyledText API |
63 |
* setContent(StyledTextContent) to initialize the widget. |
63 |
* setContent(StyledTextContent) to initialize the widget. |
64 |
* </p> |
64 |
* </p> |
65 |
* <p> |
65 |
* <p> |
66 |
* IMPORTANT: This class is <em>not</em> intended to be subclassed. |
66 |
* IMPORTANT: This class is <em>not</em> intended to be subclassed. |
Lines 71-1550
Link Here
|
71 |
* </dl> |
71 |
* </dl> |
72 |
*/ |
72 |
*/ |
73 |
public class StyledText extends Canvas { |
73 |
public class StyledText extends Canvas { |
74 |
static final char TAB = '\t'; |
74 |
static final char TAB = '\t'; |
75 |
static final String PlatformLineDelimiter = System.getProperty("line.separator"); |
75 |
static final String PlatformLineDelimiter = System.getProperty("line.separator"); |
76 |
static final int BIDI_CARET_WIDTH = 4; |
76 |
static final int BIDI_CARET_WIDTH = 4; |
77 |
static final int XINSET = BIDI_CARET_WIDTH - 1; |
77 |
static final int XINSET = BIDI_CARET_WIDTH - 1; |
78 |
static final int DEFAULT_WIDTH = 64; |
78 |
static final int DEFAULT_WIDTH = 64; |
79 |
static final int DEFAULT_HEIGHT = 64; |
79 |
static final int DEFAULT_HEIGHT = 64; |
80 |
|
80 |
|
81 |
static final int ExtendedModify = 3000; |
81 |
static final int ExtendedModify = 3000; |
82 |
static final int LineGetBackground = 3001; |
82 |
static final int LineGetBackground = 3001; |
83 |
static final int LineGetStyle = 3002; |
83 |
static final int LineGetStyle = 3002; |
84 |
static final int TextChanging = 3003; |
84 |
static final int TextChanging = 3003; |
85 |
static final int TextSet = 3004; |
85 |
static final int TextSet = 3004; |
86 |
static final int VerifyKey = 3005; |
86 |
static final int VerifyKey = 3005; |
87 |
static final int TextChanged = 3006; |
87 |
static final int TextChanged = 3006; |
88 |
static final int LineGetSegments = 3007; |
88 |
static final int LineGetSegments = 3007; |
89 |
|
89 |
|
90 |
Color selectionBackground; // selection background color |
90 |
Color selectionBackground; // selection background color |
91 |
Color selectionForeground; // selection foreground color |
91 |
Color selectionForeground; // selection foreground color |
92 |
StyledTextContent logicalContent; // native content (default or user specified) |
92 |
StyledTextContent logicalContent; // native content (default or user specified) |
93 |
StyledTextContent content; // line wrapping content, same as logicalContent if word wrap is off |
93 |
StyledTextContent content; // line wrapping content, same as logicalContent if word wrap is off |
94 |
DisplayRenderer renderer; |
94 |
DisplayRenderer renderer; |
95 |
TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent |
95 |
TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent |
96 |
DefaultLineStyler defaultLineStyler;// used for setStyles API when no LineStyleListener is registered |
96 |
DefaultLineStyler defaultLineStyler;// used for setStyles API when no LineStyleListener is registered |
97 |
LineCache lineCache; |
97 |
LineCache lineCache; |
98 |
boolean userLineStyle = false; // true=widget is using a user defined line style listener for line styles. false=widget is using the default line styler to store line styles |
98 |
boolean userLineStyle = false; // true=widget is using a user defined line style listener for line styles. false=widget is using the default line styler to store line styles |
99 |
boolean userLineBackground = false; // true=widget is using a user defined line background listener for line backgrounds. false=widget is using the default line styler to store line backgrounds |
99 |
boolean userLineBackground = false; // true=widget is using a user defined line background listener for line backgrounds. false=widget is using the default line styler to store line backgrounds |
100 |
int verticalScrollOffset = 0; // pixel based |
100 |
int verticalScrollOffset = 0; // pixel based |
101 |
int horizontalScrollOffset = 0; // pixel based |
101 |
int horizontalScrollOffset = 0; // pixel based |
102 |
int topIndex = 0; // top visible line |
102 |
int topIndex = 0; // top visible line |
103 |
int topOffset = 0; // offset of first character in top line |
103 |
int topOffset = 0; // offset of first character in top line |
104 |
int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new |
104 |
int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new |
105 |
// visible lines during Resize callback |
105 |
// visible lines during Resize callback |
106 |
int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine |
106 |
int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine |
107 |
// if line wrap needs to be recalculated |
107 |
// if line wrap needs to be recalculated |
108 |
int lineHeight; // line height=font height |
108 |
int lineHeight; // line height=font height |
109 |
int tabLength = 4; // number of characters in a tab |
109 |
int tabLength = 4; // number of characters in a tab |
110 |
int lineEndSpaceWidth; // space, in pixel, used to indicated a selected line break |
110 |
int lineEndSpaceWidth; // space, in pixel, used to indicated a selected line break |
111 |
int leftMargin = 1; |
111 |
int leftMargin = 1; |
112 |
int topMargin = 1; |
112 |
int topMargin = 1; |
113 |
int rightMargin = 2; |
113 |
int rightMargin = 2; |
114 |
int bottomMargin = 2; |
114 |
int bottomMargin = 2; |
115 |
Cursor ibeamCursor; |
115 |
Cursor ibeamCursor; |
116 |
int columnX; // keep track of the horizontal caret position |
116 |
Cursor arrowCursor; |
117 |
// when changing lines/pages. Fixes bug 5935 |
117 |
Cursor currentCursor; // tracks the current mouse pointer |
118 |
int caretOffset = 0; |
118 |
Cursor customCursor = null; |
119 |
Point selection = new Point(0, 0); // x is character offset, y is length |
119 |
int columnX; // keep track of the horizontal caret position |
120 |
int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text |
120 |
// when changing lines/pages. Fixes bug 5935 |
121 |
Point doubleClickSelection; // selection after last mouse double click |
121 |
int caretOffset = 0; |
122 |
boolean editable = true; |
122 |
Point selection = new Point(0, 0); // x is the beginning character offset, y is the ending character offset |
123 |
boolean wordWrap = false; |
123 |
int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text |
124 |
boolean doubleClickEnabled = true; // see getDoubleClickEnabled |
124 |
Point doubleClickSelection; // selection after last mouse double click |
125 |
boolean overwrite = false; // insert/overwrite edit mode |
125 |
boolean editable = true; |
126 |
int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. |
126 |
boolean wordWrap = false; |
127 |
Hashtable keyActionMap = new Hashtable(); |
127 |
boolean doubleClickEnabled = true; // see getDoubleClickEnabled |
128 |
Color background = null; // workaround for bug 4791 |
128 |
boolean overwrite = false; // insert/overwrite edit mode |
129 |
Color foreground = null; // |
129 |
int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. |
130 |
Clipboard clipboard; |
130 |
Hashtable keyActionMap = new Hashtable(); |
131 |
boolean mouseDoubleClick = false; // true=a double click ocurred. Don't do mouse swipe selection. |
131 |
Color background = null; // workaround for bug 4791 |
132 |
int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left) |
132 |
Color foreground = null; // |
133 |
int lastTextChangeStart; // cache data of the |
133 |
Clipboard clipboard; |
134 |
int lastTextChangeNewLineCount; // last text changing |
134 |
boolean mouseDoubleClick = false; // true=a double click ocurred. Don't do mouse swipe selection. |
135 |
int lastTextChangeNewCharCount; // event for use in the |
135 |
int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left) |
136 |
int lastTextChangeReplaceLineCount; // text changed handler |
136 |
int lastTextChangeStart; // cache data of the |
137 |
int lastTextChangeReplaceCharCount; |
137 |
int lastTextChangeNewLineCount; // last text changing |
138 |
boolean isBidi; |
138 |
int lastTextChangeNewCharCount; // event for use in the |
139 |
boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color |
139 |
int lastTextChangeReplaceLineCount; // text changed handler |
140 |
Image leftCaretBitmap = null; |
140 |
int lastTextChangeReplaceCharCount; |
141 |
Image rightCaretBitmap = null; |
141 |
boolean isBidi; |
142 |
int caretDirection = SWT.NULL; |
142 |
boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color |
143 |
PaletteData caretPalette = null; |
143 |
Image leftCaretBitmap = null; |
144 |
int lastCaretDirection = SWT.NULL; |
144 |
Image rightCaretBitmap = null; |
145 |
boolean isCarbon; // flag set to true on Mac OSX |
145 |
int caretDirection = SWT.NULL; |
146 |
|
146 |
PaletteData caretPalette = null; |
147 |
/** |
147 |
int lastCaretDirection = SWT.NULL; |
148 |
* The Printing class implements printing of a range of text. |
148 |
boolean isCarbon; // flag set to true on Mac OSX |
149 |
* An instance of <class>Printing </class> is returned in the |
149 |
|
150 |
* StyledText#print(Printer) API. The run() method may be |
150 |
/** |
151 |
* invoked from any thread. |
151 |
* The Printing class implements printing of a range of text. |
152 |
*/ |
152 |
* An instance of <class>Printing </class> is returned in the |
153 |
class Printing implements Runnable { |
153 |
* StyledText#print(Printer) API. The run() method may be |
154 |
final static int LEFT = 0; // left aligned header/footer segment |
154 |
* invoked from any thread. |
155 |
final static int CENTER = 1; // centered header/footer segment |
155 |
*/ |
156 |
final static int RIGHT = 2; // right aligned header/footer segment |
156 |
class Printing implements Runnable { |
157 |
|
157 |
final static int LEFT = 0; // left aligned header/footer segment |
158 |
Printer printer; |
158 |
final static int CENTER = 1; // centered header/footer segment |
159 |
PrintRenderer renderer; |
159 |
final static int RIGHT = 2; // right aligned header/footer segment |
160 |
StyledTextPrintOptions printOptions; |
160 |
|
161 |
StyledTextContent printerContent; // copy of the widget content |
161 |
Printer printer; |
162 |
Rectangle clientArea; // client area to print on |
162 |
PrintRenderer renderer; |
163 |
Font printerFont; |
163 |
StyledTextPrintOptions printOptions; |
164 |
FontData displayFontData; |
164 |
StyledTextContent printerContent; // copy of the widget content |
165 |
Hashtable printerColors; // printer color cache for line backgrounds and style |
165 |
Rectangle clientArea; // client area to print on |
166 |
Hashtable lineBackgrounds = new Hashtable(); // cached line backgrounds |
166 |
Font printerFont; |
167 |
Hashtable lineStyles = new Hashtable(); // cached line styles |
167 |
FontData displayFontData; |
168 |
Hashtable bidiSegments = new Hashtable(); // cached bidi segments when running on a bidi platform |
168 |
Hashtable printerColors; // printer color cache for line backgrounds and style |
169 |
GC gc; // printer GC |
169 |
Hashtable lineBackgrounds = new Hashtable(); // cached line backgrounds |
170 |
int pageWidth; // width of a printer page in pixels |
170 |
Hashtable lineStyles = new Hashtable(); // cached line styles |
171 |
int startPage; // first page to print |
171 |
Hashtable bidiSegments = new Hashtable(); // cached bidi segments when running on a bidi platform |
172 |
int endPage; // last page to print |
172 |
GC gc; // printer GC |
173 |
int pageSize; // number of lines on a page |
173 |
int pageWidth; // width of a printer page in pixels |
174 |
int startLine; // first (wrapped) line to print |
174 |
int startPage; // first page to print |
175 |
int endLine; // last (wrapped) line to print |
175 |
int endPage; // last page to print |
176 |
boolean singleLine; // widget single line mode |
176 |
int pageSize; // number of lines on a page |
177 |
Point selection = null; // selected text |
177 |
int startLine; // first (wrapped) line to print |
178 |
|
178 |
int endLine; // last (wrapped) line to print |
179 |
/** |
179 |
boolean singleLine; // widget single line mode |
180 |
* Creates an instance of <class>Printing</class>. |
180 |
Point selection = null; // selected text |
181 |
* Copies the widget content and rendering data that needs |
181 |
|
182 |
* to be requested from listeners. |
182 |
/** |
183 |
* </p> |
183 |
* Creates an instance of <class>Printing</class>. |
184 |
* @param parent StyledText widget to print. |
184 |
* Copies the widget content and rendering data that needs |
185 |
* @param printer printer device to print on. |
185 |
* to be requested from listeners. |
186 |
* @param printOptions print options |
186 |
* </p> |
187 |
*/ |
187 |
* @param parent StyledText widget to print. |
188 |
Printing(StyledText parent, Printer printer, StyledTextPrintOptions printOptions) { |
188 |
* @param printer printer device to print on. |
189 |
PrinterData data = printer.getPrinterData(); |
189 |
* @param printOptions print options |
190 |
|
190 |
*/ |
191 |
this.printer = printer; |
191 |
Printing(StyledText parent, Printer printer, StyledTextPrintOptions printOptions) { |
192 |
this.printOptions = printOptions; |
192 |
PrinterData data = printer.getPrinterData(); |
193 |
singleLine = parent.isSingleLine(); |
193 |
|
194 |
startPage = 1; |
194 |
this.printer = printer; |
195 |
endPage = Integer.MAX_VALUE; |
195 |
this.printOptions = printOptions; |
196 |
if (data.scope == PrinterData.PAGE_RANGE) { |
196 |
singleLine = parent.isSingleLine(); |
197 |
startPage = data.startPage; |
197 |
startPage = 1; |
198 |
endPage = data.endPage; |
198 |
endPage = Integer.MAX_VALUE; |
199 |
if (endPage < startPage) { |
199 |
if (data.scope == PrinterData.PAGE_RANGE) { |
200 |
int temp = endPage; |
200 |
startPage = data.startPage; |
201 |
endPage = startPage; |
201 |
endPage = data.endPage; |
202 |
startPage = temp; |
202 |
if (endPage < startPage) { |
203 |
} |
203 |
int temp = endPage; |
204 |
} if (data.scope == PrinterData.SELECTION) { |
204 |
endPage = startPage; |
205 |
selection = parent.getSelectionRange(); |
205 |
startPage = temp; |
206 |
} |
206 |
} |
207 |
|
207 |
} if (data.scope == PrinterData.SELECTION) { |
208 |
displayFontData = getFont().getFontData()[0]; |
208 |
selection = parent.getSelectionRange(); |
209 |
copyContent(parent.getContent()); |
209 |
} |
210 |
cacheLineData(printerContent); |
210 |
|
211 |
} |
211 |
displayFontData = getFont().getFontData()[0]; |
212 |
/** |
212 |
copyContent(parent.getContent()); |
213 |
* Caches the bidi segments of the given line. |
213 |
cacheLineData(printerContent); |
214 |
* </p> |
214 |
} |
215 |
* @param lineOffset offset of the line to cache bidi segments for. |
215 |
/** |
216 |
* Relative to the start of the document. |
216 |
* Caches the bidi segments of the given line. |
217 |
* @param line line to cache bidi segments for. |
217 |
* </p> |
218 |
*/ |
218 |
* @param lineOffset offset of the line to cache bidi segments for. |
219 |
void cacheBidiSegments(int lineOffset, String line) { |
219 |
* Relative to the start of the document. |
220 |
int[] segments = getBidiSegments(lineOffset, line); |
220 |
* @param line line to cache bidi segments for. |
221 |
|
221 |
*/ |
222 |
if (segments != null) { |
222 |
void cacheBidiSegments(int lineOffset, String line) { |
223 |
bidiSegments.put(new Integer(lineOffset), segments); |
223 |
int[] segments = getBidiSegments(lineOffset, line); |
224 |
} |
224 |
|
225 |
} |
225 |
if (segments != null) { |
226 |
/** |
226 |
bidiSegments.put(new Integer(lineOffset), segments); |
227 |
* Caches the line background color of the given line. |
227 |
} |
228 |
* </p> |
228 |
} |
229 |
* @param lineOffset offset of the line to cache the background |
229 |
/** |
230 |
* color for. Relative to the start of the document. |
230 |
* Caches the line background color of the given line. |
231 |
* @param line line to cache the background color for |
231 |
* </p> |
232 |
*/ |
232 |
* @param lineOffset offset of the line to cache the background |
233 |
void cacheLineBackground(int lineOffset, String line) { |
233 |
* color for. Relative to the start of the document. |
234 |
StyledTextEvent event = getLineBackgroundData(lineOffset, line); |
234 |
* @param line line to cache the background color for |
235 |
|
235 |
*/ |
236 |
if (event != null) { |
236 |
void cacheLineBackground(int lineOffset, String line) { |
237 |
lineBackgrounds.put(new Integer(lineOffset), event); |
237 |
StyledTextEvent event = getLineBackgroundData(lineOffset, line); |
238 |
} |
238 |
|
239 |
} |
239 |
if (event != null) { |
240 |
/** |
240 |
lineBackgrounds.put(new Integer(lineOffset), event); |
241 |
* Caches all line data that needs to be requested from a listener. |
241 |
} |
242 |
* </p> |
242 |
} |
243 |
* @param printerContent <class>StyledTextContent</class> to request |
243 |
/** |
244 |
* line data for. |
244 |
* Caches all line data that needs to be requested from a listener. |
245 |
*/ |
245 |
* </p> |
246 |
void cacheLineData(StyledTextContent printerContent) { |
246 |
* @param printerContent <class>StyledTextContent</class> to request |
247 |
for (int i = 0; i < printerContent.getLineCount(); i++) { |
247 |
* line data for. |
248 |
int lineOffset = printerContent.getOffsetAtLine(i); |
248 |
*/ |
249 |
String line = printerContent.getLine(i); |
249 |
void cacheLineData(StyledTextContent printerContent) { |
250 |
|
250 |
for (int i = 0; i < printerContent.getLineCount(); i++) { |
251 |
if (printOptions.printLineBackground) { |
251 |
int lineOffset = printerContent.getOffsetAtLine(i); |
252 |
cacheLineBackground(lineOffset, line); |
252 |
String line = printerContent.getLine(i); |
253 |
} |
253 |
|
254 |
if (printOptions.printTextBackground || |
254 |
if (printOptions.printLineBackground) { |
255 |
printOptions.printTextForeground || |
255 |
cacheLineBackground(lineOffset, line); |
256 |
printOptions.printTextFontStyle) { |
256 |
} |
257 |
cacheLineStyle(lineOffset, line); |
257 |
if (printOptions.printTextBackground || |
258 |
} |
258 |
printOptions.printTextForeground || |
259 |
if (isBidi()) { |
259 |
printOptions.printTextFontStyle) { |
260 |
cacheBidiSegments(lineOffset, line); |
260 |
cacheLineStyle(lineOffset, line); |
261 |
} |
261 |
} |
262 |
} |
262 |
if (isBidi()) { |
263 |
} |
263 |
cacheBidiSegments(lineOffset, line); |
264 |
/** |
264 |
} |
265 |
* Caches all line styles of the given line. |
265 |
} |
266 |
* </p> |
266 |
} |
267 |
* @param lineOffset offset of the line to cache the styles for. |
267 |
/** |
268 |
* Relative to the start of the document. |
268 |
* Caches all line styles of the given line. |
269 |
* @param line line to cache the styles for. |
269 |
* </p> |
270 |
*/ |
270 |
* @param lineOffset offset of the line to cache the styles for. |
271 |
void cacheLineStyle(int lineOffset, String line) { |
271 |
* Relative to the start of the document. |
272 |
StyledTextEvent event = getLineStyleData(lineOffset, line); |
272 |
* @param line line to cache the styles for. |
273 |
|
273 |
*/ |
274 |
if (event != null) { |
274 |
void cacheLineStyle(int lineOffset, String line) { |
275 |
StyleRange[] styles = event.styles; |
275 |
StyledTextEvent event = getLineStyleData(lineOffset, line); |
276 |
for (int i = 0; i < styles.length; i++) { |
276 |
|
277 |
StyleRange styleCopy = null; |
277 |
if (event != null) { |
278 |
if (printOptions.printTextBackground == false && styles[i].background != null) { |
278 |
StyleRange[] styles = event.styles; |
279 |
styleCopy = (StyleRange) styles[i].clone(); |
279 |
for (int i = 0; i < styles.length; i++) { |
280 |
styleCopy.background = null; |
280 |
StyleRange styleCopy = null; |
281 |
} |
281 |
if (printOptions.printTextBackground == false && styles[i].background != null) { |
282 |
if (printOptions.printTextForeground == false && styles[i].foreground != null) { |
282 |
styleCopy = (StyleRange) styles[i].clone(); |
283 |
if (styleCopy == null) { |
283 |
styleCopy.background = null; |
284 |
styleCopy = (StyleRange) styles[i].clone(); |
284 |
} |
285 |
} |
285 |
if (printOptions.printTextForeground == false && styles[i].foreground != null) { |
286 |
styleCopy.foreground = null; |
286 |
if (styleCopy == null) { |
287 |
} |
287 |
styleCopy = (StyleRange) styles[i].clone(); |
288 |
if (printOptions.printTextFontStyle == false && styles[i].fontStyle != SWT.NORMAL) { |
288 |
} |
289 |
if (styleCopy == null) { |
289 |
styleCopy.foreground = null; |
290 |
styleCopy = (StyleRange) styles[i].clone(); |
290 |
} |
291 |
} |
291 |
if (printOptions.printTextFontStyle == false && styles[i].fontStyle != SWT.NORMAL) { |
292 |
styleCopy.fontStyle = SWT.NORMAL; |
292 |
if (styleCopy == null) { |
293 |
} |
293 |
styleCopy = (StyleRange) styles[i].clone(); |
294 |
if (styleCopy != null) { |
294 |
} |
295 |
styles[i] = styleCopy; |
295 |
styleCopy.fontStyle = SWT.NORMAL; |
296 |
} |
296 |
} |
297 |
} |
297 |
if (styleCopy != null) { |
298 |
lineStyles.put(new Integer(lineOffset), event); |
298 |
styles[i] = styleCopy; |
299 |
} |
299 |
} |
300 |
} |
300 |
} |
301 |
/** |
301 |
lineStyles.put(new Integer(lineOffset), event); |
302 |
* Copies the text of the specified <class>StyledTextContent</class>. |
302 |
} |
303 |
* </p> |
303 |
} |
304 |
* @param original the <class>StyledTextContent</class> to copy. |
304 |
/** |
305 |
*/ |
305 |
* Copies the text of the specified <class>StyledTextContent</class>. |
306 |
void copyContent(StyledTextContent original) { |
306 |
* </p> |
307 |
int insertOffset = 0; |
307 |
* @param original the <class>StyledTextContent</class> to copy. |
308 |
|
308 |
*/ |
309 |
printerContent = new DefaultContent(); |
309 |
void copyContent(StyledTextContent original) { |
310 |
for (int i = 0; i < original.getLineCount(); i++) { |
310 |
int insertOffset = 0; |
311 |
int insertEndOffset; |
311 |
|
312 |
if (i < original.getLineCount() - 1) { |
312 |
printerContent = new DefaultContent(); |
313 |
insertEndOffset = original.getOffsetAtLine(i + 1); |
313 |
for (int i = 0; i < original.getLineCount(); i++) { |
314 |
} |
314 |
int insertEndOffset; |
315 |
else { |
315 |
if (i < original.getLineCount() - 1) { |
316 |
insertEndOffset = original.getCharCount(); |
316 |
insertEndOffset = original.getOffsetAtLine(i + 1); |
317 |
} |
317 |
} |
318 |
printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset)); |
318 |
else { |
319 |
insertOffset = insertEndOffset; |
319 |
insertEndOffset = original.getCharCount(); |
320 |
} |
320 |
} |
321 |
} |
321 |
printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset)); |
322 |
/** |
322 |
insertOffset = insertEndOffset; |
323 |
* Replaces all display colors in the cached line backgrounds and |
323 |
} |
324 |
* line styles with printer colors. |
324 |
} |
325 |
*/ |
325 |
/** |
326 |
void createPrinterColors() { |
326 |
* Replaces all display colors in the cached line backgrounds and |
327 |
Enumeration values = lineBackgrounds.elements(); |
327 |
* line styles with printer colors. |
328 |
printerColors = new Hashtable(); |
328 |
*/ |
329 |
while (values.hasMoreElements()) { |
329 |
void createPrinterColors() { |
330 |
StyledTextEvent event = (StyledTextEvent) values.nextElement(); |
330 |
Enumeration values = lineBackgrounds.elements(); |
331 |
event.lineBackground = getPrinterColor(event.lineBackground); |
331 |
printerColors = new Hashtable(); |
332 |
} |
332 |
while (values.hasMoreElements()) { |
333 |
|
333 |
StyledTextEvent event = (StyledTextEvent) values.nextElement(); |
334 |
values = lineStyles.elements(); |
334 |
event.lineBackground = getPrinterColor(event.lineBackground); |
335 |
while (values.hasMoreElements()) { |
335 |
} |
336 |
StyledTextEvent event = (StyledTextEvent) values.nextElement(); |
336 |
|
337 |
for (int i = 0; i < event.styles.length; i++) { |
337 |
values = lineStyles.elements(); |
338 |
StyleRange style = event.styles[i]; |
338 |
while (values.hasMoreElements()) { |
339 |
Color printerBackground = getPrinterColor(style.background); |
339 |
StyledTextEvent event = (StyledTextEvent) values.nextElement(); |
340 |
Color printerForeground = getPrinterColor(style.foreground); |
340 |
for (int i = 0; i < event.styles.length; i++) { |
341 |
|
341 |
StyleRange style = event.styles[i]; |
342 |
if (printerBackground != style.background || |
342 |
Color printerBackground = getPrinterColor(style.background); |
343 |
printerForeground != style.foreground) { |
343 |
Color printerForeground = getPrinterColor(style.foreground); |
344 |
style = (StyleRange) style.clone(); |
344 |
|
345 |
style.background = printerBackground; |
345 |
if (printerBackground != style.background || |
346 |
style.foreground = printerForeground; |
346 |
printerForeground != style.foreground) { |
347 |
event.styles[i] = style; |
347 |
style = (StyleRange) style.clone(); |
348 |
} |
348 |
style.background = printerBackground; |
349 |
} |
349 |
style.foreground = printerForeground; |
350 |
} |
350 |
event.styles[i] = style; |
351 |
} |
351 |
} |
352 |
/** |
352 |
} |
353 |
* Disposes of the resources and the <class>PrintRenderer</class>. |
353 |
} |
354 |
*/ |
354 |
} |
355 |
void dispose() { |
355 |
/** |
356 |
if (printerColors != null) { |
356 |
* Disposes of the resources and the <class>PrintRenderer</class>. |
357 |
Enumeration colors = printerColors.elements(); |
357 |
*/ |
358 |
|
358 |
void dispose() { |
359 |
while (colors.hasMoreElements()) { |
359 |
if (printerColors != null) { |
360 |
Color color = (Color) colors.nextElement(); |
360 |
Enumeration colors = printerColors.elements(); |
361 |
color.dispose(); |
361 |
|
362 |
} |
362 |
while (colors.hasMoreElements()) { |
363 |
printerColors = null; |
363 |
Color color = (Color) colors.nextElement(); |
364 |
} |
364 |
color.dispose(); |
365 |
if (gc != null) { |
365 |
} |
366 |
gc.dispose(); |
366 |
printerColors = null; |
367 |
gc = null; |
367 |
} |
368 |
} |
368 |
if (gc != null) { |
369 |
if (printerFont != null) { |
369 |
gc.dispose(); |
370 |
printerFont.dispose(); |
370 |
gc = null; |
371 |
printerFont = null; |
371 |
} |
372 |
} |
372 |
if (printerFont != null) { |
373 |
if (renderer != null) { |
373 |
printerFont.dispose(); |
374 |
renderer.dispose(); |
374 |
printerFont = null; |
375 |
renderer = null; |
375 |
} |
376 |
} |
376 |
if (renderer != null) { |
377 |
} |
377 |
renderer.dispose(); |
378 |
/** |
378 |
renderer = null; |
379 |
* Finish printing the indicated page. |
379 |
} |
380 |
* |
380 |
} |
381 |
* @param page page that was printed |
381 |
/** |
382 |
*/ |
382 |
* Finish printing the indicated page. |
383 |
void endPage(int page) { |
383 |
* |
384 |
printDecoration(page, false); |
384 |
* @param page page that was printed |
385 |
printer.endPage(); |
385 |
*/ |
386 |
} |
386 |
void endPage(int page) { |
387 |
/** |
387 |
printDecoration(page, false); |
388 |
* Creates a <class>PrintRenderer</class> and calculate the line range |
388 |
printer.endPage(); |
389 |
* to print. |
389 |
} |
390 |
*/ |
390 |
/** |
391 |
void initializeRenderer() { |
391 |
* Creates a <class>PrintRenderer</class> and calculate the line range |
392 |
Rectangle trim = printer.computeTrim(0, 0, 0, 0); |
392 |
* to print. |
393 |
Point dpi = printer.getDPI(); |
393 |
*/ |
394 |
|
394 |
void initializeRenderer() { |
395 |
printerFont = new Font(printer, displayFontData.getName(), displayFontData.getHeight(), SWT.NORMAL); |
395 |
Rectangle trim = printer.computeTrim(0, 0, 0, 0); |
396 |
clientArea = printer.getClientArea(); |
396 |
Point dpi = printer.getDPI(); |
397 |
pageWidth = clientArea.width; |
397 |
|
398 |
// one inch margin around text |
398 |
printerFont = new Font(printer, displayFontData.getName(), displayFontData.getHeight(), SWT.NORMAL); |
399 |
clientArea.x = dpi.x + trim.x; |
399 |
clientArea = printer.getClientArea(); |
400 |
clientArea.y = dpi.y + trim.y; |
400 |
pageWidth = clientArea.width; |
401 |
clientArea.width -= (clientArea.x + trim.width); |
401 |
// one inch margin around text |
402 |
clientArea.height -= (clientArea.y + trim.height); |
402 |
clientArea.x = dpi.x + trim.x; |
403 |
|
403 |
clientArea.y = dpi.y + trim.y; |
404 |
gc = new GC(printer); |
404 |
clientArea.width -= (clientArea.x + trim.width); |
405 |
gc.setFont(printerFont); |
405 |
clientArea.height -= (clientArea.y + trim.height); |
406 |
renderer = new PrintRenderer( |
406 |
|
407 |
printer, printerFont, isBidi(), gc, printerContent, |
407 |
gc = new GC(printer); |
408 |
lineBackgrounds, lineStyles, bidiSegments, |
408 |
gc.setFont(printerFont); |
409 |
tabLength, clientArea); |
409 |
renderer = new PrintRenderer( |
410 |
if (printOptions.header != null) { |
410 |
printer, printerFont, isBidi(), gc, printerContent, |
411 |
int lineHeight = renderer.getLineHeight(); |
411 |
lineBackgrounds, lineStyles, bidiSegments, |
412 |
clientArea.y += lineHeight * 2; |
412 |
tabLength, clientArea); |
413 |
clientArea.height -= lineHeight * 2; |
413 |
if (printOptions.header != null) { |
414 |
} |
414 |
int lineHeight = renderer.getLineHeight(); |
415 |
if (printOptions.footer != null) { |
415 |
clientArea.y += lineHeight * 2; |
416 |
clientArea.height -= renderer.getLineHeight() * 2; |
416 |
clientArea.height -= lineHeight * 2; |
417 |
} |
417 |
} |
418 |
pageSize = clientArea.height / renderer.getLineHeight(); |
418 |
if (printOptions.footer != null) { |
419 |
StyledTextContent content = renderer.getContent(); |
419 |
clientArea.height -= renderer.getLineHeight() * 2; |
420 |
startLine = 0; |
420 |
} |
421 |
endLine = content.getLineCount() - 1; |
421 |
pageSize = clientArea.height / renderer.getLineHeight(); |
422 |
PrinterData data = printer.getPrinterData(); |
422 |
StyledTextContent content = renderer.getContent(); |
423 |
if (data.scope == PrinterData.PAGE_RANGE) { |
423 |
startLine = 0; |
424 |
startLine = (startPage - 1) * pageSize; |
424 |
endLine = content.getLineCount() - 1; |
425 |
} else if (data.scope == PrinterData.SELECTION) { |
425 |
PrinterData data = printer.getPrinterData(); |
426 |
startLine = content.getLineAtOffset(selection.x); |
426 |
if (data.scope == PrinterData.PAGE_RANGE) { |
427 |
if (selection.y > 0) { |
427 |
startLine = (startPage - 1) * pageSize; |
428 |
endLine = content.getLineAtOffset(selection.x + selection.y - 1); |
428 |
} else if (data.scope == PrinterData.SELECTION) { |
429 |
} else { |
429 |
startLine = content.getLineAtOffset(selection.x); |
430 |
endLine = startLine - 1; |
430 |
if (selection.y > 0) { |
431 |
} |
431 |
endLine = content.getLineAtOffset(selection.x + selection.y - 1); |
432 |
} |
432 |
} else { |
433 |
} |
433 |
endLine = startLine - 1; |
434 |
/** |
434 |
} |
435 |
* Returns the printer color for the given display color. |
435 |
} |
436 |
* </p> |
436 |
} |
437 |
* @param color display color |
437 |
/** |
438 |
* @return color create on the printer with the same RGB values |
438 |
* Returns the printer color for the given display color. |
439 |
* as the display color. |
439 |
* </p> |
440 |
*/ |
440 |
* @param color display color |
441 |
Color getPrinterColor(Color color) { |
441 |
* @return color create on the printer with the same RGB values |
442 |
Color printerColor = null; |
442 |
* as the display color. |
443 |
|
443 |
*/ |
444 |
if (color != null) { |
444 |
Color getPrinterColor(Color color) { |
445 |
printerColor = (Color) printerColors.get(color); |
445 |
Color printerColor = null; |
446 |
if (printerColor == null) { |
446 |
|
447 |
printerColor = new Color(printer, color.getRGB()); |
447 |
if (color != null) { |
448 |
printerColors.put(color, printerColor); |
448 |
printerColor = (Color) printerColors.get(color); |
449 |
} |
449 |
if (printerColor == null) { |
450 |
} |
450 |
printerColor = new Color(printer, color.getRGB()); |
451 |
return printerColor; |
451 |
printerColors.put(color, printerColor); |
452 |
} |
452 |
} |
453 |
/** |
453 |
} |
454 |
* Prints the lines in the specified page range. |
454 |
return printerColor; |
455 |
*/ |
455 |
} |
456 |
void print() { |
456 |
/** |
457 |
StyledTextContent content = renderer.getContent(); |
457 |
* Prints the lines in the specified page range. |
458 |
Color background = gc.getBackground(); |
458 |
*/ |
459 |
Color foreground = gc.getForeground(); |
459 |
void print() { |
460 |
int lineHeight = renderer.getLineHeight(); |
460 |
StyledTextContent content = renderer.getContent(); |
461 |
int lineCount = content.getLineCount(); |
461 |
Color background = gc.getBackground(); |
462 |
int paintY = clientArea.y; |
462 |
Color foreground = gc.getForeground(); |
463 |
int page = startPage; |
463 |
int lineHeight = renderer.getLineHeight(); |
464 |
|
464 |
int lineCount = content.getLineCount(); |
465 |
if (singleLine) { |
465 |
int paintY = clientArea.y; |
466 |
lineCount = 1; |
466 |
int page = startPage; |
467 |
} |
467 |
|
468 |
for (int i = startLine; i <= endLine && page <= endPage; i++, paintY += lineHeight) { |
468 |
if (singleLine) { |
469 |
String line = content.getLine(i); |
469 |
lineCount = 1; |
470 |
|
470 |
} |
471 |
if (paintY == clientArea.y) { |
471 |
for (int i = startLine; i <= endLine && page <= endPage; i++, paintY += lineHeight) { |
472 |
startPage(page); |
472 |
String line = content.getLine(i); |
473 |
} |
473 |
|
474 |
renderer.drawLine( |
474 |
if (paintY == clientArea.y) { |
475 |
line, i, paintY, gc, background, foreground, true); |
475 |
startPage(page); |
476 |
if (paintY + lineHeight * 2 > clientArea.y + clientArea.height) { |
476 |
} |
477 |
endPage(page); |
477 |
renderer.drawLine( |
478 |
paintY = clientArea.y; |
478 |
line, i, paintY, gc, background, foreground, true); |
479 |
page++; |
479 |
if (paintY + lineHeight * 2 > clientArea.y + clientArea.height) { |
480 |
if (page > endPage || i == lineCount - 1) { |
480 |
endPage(page); |
481 |
break; |
481 |
paintY = clientArea.y; |
482 |
} |
482 |
page++; |
483 |
} |
483 |
if (page > endPage || i == lineCount - 1) { |
484 |
} |
484 |
break; |
485 |
if (paintY > clientArea.y && paintY <= clientArea.y + clientArea.height) { |
485 |
} |
486 |
endPage(page); |
486 |
} |
487 |
} |
487 |
} |
488 |
} |
488 |
if (paintY > clientArea.y && paintY <= clientArea.y + clientArea.height) { |
489 |
/** |
489 |
endPage(page); |
490 |
* Print header or footer decorations. |
490 |
} |
491 |
*
* @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
* @param header true = print the header, false = print the footer
*/ |
491 |
} |
492 |
void printDecoration(int page, boolean header) { |
492 |
/** |
493 |
int lastSegmentIndex = 0; |
493 |
* Print header or footer decorations. |
494 |
final int SegmentCount = 3; |
494 |
* |
495 |
String text; |
495 |
* @param page page number to print, if specified in the StyledTextPrintOptions header or footer. |
496 |
|
496 |
* @param header true = print the header, false = print the footer |
497 |
if (header) { |
497 |
*/ |
498 |
text = printOptions.header; |
498 |
void printDecoration(int page, boolean header) { |
499 |
} |
499 |
int lastSegmentIndex = 0; |
500 |
else { |
500 |
final int SegmentCount = 3; |
501 |
text = printOptions.footer; |
501 |
String text; |
502 |
} |
502 |
|
503 |
if (text == null) { |
503 |
if (header) { |
504 |
return; |
504 |
text = printOptions.header; |
505 |
} |
505 |
} |
506 |
for (int i = 0; i < SegmentCount; i++) { |
506 |
else { |
507 |
int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); |
507 |
text = printOptions.footer; |
508 |
String segment; |
508 |
} |
509 |
|
509 |
if (text == null) { |
510 |
if (segmentIndex == -1) { |
510 |
return; |
511 |
segment = text.substring(lastSegmentIndex); |
511 |
} |
512 |
printDecorationSegment(segment, i, page, header); |
512 |
for (int i = 0; i < SegmentCount; i++) { |
513 |
break; |
513 |
int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); |
514 |
} |
514 |
String segment; |
515 |
else { |
515 |
|
516 |
segment = text.substring(lastSegmentIndex, segmentIndex); |
516 |
if (segmentIndex == -1) { |
517 |
printDecorationSegment(segment, i, page, header); |
517 |
segment = text.substring(lastSegmentIndex); |
518 |
lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); |
518 |
printDecorationSegment(segment, i, page, header); |
519 |
} |
519 |
break; |
520 |
} |
520 |
} |
521 |
} |
521 |
else { |
522 |
/** |
522 |
segment = text.substring(lastSegmentIndex, segmentIndex); |
523 |
* Print one segment of a header or footer decoration. |
523 |
printDecorationSegment(segment, i, page, header); |
524 |
* Headers and footers have three different segments. |
524 |
lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); |
525 |
* One each for left aligned, centered, and right aligned text. |
525 |
} |
526 |
* |
526 |
} |
527 |
* @param segment decoration segment to print |
527 |
} |
528 |
* @param alignment alignment of the segment. 0=left, 1=center, 2=right |
528 |
/** |
529 |
* @param page page number to print, if specified in the decoration segment. |
529 |
* Print one segment of a header or footer decoration. |
530 |
* @param header true = print the header, false = print the footer |
530 |
* Headers and footers have three different segments. |
531 |
*/ |
531 |
* One each for left aligned, centered, and right aligned text. |
532 |
void printDecorationSegment(String segment, int alignment, int page, boolean header) { |
532 |
* |
533 |
int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); |
533 |
* @param segment decoration segment to print |
534 |
|
534 |
* @param alignment alignment of the segment. 0=left, 1=center, 2=right |
535 |
if (pageIndex != -1) { |
535 |
* @param page page number to print, if specified in the decoration segment. |
536 |
final int PageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); |
536 |
* @param header true = print the header, false = print the footer |
537 |
StringBuffer buffer = new StringBuffer(segment); |
537 |
*/ |
538 |
buffer.replace(pageIndex, pageIndex + PageTagLength, new Integer(page).toString()); |
538 |
void printDecorationSegment(String segment, int alignment, int page, boolean header) { |
539 |
segment = buffer.toString(); |
539 |
int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); |
540 |
} |
540 |
|
541 |
if (segment.length() > 0) { |
541 |
if (pageIndex != -1) { |
542 |
int segmentWidth; |
542 |
final int PageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); |
543 |
int drawX = 0; |
543 |
StringBuffer buffer = new StringBuffer(segment); |
544 |
int drawY; |
544 |
buffer.replace(pageIndex, pageIndex + PageTagLength, new Integer(page).toString()); |
545 |
StyledTextBidi bidi = null; |
545 |
segment = buffer.toString(); |
546 |
|
546 |
} |
547 |
if (isBidi()) { |
547 |
if (segment.length() > 0) { |
548 |
bidi = new StyledTextBidi(gc, tabLength, segment, null, null, new int[] {0, segment.length()}); |
548 |
int segmentWidth; |
549 |
segmentWidth = bidi.getTextWidth(); |
549 |
int drawX = 0; |
550 |
} |
550 |
int drawY; |
551 |
else { |
551 |
StyledTextBidi bidi = null; |
552 |
segmentWidth = gc.textExtent(segment).x; |
552 |
|
553 |
} |
553 |
if (isBidi()) { |
554 |
if (header) { |
554 |
bidi = new StyledTextBidi(gc, tabLength, segment, null, null, new int[] {0, segment.length()}); |
555 |
drawY = clientArea.y - renderer.getLineHeight() * 2; |
555 |
segmentWidth = bidi.getTextWidth(); |
556 |
} |
556 |
} |
557 |
else { |
557 |
else { |
558 |
drawY = clientArea.y + clientArea.height + renderer.getLineHeight(); |
558 |
segmentWidth = gc.textExtent(segment).x; |
559 |
} |
559 |
} |
560 |
if (alignment == LEFT) { |
560 |
if (header) { |
561 |
drawX = clientArea.x; |
561 |
drawY = clientArea.y - renderer.getLineHeight() * 2; |
562 |
} |
562 |
} |
563 |
else |
563 |
else { |
564 |
if (alignment == CENTER) { |
564 |
drawY = clientArea.y + clientArea.height + renderer.getLineHeight(); |
565 |
drawX = (pageWidth - segmentWidth) / 2; |
565 |
} |
566 |
} |
566 |
if (alignment == LEFT) { |
567 |
else |
567 |
drawX = clientArea.x; |
568 |
if (alignment == RIGHT) { |
568 |
} |
569 |
drawX = clientArea.x + clientArea.width - segmentWidth; |
569 |
else |
570 |
} |
570 |
if (alignment == CENTER) { |
571 |
if (bidi != null) { |
571 |
drawX = (pageWidth - segmentWidth) / 2; |
572 |
bidi.drawBidiText(0, segment.length(), drawX, drawY); |
572 |
} |
573 |
} |
573 |
else |
574 |
else { |
574 |
if (alignment == RIGHT) { |
575 |
gc.drawString(segment, drawX, drawY, true); |
575 |
drawX = clientArea.x + clientArea.width - segmentWidth; |
576 |
} |
576 |
} |
577 |
} |
577 |
if (bidi != null) { |
578 |
} |
578 |
bidi.drawBidiText(0, segment.length(), drawX, drawY); |
579 |
/** |
579 |
} |
580 |
* Starts a print job and prints the pages specified in the constructor. |
580 |
else { |
581 |
*/ |
581 |
gc.drawString(segment, drawX, drawY, true); |
582 |
public void run() { |
582 |
} |
583 |
String jobName = printOptions.jobName; |
583 |
} |
584 |
|
584 |
} |
585 |
if (jobName == null) { |
585 |
/** |
586 |
jobName = "Printing"; |
586 |
* Starts a print job and prints the pages specified in the constructor. |
587 |
} |
587 |
*/ |
588 |
if (printer.startJob(jobName)) { |
588 |
public void run() { |
589 |
createPrinterColors(); |
589 |
String jobName = printOptions.jobName; |
590 |
initializeRenderer(); |
590 |
|
591 |
print(); |
591 |
if (jobName == null) { |
592 |
dispose(); |
592 |
jobName = "Printing"; |
593 |
printer.endJob(); |
593 |
} |
594 |
} |
594 |
if (printer.startJob(jobName)) { |
595 |
} |
595 |
createPrinterColors(); |
596 |
/** |
596 |
initializeRenderer(); |
597 |
* Start printing a new page. |
597 |
print(); |
598 |
* |
598 |
dispose(); |
599 |
* @param page page number to be started |
599 |
printer.endJob(); |
600 |
*/ |
600 |
} |
601 |
void startPage(int page) { |
601 |
} |
602 |
printer.startPage(); |
602 |
/** |
603 |
printDecoration(page, true); |
603 |
* Start printing a new page. |
604 |
} |
604 |
* |
605 |
} |
605 |
* @param page page number to be started |
606 |
/** |
606 |
*/ |
607 |
* The <code>RTFWriter</code> class is used to write widget content as |
607 |
void startPage(int page) { |
608 |
* rich text. The implementation complies with the RTF specification |
608 |
printer.startPage(); |
609 |
* version 1.5. |
609 |
printDecoration(page, true); |
610 |
* <p> |
610 |
} |
611 |
* toString() is guaranteed to return a valid RTF string only after |
611 |
} |
612 |
* close() has been called. |
612 |
/** |
613 |
* </p> |
613 |
* The <code>RTFWriter</code> class is used to write widget content as |
614 |
* <p> |
614 |
* rich text. The implementation complies with the RTF specification |
615 |
* Whole and partial lines and line breaks can be written. Lines will be |
615 |
* version 1.5. |
616 |
* formatted using the styles queried from the LineStyleListener, if |
616 |
* <p> |
617 |
* set, or those set directly in the widget. All styles are applied to |
617 |
* toString() is guaranteed to return a valid RTF string only after |
618 |
* the RTF stream like they are rendered by the widget. In addition, the |
618 |
* close() has been called. |
619 |
* widget font name and size is used for the whole text. |
619 |
* </p> |
620 |
* </p> |
620 |
* <p> |
621 |
*/ |
621 |
* Whole and partial lines and line breaks can be written. Lines will be |
622 |
class RTFWriter extends TextWriter { |
622 |
* formatted using the styles queried from the LineStyleListener, if |
623 |
final int DEFAULT_FOREGROUND = 0; |
623 |
* set, or those set directly in the widget. All styles are applied to |
624 |
final int DEFAULT_BACKGROUND = 1; |
624 |
* the RTF stream like they are rendered by the widget. In addition, the |
625 |
Vector colorTable = new Vector(); |
625 |
* widget font name and size is used for the whole text. |
626 |
boolean WriteUnicode; |
626 |
* </p> |
627 |
|
627 |
*/ |
628 |
/** |
628 |
class RTFWriter extends TextWriter { |
629 |
* Creates a RTF writer that writes content starting at offset "start" |
629 |
final int DEFAULT_FOREGROUND = 0; |
630 |
* in the document. <code>start</code> and <code>length</code>can be set to specify partial |
630 |
final int DEFAULT_BACKGROUND = 1; |
631 |
* lines. |
631 |
Vector colorTable = new Vector(); |
632 |
* <p> |
632 |
boolean WriteUnicode; |
633 |
* |
633 |
|
634 |
* @param start start offset of content to write, 0 based from |
634 |
/** |
635 |
* beginning of document |
635 |
* Creates a RTF writer that writes content starting at offset "start" |
636 |
* @param length length of content to write |
636 |
* in the document. <code>start</code> and <code>length</code>can be set to specify partial |
637 |
*/ |
637 |
* lines. |
638 |
public RTFWriter(int start, int length) { |
638 |
* <p> |
639 |
super(start, length); |
639 |
* |
640 |
colorTable.addElement(getForeground()); |
640 |
* @param start start offset of content to write, 0 based from |
641 |
colorTable.addElement(getBackground()); |
641 |
* beginning of document |
642 |
setUnicode(); |
642 |
* @param length length of content to write |
643 |
} |
643 |
*/ |
644 |
/** |
644 |
public RTFWriter(int start, int length) { |
645 |
* Closes the RTF writer. Once closed no more content can be written. |
645 |
super(start, length); |
646 |
* <b>NOTE:</b> <code>toString()</code> does not return a valid RTF string until |
646 |
colorTable.addElement(getForeground()); |
647 |
* <code>close()</code> has been called. |
647 |
colorTable.addElement(getBackground()); |
648 |
*/ |
648 |
setUnicode(); |
649 |
public void close() { |
649 |
} |
650 |
if (isClosed() == false) { |
650 |
/** |
651 |
writeHeader(); |
651 |
* Closes the RTF writer. Once closed no more content can be written. |
652 |
write("\n}}\0"); |
652 |
* <b>NOTE:</b> <code>toString()</code> does not return a valid RTF string until |
653 |
super.close(); |
653 |
* <code>close()</code> has been called. |
654 |
} |
654 |
*/ |
655 |
} |
655 |
public void close() { |
656 |
/** |
656 |
if (isClosed() == false) { |
657 |
* Returns the index of the specified color in the RTF color table. |
657 |
writeHeader(); |
658 |
* <p> |
658 |
write("\n}}\0"); |
659 |
* |
659 |
super.close(); |
660 |
* @param color the color |
660 |
} |
661 |
* @param defaultIndex return value if color is null |
661 |
} |
662 |
* @return the index of the specified color in the RTF color table |
662 |
/** |
663 |
* or "defaultIndex" if "color" is null. |
663 |
* Returns the index of the specified color in the RTF color table. |
664 |
*/ |
664 |
* <p> |
665 |
int getColorIndex(Color color, int defaultIndex) { |
665 |
* |
666 |
int index; |
666 |
* @param color the color |
667 |
|
667 |
* @param defaultIndex return value if color is null |
668 |
if (color == null) { |
668 |
* @return the index of the specified color in the RTF color table |
669 |
index = defaultIndex; |
669 |
* or "defaultIndex" if "color" is null. |
670 |
} |
670 |
*/ |
671 |
else { |
671 |
int getColorIndex(Color color, int defaultIndex) { |
672 |
index = colorTable.indexOf(color); |
672 |
int index; |
673 |
if (index == -1) { |
673 |
|
674 |
index = colorTable.size(); |
674 |
if (color == null) { |
675 |
colorTable.addElement(color); |
675 |
index = defaultIndex; |
676 |
} |
676 |
} |
677 |
} |
677 |
else { |
678 |
return index; |
678 |
index = colorTable.indexOf(color); |
679 |
} |
679 |
if (index == -1) { |
680 |
/** |
680 |
index = colorTable.size(); |
681 |
* Determines if Unicode RTF should be written. |
681 |
colorTable.addElement(color); |
682 |
* Don't write Unicode RTF on Windows 95/98/ME or NT. |
682 |
} |
683 |
*/ |
683 |
} |
684 |
void setUnicode() { |
684 |
return index; |
685 |
final String Win95 = "windows 95"; |
685 |
} |
686 |
final String Win98 = "windows 98"; |
686 |
/** |
687 |
final String WinME = "windows me"; |
687 |
* Determines if Unicode RTF should be written. |
688 |
final String WinNT = "windows nt"; |
688 |
* Don't write Unicode RTF on Windows 95/98/ME or NT. |
689 |
String osName = System.getProperty("os.name").toLowerCase(); |
689 |
*/ |
690 |
String osVersion = System.getProperty("os.version"); |
690 |
void setUnicode() { |
691 |
int majorVersion = 0; |
691 |
final String Win95 = "windows 95"; |
692 |
|
692 |
final String Win98 = "windows 98"; |
693 |
if (osName.startsWith(WinNT) && osVersion != null) { |
693 |
final String WinME = "windows me"; |
694 |
int majorIndex = osVersion.indexOf('.'); |
694 |
final String WinNT = "windows nt"; |
695 |
if (majorIndex != -1) { |
695 |
String osName = System.getProperty("os.name").toLowerCase(); |
696 |
osVersion = osVersion.substring(0, majorIndex); |
696 |
String osVersion = System.getProperty("os.version"); |
697 |
try { |
697 |
int majorVersion = 0; |
698 |
majorVersion = Integer.parseInt(osVersion); |
698 |
|
699 |
} |
699 |
if (osName.startsWith(WinNT) && osVersion != null) { |
700 |
catch (NumberFormatException exception) { |
700 |
int majorIndex = osVersion.indexOf('.'); |
701 |
// ignore exception. version number remains unknown. |
701 |
if (majorIndex != -1) { |
702 |
// will write without Unicode |
702 |
osVersion = osVersion.substring(0, majorIndex); |
703 |
} |
703 |
try { |
704 |
} |
704 |
majorVersion = Integer.parseInt(osVersion); |
705 |
} |
705 |
} |
706 |
if (osName != null && |
706 |
catch (NumberFormatException exception) { |
707 |
osName.startsWith(Win95) == false && |
707 |
// ignore exception. version number remains unknown. |
708 |
osName.startsWith(Win98) == false && |
708 |
// will write without Unicode |
709 |
osName.startsWith(WinME) == false && |
709 |
} |
710 |
(osName.startsWith(WinNT) == false || majorVersion > 4)) { |
710 |
} |
711 |
WriteUnicode = true; |
711 |
} |
712 |
} |
712 |
if (osName != null && |
713 |
else { |
713 |
osName.startsWith(Win95) == false && |
714 |
WriteUnicode = false; |
714 |
osName.startsWith(Win98) == false && |
715 |
} |
715 |
osName.startsWith(WinME) == false && |
716 |
} |
716 |
(osName.startsWith(WinNT) == false || majorVersion > 4)) { |
717 |
/** |
717 |
WriteUnicode = true; |
718 |
* Appends the specified segment of "string" to the RTF data. |
718 |
} |
719 |
* Copy from <code>start</code> up to, but excluding, <code>end</code>. |
719 |
else { |
720 |
* <p> |
720 |
WriteUnicode = false; |
721 |
* |
721 |
} |
722 |
* @param string string to copy a segment from. Must not contain |
722 |
} |
723 |
* line breaks. Line breaks should be written using writeLineDelimiter() |
723 |
/** |
724 |
* @param start start offset of segment. 0 based. |
724 |
* Appends the specified segment of "string" to the RTF data. |
725 |
* @param end end offset of segment |
725 |
* Copy from <code>start</code> up to, but excluding, <code>end</code>. |
726 |
*/ |
726 |
* <p> |
727 |
void write(String string, int start, int end) { |
727 |
* |
728 |
for (int index = start; index < end; index++) { |
728 |
* @param string string to copy a segment from. Must not contain |
729 |
char ch = string.charAt(index); |
729 |
* line breaks. Line breaks should be written using writeLineDelimiter() |
730 |
if (ch > 0xFF && WriteUnicode) { |
730 |
* @param start start offset of segment. 0 based. |
731 |
// write the sub string from the last escaped character |
731 |
* @param end end offset of segment |
732 |
// to the current one. Fixes bug 21698. |
732 |
*/ |
733 |
if (index > start) { |
733 |
void write(String string, int start, int end) { |
734 |
write(string.substring(start, index)); |
734 |
for (int index = start; index < end; index++) { |
735 |
} |
735 |
char ch = string.charAt(index); |
736 |
write("\\u"); |
736 |
if (ch > 0xFF && WriteUnicode) { |
737 |
write(Integer.toString((short) ch)); |
737 |
// write the sub string from the last escaped character |
738 |
write(' '); // control word delimiter |
738 |
// to the current one. Fixes bug 21698. |
739 |
start = index + 1; |
739 |
if (index > start) { |
740 |
} |
740 |
write(string.substring(start, index)); |
741 |
else |
741 |
} |
742 |
if (ch == '}' || ch == '{' || ch == '\\') { |
742 |
write("\\u"); |
743 |
// write the sub string from the last escaped character |
743 |
write(Integer.toString((short) ch)); |
744 |
// to the current one. Fixes bug 21698. |
744 |
write(' '); // control word delimiter |
745 |
if (index > start) { |
745 |
start = index + 1; |
746 |
write(string.substring(start, index)); |
746 |
} |
747 |
} |
747 |
else |
748 |
write('\\'); |
748 |
if (ch == '}' || ch == '{' || ch == '\\') { |
749 |
write(ch); |
749 |
// write the sub string from the last escaped character |
750 |
start = index + 1; |
750 |
// to the current one. Fixes bug 21698. |
751 |
} |
751 |
if (index > start) { |
752 |
} |
752 |
write(string.substring(start, index)); |
753 |
// write from the last escaped character to the end. |
753 |
} |
754 |
// Fixes bug 21698. |
754 |
write('\\'); |
755 |
if (start < end) { |
755 |
write(ch); |
756 |
write(string.substring(start, end)); |
756 |
start = index + 1; |
757 |
} |
757 |
} |
758 |
} |
758 |
} |
759 |
/** |
759 |
// write from the last escaped character to the end. |
760 |
* Writes the RTF header including font table and color table. |
760 |
// Fixes bug 21698. |
761 |
*/ |
761 |
if (start < end) { |
762 |
void writeHeader() { |
762 |
write(string.substring(start, end)); |
763 |
StringBuffer header = new StringBuffer(); |
763 |
} |
764 |
FontData fontData = getFont().getFontData()[0]; |
764 |
} |
765 |
header.append("{\\rtf1\\ansi"); |
765 |
/** |
766 |
// specify code page, necessary for copy to work in bidi |
766 |
* Writes the RTF header including font table and color table. |
767 |
// systems that don't support Unicode RTF. |
767 |
*/ |
768 |
String cpg = System.getProperty("file.encoding").toLowerCase(); |
768 |
void writeHeader() { |
769 |
if (cpg.startsWith("cp") || cpg.startsWith("ms")) { |
769 |
StringBuffer header = new StringBuffer(); |
770 |
cpg = cpg.substring(2, cpg.length()); |
770 |
FontData fontData = getFont().getFontData()[0]; |
771 |
header.append("\\ansicpg"); |
771 |
header.append("{\\rtf1\\ansi"); |
772 |
header.append(cpg); |
772 |
// specify code page, necessary for copy to work in bidi |
773 |
} |
773 |
// systems that don't support Unicode RTF. |
774 |
header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); |
774 |
String cpg = System.getProperty("file.encoding").toLowerCase(); |
775 |
header.append(fontData.getName()); |
775 |
if (cpg.startsWith("cp") || cpg.startsWith("ms")) { |
776 |
header.append(";}}\n{\\colortbl"); |
776 |
cpg = cpg.substring(2, cpg.length()); |
777 |
for (int i = 0; i < colorTable.size(); i++) { |
777 |
header.append("\\ansicpg"); |
778 |
Color color = (Color) colorTable.elementAt(i); |
778 |
header.append(cpg); |
779 |
header.append("\\red"); |
779 |
} |
780 |
header.append(color.getRed()); |
780 |
header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); |
781 |
header.append("\\green"); |
781 |
header.append(fontData.getName()); |
782 |
header.append(color.getGreen()); |
782 |
header.append(";}}\n{\\colortbl"); |
783 |
header.append("\\blue"); |
783 |
for (int i = 0; i < colorTable.size(); i++) { |
784 |
header.append(color.getBlue()); |
784 |
Color color = (Color) colorTable.elementAt(i); |
785 |
header.append(";"); |
785 |
header.append("\\red"); |
786 |
} |
786 |
header.append(color.getRed()); |
787 |
// some RTF readers ignore the deff0 font tag. Explicitly |
787 |
header.append("\\green"); |
788 |
// set the font for the whole document to work around this. |
788 |
header.append(color.getGreen()); |
789 |
header.append("}\n{\\f0\\fs"); |
789 |
header.append("\\blue"); |
790 |
// font size is specified in half points |
790 |
header.append(color.getBlue()); |
791 |
header.append(fontData.getHeight() * 2); |
791 |
header.append(";"); |
792 |
header.append(" "); |
792 |
} |
793 |
write(header.toString(), 0); |
793 |
// some RTF readers ignore the deff0 font tag. Explicitly |
794 |
} |
794 |
// set the font for the whole document to work around this. |
795 |
/** |
795 |
header.append("}\n{\\f0\\fs"); |
796 |
* Appends the specified line text to the RTF data. Lines will be formatted |
796 |
// font size is specified in half points |
797 |
* using the styles queried from the LineStyleListener, if set, or those set |
797 |
header.append(fontData.getHeight() * 2); |
798 |
* directly in the widget. |
798 |
header.append(" "); |
799 |
* <p> |
799 |
write(header.toString(), 0); |
800 |
* |
800 |
} |
801 |
* @param line line text to write as RTF. Must not contain line breaks |
801 |
/** |
802 |
* Line breaks should be written using writeLineDelimiter() |
802 |
* Appends the specified line text to the RTF data. Lines will be formatted |
803 |
* @param lineOffset offset of the line. 0 based from the start of the |
803 |
* using the styles queried from the LineStyleListener, if set, or those set |
804 |
* widget document. Any text occurring before the start offset or after the |
804 |
* directly in the widget. |
805 |
* end offset specified during object creation is ignored. |
805 |
* <p> |
806 |
* @exception SWTException <ul> |
806 |
* |
807 |
* <li>ERROR_IO when the writer is closed.</li> |
807 |
* @param line line text to write as RTF. Must not contain line breaks |
808 |
* </ul> |
808 |
* Line breaks should be written using writeLineDelimiter() |
809 |
*/ |
809 |
* @param lineOffset offset of the line. 0 based from the start of the |
810 |
public void writeLine(String line, int lineOffset) { |
810 |
* widget document. Any text occurring before the start offset or after the |
811 |
StyleRange[] styles = new StyleRange[0]; |
811 |
* end offset specified during object creation is ignored. |
812 |
Color lineBackground = null; |
812 |
* @exception SWTException <ul> |
813 |
StyledTextEvent event; |
813 |
* <li>ERROR_IO when the writer is closed.</li> |
814 |
|
814 |
* </ul> |
815 |
if (isClosed()) { |
815 |
*/ |
816 |
SWT.error(SWT.ERROR_IO); |
816 |
public void writeLine(String line, int lineOffset) { |
817 |
} |
817 |
StyleRange[] styles = new StyleRange[0]; |
818 |
event = renderer.getLineStyleData(lineOffset, line); |
818 |
Color lineBackground = null; |
819 |
if (event != null) { |
819 |
StyledTextEvent event; |
820 |
styles = event.styles; |
820 |
|
821 |
} |
821 |
if (isClosed()) { |
822 |
event = renderer.getLineBackgroundData(lineOffset, line); |
822 |
SWT.error(SWT.ERROR_IO); |
823 |
if (event != null) { |
823 |
} |
824 |
lineBackground = event.lineBackground; |
824 |
event = renderer.getLineStyleData(lineOffset, line); |
825 |
} |
825 |
if (event != null) { |
826 |
if (lineBackground == null) { |
826 |
styles = event.styles; |
827 |
lineBackground = getBackground(); |
827 |
} |
828 |
} |
828 |
event = renderer.getLineBackgroundData(lineOffset, line); |
829 |
writeStyledLine(line, lineOffset, styles, lineBackground); |
829 |
if (event != null) { |
830 |
} |
830 |
lineBackground = event.lineBackground; |
831 |
/** |
831 |
} |
832 |
* Appends the specified line delmimiter to the RTF data. |
832 |
if (lineBackground == null) { |
833 |
* <p> |
833 |
lineBackground = getBackground(); |
834 |
* |
834 |
} |
835 |
* @param lineDelimiter line delimiter to write as RTF. |
835 |
writeStyledLine(line, lineOffset, styles, lineBackground); |
836 |
* @exception SWTException <ul> |
836 |
} |
837 |
* <li>ERROR_IO when the writer is closed.</li> |
837 |
/** |
838 |
* </ul> |
838 |
* Appends the specified line delmimiter to the RTF data. |
839 |
*/ |
839 |
* <p> |
840 |
public void writeLineDelimiter(String lineDelimiter) { |
840 |
* |
841 |
if (isClosed()) { |
841 |
* @param lineDelimiter line delimiter to write as RTF. |
842 |
SWT.error(SWT.ERROR_IO); |
842 |
* @exception SWTException <ul> |
843 |
} |
843 |
* <li>ERROR_IO when the writer is closed.</li> |
844 |
write(lineDelimiter, 0, lineDelimiter.length()); |
844 |
* </ul> |
845 |
write("\\par "); |
845 |
*/ |
846 |
} |
846 |
public void writeLineDelimiter(String lineDelimiter) { |
847 |
/** |
847 |
if (isClosed()) { |
848 |
* Appends the specified line text to the RTF data. |
848 |
SWT.error(SWT.ERROR_IO); |
849 |
* Use the colors and font styles specified in "styles" and "lineBackground". |
849 |
} |
850 |
* Formatting is written to reflect the text rendering by the text widget. |
850 |
write(lineDelimiter, 0, lineDelimiter.length()); |
851 |
* Style background colors take precedence over the line background color. |
851 |
write("\\par "); |
852 |
* Background colors are written using the \highlight tag (vs. the \cb tag). |
852 |
} |
853 |
* <p> |
853 |
/** |
854 |
* |
854 |
* Appends the specified line text to the RTF data. |
855 |
* @param line line text to write as RTF. Must not contain line breaks |
855 |
* Use the colors and font styles specified in "styles" and "lineBackground". |
856 |
* Line breaks should be written using writeLineDelimiter() |
856 |
* Formatting is written to reflect the text rendering by the text widget. |
857 |
* @param lineOffset offset of the line. 0 based from the start of the |
857 |
* Style background colors take precedence over the line background color. |
858 |
* widget document. Any text occurring before the start offset or after the |
858 |
* Background colors are written using the \highlight tag (vs. the \cb tag). |
859 |
* end offset specified during object creation is ignored. |
859 |
* <p> |
860 |
* @param styles styles to use for formatting. Must not be null. |
860 |
* |
861 |
* @param linebackground line background color to use for formatting. |
861 |
* @param line line text to write as RTF. Must not contain line breaks |
862 |
* May be null. |
862 |
* Line breaks should be written using writeLineDelimiter() |
863 |
*/ |
863 |
* @param lineOffset offset of the line. 0 based from the start of the |
864 |
void writeStyledLine(String line, int lineOffset, StyleRange[] styles, Color lineBackground) { |
864 |
* widget document. Any text occurring before the start offset or after the |
865 |
int lineLength = line.length(); |
865 |
* end offset specified during object creation is ignored. |
866 |
int lineIndex; |
866 |
* @param styles styles to use for formatting. Must not be null. |
867 |
int copyEnd; |
867 |
* @param linebackground line background color to use for formatting. |
868 |
int startOffset = getStart(); |
868 |
* May be null. |
869 |
int endOffset = startOffset + super.getCharCount(); |
869 |
*/ |
870 |
int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); |
870 |
void writeStyledLine(String line, int lineOffset, StyleRange[] styles, Color lineBackground) { |
871 |
int writeOffset = startOffset - lineOffset; |
871 |
int lineLength = line.length(); |
872 |
|
872 |
int lineIndex; |
873 |
if (writeOffset >= line.length()) { |
873 |
int copyEnd; |
874 |
return; // whole line is outside write range |
874 |
int startOffset = getStart(); |
875 |
} |
875 |
int endOffset = startOffset + super.getCharCount(); |
876 |
else |
876 |
int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); |
877 |
if (writeOffset > 0) { |
877 |
int writeOffset = startOffset - lineOffset; |
878 |
lineIndex = writeOffset; // line starts before RTF write start |
878 |
|
879 |
} |
879 |
if (writeOffset >= line.length()) { |
880 |
else { |
880 |
return; // whole line is outside write range |
881 |
lineIndex = 0; |
881 |
} |
882 |
} |
882 |
else |
883 |
if (lineBackground != null) { |
883 |
if (writeOffset > 0) { |
884 |
write("{\\highlight"); |
884 |
lineIndex = writeOffset; // line starts before RTF write start |
885 |
write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); |
885 |
} |
886 |
write(" "); |
886 |
else { |
887 |
} |
887 |
lineIndex = 0; |
888 |
for (int i = 0; i < styles.length; i++) { |
888 |
} |
889 |
StyleRange style = styles[i]; |
889 |
if (lineBackground != null) { |
890 |
int start = style.start - lineOffset; |
890 |
write("{\\highlight"); |
891 |
int end = start + style.length; |
891 |
write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); |
892 |
int colorIndex; |
892 |
write(" "); |
893 |
// skip over partial first line |
893 |
} |
894 |
if (end < writeOffset) { |
894 |
for (int i = 0; i < styles.length; i++) { |
895 |
continue; |
895 |
StyleRange style = styles[i]; |
896 |
} |
896 |
int start = style.start - lineOffset; |
897 |
// style starts beyond line end or RTF write end |
897 |
int end = start + style.length; |
898 |
if (start >= lineEndOffset) { |
898 |
int colorIndex; |
899 |
break; |
899 |
// skip over partial first line |
900 |
} |
900 |
if (end < writeOffset) { |
901 |
// write any unstyled text |
901 |
continue; |
902 |
if (lineIndex < start) { |
902 |
} |
903 |
// copy to start of style |
903 |
// style starts beyond line end or RTF write end |
904 |
// style starting betond end of write range or end of line |
904 |
if (start >= lineEndOffset) { |
905 |
// is guarded against above. |
905 |
break; |
906 |
write(line, lineIndex, start); |
906 |
} |
907 |
lineIndex = start; |
907 |
// write any unstyled text |
908 |
} |
908 |
if (lineIndex < start) { |
909 |
// write styled text |
909 |
// copy to start of style |
910 |
colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); |
910 |
// style starting betond end of write range or end of line |
911 |
write("{\\cf"); |
911 |
// is guarded against above. |
912 |
write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); |
912 |
write(line, lineIndex, start); |
913 |
if (colorIndex != DEFAULT_BACKGROUND) { |
913 |
lineIndex = start; |
914 |
write("\\highlight"); |
914 |
} |
915 |
write(colorIndex); |
915 |
// write styled text |
916 |
} |
916 |
colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND); |
917 |
if (style.fontStyle == SWT.BOLD) { |
917 |
write("{\\cf"); |
918 |
write("\\b"); |
918 |
write(getColorIndex(style.foreground, DEFAULT_FOREGROUND)); |
919 |
} |
919 |
if (colorIndex != DEFAULT_BACKGROUND) { |
920 |
write(" "); |
920 |
write("\\highlight"); |
921 |
// copy to end of style or end of write range or end of line |
921 |
write(colorIndex); |
922 |
copyEnd = Math.min(end, lineEndOffset); |
922 |
} |
923 |
// guard against invalid styles and let style processing continue |
923 |
if (style.fontStyle == SWT.BOLD) { |
924 |
copyEnd = Math.max(copyEnd, lineIndex); |
924 |
write("\\b"); |
925 |
write(line, lineIndex, copyEnd); |
925 |
} |
926 |
if (style.fontStyle == SWT.BOLD) { |
926 |
write(" "); |
927 |
write("\\b0"); |
927 |
// copy to end of style or end of write range or end of line |
928 |
} |
928 |
copyEnd = Math.min(end, lineEndOffset); |
929 |
write("}"); |
929 |
// guard against invalid styles and let style processing continue |
930 |
lineIndex = copyEnd; |
930 |
copyEnd = Math.max(copyEnd, lineIndex); |
931 |
} |
931 |
write(line, lineIndex, copyEnd); |
932 |
// write unstyled text at the end of the line |
932 |
if (style.fontStyle == SWT.BOLD) { |
933 |
if (lineIndex < lineEndOffset) { |
933 |
write("\\b0"); |
934 |
write(line, lineIndex, lineEndOffset); |
934 |
} |
935 |
} |
935 |
write("}"); |
936 |
if (lineBackground != null) { |
936 |
lineIndex = copyEnd; |
937 |
write("}"); |
937 |
} |
938 |
} |
938 |
// write unstyled text at the end of the line |
939 |
} |
939 |
if (lineIndex < lineEndOffset) { |
940 |
} |
940 |
write(line, lineIndex, lineEndOffset); |
941 |
/** |
941 |
} |
942 |
* The <code>TextWriter</code> class is used to write widget content to |
942 |
if (lineBackground != null) { |
943 |
* a string. Whole and partial lines and line breaks can be written. To write |
943 |
write("}"); |
944 |
* partial lines, specify the start and length of the desired segment |
944 |
} |
945 |
* during object creation. |
945 |
} |
946 |
* <p> |
946 |
} |
947 |
* </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close() |
947 |
/** |
948 |
* has been called. |
948 |
* The <code>TextWriter</code> class is used to write widget content to |
949 |
*/ |
949 |
* a string. Whole and partial lines and line breaks can be written. To write |
950 |
class TextWriter { |
950 |
* partial lines, specify the start and length of the desired segment |
951 |
private StringBuffer buffer; |
951 |
* during object creation. |
952 |
private int startOffset; // offset of first character that will be written |
952 |
* <p> |
953 |
private int endOffset; // offset of last character that will be written. |
953 |
* </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close() |
954 |
// 0 based from the beginning of the widget text. |
954 |
* has been called. |
955 |
private boolean isClosed = false; |
955 |
*/ |
956 |
|
956 |
class TextWriter { |
957 |
/** |
957 |
private StringBuffer buffer; |
958 |
* Creates a writer that writes content starting at offset "start" |
958 |
private int startOffset; // offset of first character that will be written |
959 |
* in the document. <code>start</code> and <code>length</code> can be set to specify partial lines. |
959 |
private int endOffset; // offset of last character that will be written. |
960 |
* <p> |
960 |
// 0 based from the beginning of the widget text. |
961 |
* |
961 |
private boolean isClosed = false; |
962 |
* @param start start offset of content to write, 0 based from beginning of document |
962 |
|
963 |
* @param length length of content to write |
963 |
/** |
964 |
*/ |
964 |
* Creates a writer that writes content starting at offset "start" |
965 |
public TextWriter(int start, int length) { |
965 |
* in the document. <code>start</code> and <code>length</code> can be set to specify partial lines. |
966 |
buffer = new StringBuffer(length); |
966 |
* <p> |
967 |
startOffset = start; |
967 |
* |
968 |
endOffset = start + length; |
968 |
* @param start start offset of content to write, 0 based from beginning of document |
969 |
} |
969 |
* @param length length of content to write |
970 |
/** |
970 |
*/ |
971 |
* Closes the writer. Once closed no more content can be written. |
971 |
public TextWriter(int start, int length) { |
972 |
* <b>NOTE:</b> <code>toString()</code> is not guaranteed to return a valid string unless |
972 |
buffer = new StringBuffer(length); |
973 |
* the writer is closed. |
973 |
startOffset = start; |
974 |
*/ |
974 |
endOffset = start + length; |
975 |
public void close() { |
975 |
} |
976 |
if (isClosed == false) { |
976 |
/** |
977 |
isClosed = true; |
977 |
* Closes the writer. Once closed no more content can be written. |
978 |
} |
978 |
* <b>NOTE:</b> <code>toString()</code> is not guaranteed to return a valid string unless |
979 |
} |
979 |
* the writer is closed. |
980 |
/** |
980 |
*/ |
981 |
* Returns the number of characters to write. |
981 |
public void close() { |
982 |
*/ |
982 |
if (isClosed == false) { |
983 |
public int getCharCount() { |
983 |
isClosed = true; |
984 |
return endOffset - startOffset; |
984 |
} |
985 |
} |
985 |
} |
986 |
/** |
986 |
/** |
987 |
* Returns the offset where writing starts. 0 based from the start of |
987 |
* Returns the number of characters to write. |
988 |
* the widget text. Used to write partial lines. |
988 |
*/ |
989 |
*/ |
989 |
public int getCharCount() { |
990 |
public int getStart() { |
990 |
return endOffset - startOffset; |
991 |
return startOffset; |
991 |
} |
992 |
} |
992 |
/** |
993 |
/** |
993 |
* Returns the offset where writing starts. 0 based from the start of |
994 |
* Returns whether the writer is closed. |
994 |
* the widget text. Used to write partial lines. |
995 |
*/ |
995 |
*/ |
996 |
public boolean isClosed() { |
996 |
public int getStart() { |
997 |
return isClosed; |
997 |
return startOffset; |
998 |
} |
998 |
} |
999 |
/** |
999 |
/** |
1000 |
* Returns the string. <code>close()</code> must be called before <code>toString()</code> |
1000 |
* Returns whether the writer is closed. |
1001 |
* is guaranteed to return a valid string. |
1001 |
*/ |
1002 |
* <p> |
1002 |
public boolean isClosed() { |
1003 |
* |
1003 |
return isClosed; |
1004 |
* @return the string |
1004 |
} |
1005 |
*/ |
1005 |
/** |
1006 |
public String toString() { |
1006 |
* Returns the string. <code>close()</code> must be called before <code>toString()</code> |
1007 |
return buffer.toString(); |
1007 |
* is guaranteed to return a valid string. |
1008 |
} |
1008 |
* <p> |
1009 |
/** |
1009 |
* |
1010 |
* Appends the given string to the data. |
1010 |
* @return the string |
1011 |
*/ |
1011 |
*/ |
1012 |
void write(String string) { |
1012 |
public String toString() { |
1013 |
buffer.append(string); |
1013 |
return buffer.toString(); |
1014 |
} |
1014 |
} |
1015 |
/** |
1015 |
/** |
1016 |
* Inserts the given string to the data at the specified offset. |
1016 |
* Appends the given string to the data. |
1017 |
* Do nothing if "offset" is < 0 or > getCharCount() |
1017 |
*/ |
1018 |
* <p> |
1018 |
void write(String string) { |
1019 |
* |
1019 |
buffer.append(string); |
1020 |
* @param string text to insert |
1020 |
} |
1021 |
* @param offset offset in the existing data to insert "string" at. |
1021 |
/** |
1022 |
*/ |
1022 |
* Inserts the given string to the data at the specified offset. |
1023 |
void write(String string, int offset) { |
1023 |
* Do nothing if "offset" is < 0 or > getCharCount() |
1024 |
if (offset < 0 || offset > buffer.length()) { |
1024 |
* <p> |
1025 |
return; |
1025 |
* |
1026 |
} |
1026 |
* @param string text to insert |
1027 |
buffer.insert(offset, string); |
1027 |
* @param offset offset in the existing data to insert "string" at. |
1028 |
} |
1028 |
*/ |
1029 |
/** |
1029 |
void write(String string, int offset) { |
1030 |
* Appends the given int to the data. |
1030 |
if (offset < 0 || offset > buffer.length()) { |
1031 |
*/ |
1031 |
return; |
1032 |
void write(int i) { |
1032 |
} |
1033 |
buffer.append(i); |
1033 |
buffer.insert(offset, string); |
1034 |
} |
1034 |
} |
1035 |
/** |
1035 |
/** |
1036 |
* Appends the given character to the data. |
1036 |
* Appends the given int to the data. |
1037 |
*/ |
1037 |
*/ |
1038 |
void write(char i) { |
1038 |
void write(int i) { |
1039 |
buffer.append(i); |
1039 |
buffer.append(i); |
1040 |
} |
1040 |
} |
1041 |
/** |
1041 |
/** |
1042 |
* Appends the specified line text to the data. |
1042 |
* Appends the given character to the data. |
1043 |
* <p> |
1043 |
*/ |
1044 |
* |
1044 |
void write(char i) { |
1045 |
* @param line line text to write. Must not contain line breaks |
1045 |
buffer.append(i); |
1046 |
* Line breaks should be written using writeLineDelimiter() |
1046 |
} |
1047 |
* @param lineOffset offset of the line. 0 based from the start of the |
1047 |
/** |
1048 |
* widget document. Any text occurring before the start offset or after the |
1048 |
* Appends the specified line text to the data. |
1049 |
* end offset specified during object creation is ignored. |
1049 |
* <p> |
1050 |
* @exception SWTException <ul> |
1050 |
* |
1051 |
* <li>ERROR_IO when the writer is closed.</li> |
1051 |
* @param line line text to write. Must not contain line breaks |
1052 |
* </ul> |
1052 |
* Line breaks should be written using writeLineDelimiter() |
1053 |
*/ |
1053 |
* @param lineOffset offset of the line. 0 based from the start of the |
1054 |
public void writeLine(String line, int lineOffset) { |
1054 |
* widget document. Any text occurring before the start offset or after the |
1055 |
int lineLength = line.length(); |
1055 |
* end offset specified during object creation is ignored. |
1056 |
int lineIndex; |
1056 |
* @exception SWTException <ul> |
1057 |
int copyEnd; |
1057 |
* <li>ERROR_IO when the writer is closed.</li> |
1058 |
int writeOffset = startOffset - lineOffset; |
1058 |
* </ul> |
1059 |
|
1059 |
*/ |
1060 |
if (isClosed) { |
1060 |
public void writeLine(String line, int lineOffset) { |
1061 |
SWT.error(SWT.ERROR_IO); |
1061 |
int lineLength = line.length(); |
1062 |
} |
1062 |
int lineIndex; |
1063 |
if (writeOffset >= lineLength) { |
1063 |
int copyEnd; |
1064 |
return; // whole line is outside write range |
1064 |
int writeOffset = startOffset - lineOffset; |
1065 |
} |
1065 |
|
1066 |
else |
1066 |
if (isClosed) { |
1067 |
if (writeOffset > 0) { |
1067 |
SWT.error(SWT.ERROR_IO); |
1068 |
lineIndex = writeOffset; // line starts before write start |
1068 |
} |
1069 |
} |
1069 |
if (writeOffset >= lineLength) { |
1070 |
else { |
1070 |
return; // whole line is outside write range |
1071 |
lineIndex = 0; |
1071 |
} |
1072 |
} |
1072 |
else |
1073 |
copyEnd = Math.min(lineLength, endOffset - lineOffset); |
1073 |
if (writeOffset > 0) { |
1074 |
if (lineIndex < copyEnd) { |
1074 |
lineIndex = writeOffset; // line starts before write start |
1075 |
write(line.substring(lineIndex, copyEnd)); |
1075 |
} |
1076 |
} |
1076 |
else { |
1077 |
} |
1077 |
lineIndex = 0; |
1078 |
/** |
1078 |
} |
1079 |
* Appends the specified line delmimiter to the data. |
1079 |
copyEnd = Math.min(lineLength, endOffset - lineOffset); |
1080 |
* <p> |
1080 |
if (lineIndex < copyEnd) { |
1081 |
* |
1081 |
write(line.substring(lineIndex, copyEnd)); |
1082 |
* @param lineDelimiter line delimiter to write |
1082 |
} |
1083 |
* @exception SWTException <ul> |
1083 |
} |
1084 |
* <li>ERROR_IO when the writer is closed.</li> |
1084 |
/** |
1085 |
* </ul> |
1085 |
* Appends the specified line delmimiter to the data. |
1086 |
*/ |
1086 |
* <p> |
1087 |
public void writeLineDelimiter(String lineDelimiter) { |
1087 |
* |
1088 |
if (isClosed) { |
1088 |
* @param lineDelimiter line delimiter to write |
1089 |
SWT.error(SWT.ERROR_IO); |
1089 |
* @exception SWTException <ul> |
1090 |
} |
1090 |
* <li>ERROR_IO when the writer is closed.</li> |
1091 |
write(lineDelimiter); |
1091 |
* </ul> |
1092 |
} |
1092 |
*/ |
1093 |
} |
1093 |
public void writeLineDelimiter(String lineDelimiter) { |
1094 |
/** |
1094 |
if (isClosed) { |
1095 |
* LineCache provides an interface to calculate and invalidate |
1095 |
SWT.error(SWT.ERROR_IO); |
1096 |
* line based data. |
1096 |
} |
1097 |
* Implementors need to return a line width in <code>getWidth</code>. |
1097 |
write(lineDelimiter); |
1098 |
*/ |
1098 |
} |
1099 |
interface LineCache { |
1099 |
} |
1100 |
/** |
1100 |
/** |
1101 |
* Calculates the lines in the specified range. |
1101 |
* LineCache provides an interface to calculate and invalidate |
1102 |
* <p> |
1102 |
* line based data. |
1103 |
* |
1103 |
* Implementors need to return a line width in <code>getWidth</code>. |
1104 |
* @param startLine first line to calculate |
1104 |
*/ |
1105 |
* @param lineCount number of lines to calculate |
1105 |
interface LineCache { |
1106 |
*/ |
1106 |
/** |
1107 |
public void calculate(int startLine, int lineCount); |
1107 |
* Calculates the lines in the specified range. |
1108 |
/** |
1108 |
* <p> |
1109 |
* Returns a width that will be used by the <code>StyledText</code> |
1109 |
* |
1110 |
* widget to size a horizontal scroll bar. |
1110 |
* @param startLine first line to calculate |
1111 |
* <p> |
1111 |
* @param lineCount number of lines to calculate |
1112 |
* |
1112 |
*/ |
1113 |
* @return the line width |
1113 |
public void calculate(int startLine, int lineCount); |
1114 |
*/ |
1114 |
/** |
1115 |
public int getWidth(); |
1115 |
* Returns a width that will be used by the <code>StyledText</code> |
1116 |
/** |
1116 |
* widget to size a horizontal scroll bar. |
1117 |
* Resets the lines in the specified range. |
1117 |
* <p> |
1118 |
* This method is called in <code>StyledText.redraw()</code> |
1118 |
* |
1119 |
* and allows implementors to call redraw themselves during reset. |
1119 |
* @return the line width |
1120 |
* <p> |
1120 |
*/ |
1121 |
* |
1121 |
public int getWidth(); |
1122 |
* @param startLine the first line to reset |
1122 |
/** |
1123 |
* @param lineCount the number of lines to reset |
1123 |
* Resets the lines in the specified range. |
1124 |
* @param calculateMaxWidth true=implementors should retain a |
1124 |
* This method is called in <code>StyledText.redraw()</code> |
1125 |
* valid width even if it is affected by the reset operation. |
1125 |
* and allows implementors to call redraw themselves during reset. |
1126 |
* false=the width may be set to 0 |
1126 |
* <p> |
1127 |
*/ |
1127 |
* |
1128 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth); |
1128 |
* @param startLine the first line to reset |
1129 |
/** |
1129 |
* @param lineCount the number of lines to reset |
1130 |
* Resets the lines in the specified range. |
1130 |
* @param calculateMaxWidth true=implementors should retain a |
1131 |
* <p> |
1131 |
* valid width even if it is affected by the reset operation. |
1132 |
* |
1132 |
* false=the width may be set to 0 |
1133 |
* @param startLine the first line to reset |
1133 |
*/ |
1134 |
* @param lineCount the number of lines to reset |
1134 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth); |
1135 |
* @param calculateMaxWidth true=implementors should retain a |
1135 |
/** |
1136 |
* valid width even if it is affected by the reset operation. |
1136 |
* Resets the lines in the specified range. |
1137 |
* false=the width may be set to 0 |
1137 |
* <p> |
1138 |
*/ |
1138 |
* |
1139 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth); |
1139 |
* @param startLine the first line to reset |
1140 |
/** |
1140 |
* @param lineCount the number of lines to reset |
1141 |
* Called when a text change occurred. |
1141 |
* @param calculateMaxWidth true=implementors should retain a |
1142 |
* <p> |
1142 |
* valid width even if it is affected by the reset operation. |
1143 |
* |
1143 |
* false=the width may be set to 0 |
1144 |
* @param startOffset the start offset of the text change |
1144 |
*/ |
1145 |
* @param newLineCount the number of inserted lines |
1145 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth); |
1146 |
* @param replaceLineCount the number of deleted lines |
1146 |
/** |
1147 |
* @param newCharCount the number of new characters |
1147 |
* Called when a text change occurred. |
1148 |
* @param replaceCharCount the number of deleted characters |
1148 |
* <p> |
1149 |
*/ |
1149 |
* |
1150 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount); |
1150 |
* @param startOffset the start offset of the text change |
1151 |
} |
1151 |
* @param newLineCount the number of inserted lines |
1152 |
/** |
1152 |
* @param replaceLineCount the number of deleted lines |
1153 |
* Keeps track of line widths and the longest line in the |
1153 |
* @param newCharCount the number of new characters |
1154 |
* StyledText document. |
1154 |
* @param replaceCharCount the number of deleted characters |
1155 |
* Line widths are calculated when requested by a call to |
1155 |
*/ |
1156 |
* <code>calculate</code> and cached until reset by a call |
1156 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount); |
1157 |
* to <code>redrawReset</code> or <code>reset</code>. |
1157 |
} |
1158 |
*/ |
1158 |
/** |
1159 |
class ContentWidthCache implements LineCache { |
1159 |
* Keeps track of line widths and the longest line in the |
1160 |
StyledText parent; // parent widget, used to create a GC for line measuring |
1160 |
* StyledText document. |
1161 |
int[] lineWidth; // width in pixel of each line in the document, -1 for unknown width |
1161 |
* Line widths are calculated when requested by a call to |
1162 |
int lineCount; // number of lines in lineWidth array |
1162 |
* <code>calculate</code> and cached until reset by a call |
1163 |
int maxWidth; // maximum line width of all measured lines |
1163 |
* to <code>redrawReset</code> or <code>reset</code>. |
1164 |
int maxWidthLineIndex; // index of the widest line |
1164 |
*/ |
1165 |
|
1165 |
class ContentWidthCache implements LineCache { |
1166 |
/** |
1166 |
StyledText parent; // parent widget, used to create a GC for line measuring |
1167 |
* Creates a new <code>ContentWidthCache</code> and allocates space |
1167 |
int[] lineWidth; // width in pixel of each line in the document, -1 for unknown width |
1168 |
* for the given number of lines. |
1168 |
int lineCount; // number of lines in lineWidth array |
1169 |
* <p> |
1169 |
int maxWidth; // maximum line width of all measured lines |
1170 |
* |
1170 |
int maxWidthLineIndex; // index of the widest line |
1171 |
* @param parent the StyledText widget used to create a GC for |
1171 |
|
1172 |
* line measuring |
1172 |
/** |
1173 |
* @param lineCount initial number of lines to allocate space for |
1173 |
* Creates a new <code>ContentWidthCache</code> and allocates space |
1174 |
*/ |
1174 |
* for the given number of lines. |
1175 |
public ContentWidthCache(StyledText parent, int lineCount) { |
1175 |
* <p> |
1176 |
this.lineCount = lineCount; |
1176 |
* |
1177 |
this.parent = parent; |
1177 |
* @param parent the StyledText widget used to create a GC for |
1178 |
lineWidth = new int[lineCount]; |
1178 |
* line measuring |
1179 |
reset(0, lineCount, false); |
1179 |
* @param lineCount initial number of lines to allocate space for |
1180 |
} |
1180 |
*/ |
1181 |
/** |
1181 |
public ContentWidthCache(StyledText parent, int lineCount) { |
1182 |
* Calculates the width of each line in the given range if it has |
1182 |
this.lineCount = lineCount; |
1183 |
* not been calculated yet. |
1183 |
this.parent = parent; |
1184 |
* If any line in the given range is wider than the currently widest |
1184 |
lineWidth = new int[lineCount]; |
1185 |
* line, the maximum line width is updated, |
1185 |
reset(0, lineCount, false); |
1186 |
* <p> |
1186 |
} |
1187 |
* |
1187 |
/** |
1188 |
* @param startLine first line to calculate the line width of |
1188 |
* Calculates the width of each line in the given range if it has |
1189 |
* @param lineCount number of lines to calculate the line width for |
1189 |
* not been calculated yet. |
1190 |
*/ |
1190 |
* If any line in the given range is wider than the currently widest |
1191 |
public void calculate(int startLine, int lineCount) { |
1191 |
* line, the maximum line width is updated, |
1192 |
GC gc = null; |
1192 |
* <p> |
1193 |
int caretWidth = 0; |
1193 |
* |
1194 |
int stopLine = startLine + lineCount; |
1194 |
* @param startLine first line to calculate the line width of |
1195 |
|
1195 |
* @param lineCount number of lines to calculate the line width for |
1196 |
for (int i = startLine; i < stopLine; i++) { |
1196 |
*/ |
1197 |
if (lineWidth[i] == -1) { |
1197 |
public void calculate(int startLine, int lineCount) { |
1198 |
String line = content.getLine(i); |
1198 |
GC gc = null; |
1199 |
int lineOffset = content.getOffsetAtLine(i); |
1199 |
int caretWidth = 0; |
1200 |
|
1200 |
int stopLine = startLine + lineCount; |
1201 |
if (gc == null) { |
1201 |
|
1202 |
gc = parent.getGC(); |
1202 |
for (int i = startLine; i < stopLine; i++) { |
1203 |
caretWidth = getCaretWidth(); |
1203 |
if (lineWidth[i] == -1) { |
1204 |
} |
1204 |
String line = content.getLine(i); |
1205 |
lineWidth[i] = contentWidth(line, lineOffset, gc) + caretWidth; |
1205 |
int lineOffset = content.getOffsetAtLine(i); |
1206 |
} |
1206 |
|
1207 |
if (lineWidth[i] > maxWidth) { |
1207 |
if (gc == null) { |
1208 |
maxWidth = lineWidth[i]; |
1208 |
gc = parent.getGC(); |
1209 |
maxWidthLineIndex = i; |
1209 |
caretWidth = getCaretWidth(); |
1210 |
} |
1210 |
} |
1211 |
} |
1211 |
lineWidth[i] = contentWidth(line, lineOffset, gc) + caretWidth; |
1212 |
if (gc != null) { |
1212 |
} |
1213 |
gc.dispose(); |
1213 |
if (lineWidth[i] > maxWidth) { |
1214 |
} |
1214 |
maxWidth = lineWidth[i]; |
1215 |
} |
1215 |
maxWidthLineIndex = i; |
1216 |
/** |
1216 |
} |
1217 |
* Calculates the width of the visible lines in the specified |
1217 |
} |
1218 |
* range. |
1218 |
if (gc != null) { |
1219 |
* <p> |
1219 |
gc.dispose(); |
1220 |
* |
1220 |
} |
1221 |
* @param startLine the first changed line |
1221 |
} |
1222 |
* @param newLineCount the number of inserted lines |
1222 |
/** |
1223 |
*/ |
1223 |
* Calculates the width of the visible lines in the specified |
1224 |
void calculateVisible(int startLine, int newLineCount) { |
1224 |
* range. |
1225 |
int topIndex = parent.getTopIndex(); |
1225 |
* <p> |
1226 |
int bottomLine = Math.min(getPartialBottomIndex(), startLine + newLineCount); |
1226 |
* |
1227 |
|
1227 |
* @param startLine the first changed line |
1228 |
startLine = Math.max(startLine, topIndex); |
1228 |
* @param newLineCount the number of inserted lines |
1229 |
calculate(startLine, bottomLine - startLine + 1); |
1229 |
*/ |
1230 |
} |
1230 |
void calculateVisible(int startLine, int newLineCount) { |
1231 |
/** |
1231 |
int topIndex = parent.getTopIndex(); |
1232 |
* Measures the width of the given line. |
1232 |
int bottomLine = Math.min(getPartialBottomIndex(), startLine + newLineCount); |
1233 |
* <p> |
1233 |
|
1234 |
* |
1234 |
startLine = Math.max(startLine, topIndex); |
1235 |
* @param line the line to measure |
1235 |
calculate(startLine, bottomLine - startLine + 1); |
1236 |
* @param lineOffset start offset of the line to measure, relative |
1236 |
} |
1237 |
* to the start of the document |
1237 |
/** |
1238 |
* @param gc the GC to use for measuring the line |
1238 |
* Measures the width of the given line. |
1239 |
* @param currentFont the font currently set in gc. Cached for better |
1239 |
* <p> |
1240 |
* performance. Null when running in a bidi locale. |
1240 |
* |
1241 |
* @return the width of the given line |
1241 |
* @param line the line to measure |
1242 |
*/ |
1242 |
* @param lineOffset start offset of the line to measure, relative |
1243 |
int contentWidth(String line, int lineOffset, GC gc) { |
1243 |
* to the start of the document |
1244 |
int width; |
1244 |
* @param gc the GC to use for measuring the line |
1245 |
|
1245 |
* @param currentFont the font currently set in gc. Cached for better |
1246 |
if (isBidi()) { |
1246 |
* performance. Null when running in a bidi locale. |
1247 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); |
1247 |
* @return the width of the given line |
1248 |
width = bidi.getTextWidth(); |
1248 |
*/ |
1249 |
} |
1249 |
int contentWidth(String line, int lineOffset, GC gc) { |
1250 |
else { |
1250 |
int width; |
1251 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
1251 |
|
1252 |
StyleRange[] styles = null; |
1252 |
if (isBidi()) { |
1253 |
if (event != null) { |
1253 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); |
1254 |
styles = renderer.filterLineStyles(event.styles); |
1254 |
width = bidi.getTextWidth(); |
1255 |
} |
1255 |
} |
1256 |
width = renderer.getTextWidth(line, lineOffset, 0, line.length(), styles, 0, gc); |
1256 |
else { |
1257 |
} |
1257 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
1258 |
return width + leftMargin; |
1258 |
StyleRange[] styles = null; |
1259 |
} |
1259 |
if (event != null) { |
1260 |
/** |
1260 |
styles = renderer.filterLineStyles(event.styles); |
1261 |
* Grows the <code>lineWidth</code> array to accomodate new line width |
1261 |
} |
1262 |
* information. |
1262 |
width = renderer.getTextWidth(line, lineOffset, 0, line.length(), styles, 0, gc); |
1263 |
* <p> |
1263 |
} |
1264 |
* |
1264 |
return width + leftMargin; |
1265 |
* @param numLines the number of elements to increase the array by |
1265 |
} |
1266 |
*/ |
1266 |
/** |
1267 |
void expandLines(int numLines) { |
1267 |
* Grows the <code>lineWidth</code> array to accomodate new line width |
1268 |
int size = lineWidth.length; |
1268 |
* information. |
1269 |
if (size - lineCount >= numLines) { |
1269 |
* <p> |
1270 |
return; |
1270 |
* |
1271 |
} |
1271 |
* @param numLines the number of elements to increase the array by |
1272 |
int[] newLines = new int[Math.max(size * 2, size + numLines)]; |
1272 |
*/ |
1273 |
System.arraycopy(lineWidth, 0, newLines, 0, size); |
1273 |
void expandLines(int numLines) { |
1274 |
lineWidth = newLines; |
1274 |
int size = lineWidth.length; |
1275 |
reset(size, lineWidth.length - size, false); |
1275 |
if (size - lineCount >= numLines) { |
1276 |
} |
1276 |
return; |
1277 |
/** |
1277 |
} |
1278 |
* Returns the width of the longest measured line. |
1278 |
int[] newLines = new int[Math.max(size * 2, size + numLines)]; |
1279 |
* <p> |
1279 |
System.arraycopy(lineWidth, 0, newLines, 0, size); |
1280 |
* |
1280 |
lineWidth = newLines; |
1281 |
* @return the width of the longest measured line. |
1281 |
reset(size, lineWidth.length - size, false); |
1282 |
*/ |
1282 |
} |
1283 |
public int getWidth() { |
1283 |
/** |
1284 |
return maxWidth; |
1284 |
* Returns the width of the longest measured line. |
1285 |
} |
1285 |
* <p> |
1286 |
/** |
1286 |
* |
1287 |
* Updates the line width array to reflect inserted or deleted lines. |
1287 |
* @return the width of the longest measured line. |
1288 |
* <p> |
1288 |
*/ |
1289 |
* |
1289 |
public int getWidth() { |
1290 |
* @param start the starting line of the change that took place |
1290 |
return maxWidth; |
1291 |
* @param delta the number of lines in the change, > 0 indicates lines inserted, |
1291 |
} |
1292 |
* < 0 indicates lines deleted |
1292 |
/** |
1293 |
*/ |
1293 |
* Updates the line width array to reflect inserted or deleted lines. |
1294 |
void linesChanged(int startLine, int delta) { |
1294 |
* <p> |
1295 |
boolean inserting = delta > 0; |
1295 |
* |
1296 |
|
1296 |
* @param start the starting line of the change that took place |
1297 |
if (delta == 0) { |
1297 |
* @param delta the number of lines in the change, > 0 indicates lines inserted, |
1298 |
return; |
1298 |
* < 0 indicates lines deleted |
1299 |
} |
1299 |
*/ |
1300 |
if (inserting) { |
1300 |
void linesChanged(int startLine, int delta) { |
1301 |
// shift the lines down to make room for new lines |
1301 |
boolean inserting = delta > 0; |
1302 |
expandLines(delta); |
1302 |
|
1303 |
for (int i = lineCount - 1; i >= startLine; i--) { |
1303 |
if (delta == 0) { |
1304 |
lineWidth[i + delta] = lineWidth[i]; |
1304 |
return; |
1305 |
} |
1305 |
} |
1306 |
// reset the new lines |
1306 |
if (inserting) { |
1307 |
for (int i = startLine + 1; i <= startLine + delta && i < lineWidth.length; i++) { |
1307 |
// shift the lines down to make room for new lines |
1308 |
lineWidth[i] = -1; |
1308 |
expandLines(delta); |
1309 |
} |
1309 |
for (int i = lineCount - 1; i >= startLine; i--) { |
1310 |
// have new lines been inserted above the longest line? |
1310 |
lineWidth[i + delta] = lineWidth[i]; |
1311 |
if (maxWidthLineIndex >= startLine) { |
1311 |
} |
1312 |
maxWidthLineIndex += delta; |
1312 |
// reset the new lines |
1313 |
} |
1313 |
for (int i = startLine + 1; i <= startLine + delta && i < lineWidth.length; i++) { |
1314 |
} |
1314 |
lineWidth[i] = -1; |
1315 |
else { |
1315 |
} |
1316 |
// shift up the lines |
1316 |
// have new lines been inserted above the longest line? |
1317 |
for (int i = startLine - delta; i < lineCount; i++) { |
1317 |
if (maxWidthLineIndex >= startLine) { |
1318 |
lineWidth[i+delta] = lineWidth[i]; |
1318 |
maxWidthLineIndex += delta; |
1319 |
} |
1319 |
} |
1320 |
// has the longest line been removed? |
1320 |
} |
1321 |
if (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine - delta) { |
1321 |
else { |
1322 |
maxWidth = 0; |
1322 |
// shift up the lines |
1323 |
maxWidthLineIndex = -1; |
1323 |
for (int i = startLine - delta; i < lineCount; i++) { |
1324 |
} |
1324 |
lineWidth[i+delta] = lineWidth[i]; |
1325 |
else |
1325 |
} |
1326 |
if (maxWidthLineIndex >= startLine - delta) { |
1326 |
// has the longest line been removed? |
1327 |
maxWidthLineIndex += delta; |
1327 |
if (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine - delta) { |
1328 |
} |
1328 |
maxWidth = 0; |
1329 |
} |
1329 |
maxWidthLineIndex = -1; |
1330 |
lineCount += delta; |
1330 |
} |
1331 |
} |
1331 |
else |
1332 |
/** |
1332 |
if (maxWidthLineIndex >= startLine - delta) { |
1333 |
* Resets the line width of the lines in the specified range. |
1333 |
maxWidthLineIndex += delta; |
1334 |
* <p> |
1334 |
} |
1335 |
* |
1335 |
} |
1336 |
* @param startLine the first line to reset |
1336 |
lineCount += delta; |
1337 |
* @param lineCount the number of lines to reset |
1337 |
} |
1338 |
* @param calculateMaxWidth true=if the widest line is being |
1338 |
/** |
1339 |
* reset the maximum width of all remaining cached lines is |
1339 |
* Resets the line width of the lines in the specified range. |
1340 |
* calculated. false=the maximum width is set to 0 if the |
1340 |
* <p> |
1341 |
* widest line is being reset. |
1341 |
* |
1342 |
*/ |
1342 |
* @param startLine the first line to reset |
1343 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1343 |
* @param lineCount the number of lines to reset |
1344 |
reset(startLine, lineCount, calculateMaxWidth); |
1344 |
* @param calculateMaxWidth true=if the widest line is being |
1345 |
} |
1345 |
* reset the maximum width of all remaining cached lines is |
1346 |
/** |
1346 |
* calculated. false=the maximum width is set to 0 if the |
1347 |
* Resets the line width of the lines in the specified range. |
1347 |
* widest line is being reset. |
1348 |
* <p> |
1348 |
*/ |
1349 |
* |
1349 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1350 |
* @param startLine the first line to reset |
1350 |
reset(startLine, lineCount, calculateMaxWidth); |
1351 |
* @param lineCount the number of lines to reset |
1351 |
} |
1352 |
* @param calculateMaxWidth true=if the widest line is being |
1352 |
/** |
1353 |
* reset the maximum width of all remaining cached lines is |
1353 |
* Resets the line width of the lines in the specified range. |
1354 |
* calculated. false=the maximum width is set to 0 if the |
1354 |
* <p> |
1355 |
* widest line is being reset. |
1355 |
* |
1356 |
*/ |
1356 |
* @param startLine the first line to reset |
1357 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1357 |
* @param lineCount the number of lines to reset |
1358 |
int endLine = startLine + lineCount; |
1358 |
* @param calculateMaxWidth true=if the widest line is being |
1359 |
|
1359 |
* reset the maximum width of all remaining cached lines is |
1360 |
if (startLine < 0 || endLine > lineWidth.length) { |
1360 |
* calculated. false=the maximum width is set to 0 if the |
1361 |
return; |
1361 |
* widest line is being reset. |
1362 |
} |
1362 |
*/ |
1363 |
for (int i = startLine; i < endLine; i++) { |
1363 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1364 |
lineWidth[i] = -1; |
1364 |
int endLine = startLine + lineCount; |
1365 |
} |
1365 |
|
1366 |
// if the longest line is one of the reset lines, the maximum line |
1366 |
if (startLine < 0 || endLine > lineWidth.length) { |
1367 |
// width is no longer valid |
1367 |
return; |
1368 |
if (maxWidthLineIndex >= startLine && maxWidthLineIndex < endLine) { |
1368 |
} |
1369 |
maxWidth = 0; |
1369 |
for (int i = startLine; i < endLine; i++) { |
1370 |
maxWidthLineIndex = -1; |
1370 |
lineWidth[i] = -1; |
1371 |
if (calculateMaxWidth) { |
1371 |
} |
1372 |
for (int i = 0; i < lineCount; i++) { |
1372 |
// if the longest line is one of the reset lines, the maximum line |
1373 |
if (lineWidth[i] > maxWidth) { |
1373 |
// width is no longer valid |
1374 |
maxWidth = lineWidth[i]; |
1374 |
if (maxWidthLineIndex >= startLine && maxWidthLineIndex < endLine) { |
1375 |
maxWidthLineIndex = i; |
1375 |
maxWidth = 0; |
1376 |
} |
1376 |
maxWidthLineIndex = -1; |
1377 |
} |
1377 |
if (calculateMaxWidth) { |
1378 |
} |
1378 |
for (int i = 0; i < lineCount; i++) { |
1379 |
} |
1379 |
if (lineWidth[i] > maxWidth) { |
1380 |
} |
1380 |
maxWidth = lineWidth[i]; |
1381 |
/** |
1381 |
maxWidthLineIndex = i; |
1382 |
* Updates the line width array to reflect a text change. |
1382 |
} |
1383 |
* Lines affected by the text change will be reset. |
1383 |
} |
1384 |
* <p> |
1384 |
} |
1385 |
* |
1385 |
} |
1386 |
* @param startOffset the start offset of the text change |
1386 |
} |
1387 |
* @param newLineCount the number of inserted lines |
1387 |
/** |
1388 |
* @param replaceLineCount the number of deleted lines |
1388 |
* Updates the line width array to reflect a text change. |
1389 |
* @param newCharCount the number of new characters |
1389 |
* Lines affected by the text change will be reset. |
1390 |
* @param replaceCharCount the number of deleted characters |
1390 |
* <p> |
1391 |
*/ |
1391 |
* |
1392 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) { |
1392 |
* @param startOffset the start offset of the text change |
1393 |
int startLine = parent.getLineAtOffset(startOffset); |
1393 |
* @param newLineCount the number of inserted lines |
1394 |
boolean removedMaxLine = (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine + replaceLineCount); |
1394 |
* @param replaceLineCount the number of deleted lines |
1395 |
// entire text deleted? |
1395 |
* @param newCharCount the number of new characters |
1396 |
if (startLine == 0 && replaceLineCount == lineCount) { |
1396 |
* @param replaceCharCount the number of deleted characters |
1397 |
lineCount = newLineCount; |
1397 |
*/ |
1398 |
lineWidth = new int[lineCount]; |
1398 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) { |
1399 |
reset(0, lineCount, false); |
1399 |
int startLine = parent.getLineAtOffset(startOffset); |
1400 |
maxWidth = 0; |
1400 |
boolean removedMaxLine = (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine + replaceLineCount); |
1401 |
} |
1401 |
// entire text deleted? |
1402 |
else { |
1402 |
if (startLine == 0 && replaceLineCount == lineCount) { |
1403 |
linesChanged(startLine, -replaceLineCount); |
1403 |
lineCount = newLineCount; |
1404 |
linesChanged(startLine, newLineCount); |
1404 |
lineWidth = new int[lineCount]; |
1405 |
lineWidth[startLine] = -1; |
1405 |
reset(0, lineCount, false); |
1406 |
} |
1406 |
maxWidth = 0; |
1407 |
// only calculate the visible lines. otherwise measurements of changed lines |
1407 |
} |
1408 |
// outside the visible area may subsequently change again without the |
1408 |
else { |
1409 |
// lines ever being visible. |
1409 |
linesChanged(startLine, -replaceLineCount); |
1410 |
calculateVisible(startLine, newLineCount); |
1410 |
linesChanged(startLine, newLineCount); |
1411 |
// maxWidthLineIndex will be -1 (i.e., unknown line width) if the widget has |
1411 |
lineWidth[startLine] = -1; |
1412 |
// not been visible yet and the changed lines have therefore not been |
1412 |
} |
1413 |
// calculated above. |
1413 |
// only calculate the visible lines. otherwise measurements of changed lines |
1414 |
if (removedMaxLine || |
1414 |
// outside the visible area may subsequently change again without the |
1415 |
(maxWidthLineIndex != -1 && lineWidth[maxWidthLineIndex] < maxWidth)) { |
1415 |
// lines ever being visible. |
1416 |
// longest line has been removed or changed and is now shorter. |
1416 |
calculateVisible(startLine, newLineCount); |
1417 |
// need to recalculate maximum content width for all lines |
1417 |
// maxWidthLineIndex will be -1 (i.e., unknown line width) if the widget has |
1418 |
maxWidth = 0; |
1418 |
// not been visible yet and the changed lines have therefore not been |
1419 |
for (int i = 0; i < lineCount; i++) { |
1419 |
// calculated above. |
1420 |
if (lineWidth[i] > maxWidth) { |
1420 |
if (removedMaxLine || |
1421 |
maxWidth = lineWidth[i]; |
1421 |
(maxWidthLineIndex != -1 && lineWidth[maxWidthLineIndex] < maxWidth)) { |
1422 |
maxWidthLineIndex = i; |
1422 |
// longest line has been removed or changed and is now shorter. |
1423 |
} |
1423 |
// need to recalculate maximum content width for all lines |
1424 |
} |
1424 |
maxWidth = 0; |
1425 |
} |
1425 |
for (int i = 0; i < lineCount; i++) { |
1426 |
} |
1426 |
if (lineWidth[i] > maxWidth) { |
1427 |
} |
1427 |
maxWidth = lineWidth[i]; |
1428 |
/** |
1428 |
maxWidthLineIndex = i; |
1429 |
* Updates the line wrapping of the content. |
1429 |
} |
1430 |
* The line wrapping must always be in a consistent state. |
1430 |
} |
1431 |
* Therefore, when <code>reset</code> or <code>redrawReset</code> |
1431 |
} |
1432 |
* is called, the line wrapping is recalculated immediately |
1432 |
} |
1433 |
* instead of in <code>calculate</code>. |
1433 |
} |
1434 |
*/ |
1434 |
/** |
1435 |
class WordWrapCache implements LineCache { |
1435 |
* Updates the line wrapping of the content. |
1436 |
StyledText parent; |
1436 |
* The line wrapping must always be in a consistent state. |
1437 |
WrappedContent visualContent; |
1437 |
* Therefore, when <code>reset</code> or <code>redrawReset</code> |
1438 |
|
1438 |
* is called, the line wrapping is recalculated immediately |
1439 |
/** |
1439 |
* instead of in <code>calculate</code>. |
1440 |
* Creates a new <code>WordWrapCache</code> and calculates an initial |
1440 |
*/ |
1441 |
* line wrapping. |
1441 |
class WordWrapCache implements LineCache { |
1442 |
* <p> |
1442 |
StyledText parent; |
1443 |
* |
1443 |
WrappedContent visualContent; |
1444 |
* @param parent the StyledText widget to wrap content in. |
1444 |
|
1445 |
* @param content the content provider that does the actual line wrapping. |
1445 |
/** |
1446 |
*/ |
1446 |
* Creates a new <code>WordWrapCache</code> and calculates an initial |
1447 |
public WordWrapCache(StyledText parent, WrappedContent content) { |
1447 |
* line wrapping. |
1448 |
this.parent = parent; |
1448 |
* <p> |
1449 |
visualContent = content; |
1449 |
* |
1450 |
visualContent.wrapLines(); |
1450 |
* @param parent the StyledText widget to wrap content in. |
1451 |
} |
1451 |
* @param content the content provider that does the actual line wrapping. |
1452 |
/** |
1452 |
*/ |
1453 |
* Do nothing. Lines are wrapped immediately after reset. |
1453 |
public WordWrapCache(StyledText parent, WrappedContent content) { |
1454 |
* <p> |
1454 |
this.parent = parent; |
1455 |
* |
1455 |
visualContent = content; |
1456 |
* @param startLine first line to calculate |
1456 |
visualContent.wrapLines(); |
1457 |
* @param lineCount number of lines to calculate |
1457 |
} |
1458 |
*/ |
1458 |
/** |
1459 |
public void calculate(int startLine, int lineCount) { |
1459 |
* Do nothing. Lines are wrapped immediately after reset. |
1460 |
} |
1460 |
* <p> |
1461 |
/** |
1461 |
* |
1462 |
* Returns the client area width. Lines are wrapped so there |
1462 |
* @param startLine first line to calculate |
1463 |
* is no horizontal scroll bar. |
1463 |
* @param lineCount number of lines to calculate |
1464 |
* <p> |
1464 |
*/ |
1465 |
* |
1465 |
public void calculate(int startLine, int lineCount) { |
1466 |
* @return the line width |
1466 |
} |
1467 |
*/ |
1467 |
/** |
1468 |
public int getWidth() { |
1468 |
* Returns the client area width. Lines are wrapped so there |
1469 |
return parent.getClientArea().width; |
1469 |
* is no horizontal scroll bar. |
1470 |
} |
1470 |
* <p> |
1471 |
/** |
1471 |
* |
1472 |
* Wraps the lines in the specified range. |
1472 |
* @return the line width |
1473 |
* This method is called in <code>StyledText.redraw()</code>. |
1473 |
*/ |
1474 |
* A redraw is therefore not necessary. |
1474 |
public int getWidth() { |
1475 |
* <p> |
1475 |
return parent.getClientArea().width; |
1476 |
* |
1476 |
} |
1477 |
* @param startLine the first line to reset |
1477 |
/** |
1478 |
* @param lineCount the number of lines to reset |
1478 |
* Wraps the lines in the specified range. |
1479 |
* @param calculateMaxWidth true=implementors should retain a |
1479 |
* This method is called in <code>StyledText.redraw()</code>. |
1480 |
* valid width even if it is affected by the reset operation. |
1480 |
* A redraw is therefore not necessary. |
1481 |
* false=the width may be set to 0 |
1481 |
* <p> |
1482 |
*/ |
1482 |
* |
1483 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1483 |
* @param startLine the first line to reset |
1484 |
if (lineCount == visualContent.getLineCount()) { |
1484 |
* @param lineCount the number of lines to reset |
1485 |
// do a full rewrap if all lines are reset |
1485 |
* @param calculateMaxWidth true=implementors should retain a |
1486 |
visualContent.wrapLines(); |
1486 |
* valid width even if it is affected by the reset operation. |
1487 |
} |
1487 |
* false=the width may be set to 0 |
1488 |
else { |
1488 |
*/ |
1489 |
visualContent.reset(startLine, lineCount); |
1489 |
public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1490 |
} |
1490 |
if (lineCount == visualContent.getLineCount()) { |
1491 |
} |
1491 |
// do a full rewrap if all lines are reset |
1492 |
/** |
1492 |
visualContent.wrapLines(); |
1493 |
* Rewraps the lines in the specified range and redraws |
1493 |
} |
1494 |
* the widget if the line wrapping has changed. |
1494 |
else { |
1495 |
* <p> |
1495 |
visualContent.reset(startLine, lineCount); |
1496 |
* |
1496 |
} |
1497 |
* @param startLine the first line to reset |
1497 |
} |
1498 |
* @param lineCount the number of lines to reset |
1498 |
/** |
1499 |
* @param calculateMaxWidth true=implementors should retain a |
1499 |
* Rewraps the lines in the specified range and redraws |
1500 |
* valid width even if it is affected by the reset operation. |
1500 |
* the widget if the line wrapping has changed. |
1501 |
* false=the width may be set to 0 |
1501 |
* <p> |
1502 |
*/ |
1502 |
* |
1503 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1503 |
* @param startLine the first line to reset |
1504 |
int itemCount = getPartialBottomIndex() - topIndex + 1; |
1504 |
* @param lineCount the number of lines to reset |
1505 |
int[] oldLineOffsets = new int[itemCount]; |
1505 |
* @param calculateMaxWidth true=implementors should retain a |
1506 |
|
1506 |
* valid width even if it is affected by the reset operation. |
1507 |
for (int i = 0; i < itemCount; i++) { |
1507 |
* false=the width may be set to 0 |
1508 |
oldLineOffsets[i] = visualContent.getOffsetAtLine(i + topIndex); |
1508 |
*/ |
1509 |
} |
1509 |
public void reset(int startLine, int lineCount, boolean calculateMaxWidth) { |
1510 |
redrawReset(startLine, lineCount, calculateMaxWidth); |
1510 |
int itemCount = getPartialBottomIndex() - topIndex + 1; |
1511 |
// check for cases which will require a full redraw |
1511 |
int[] oldLineOffsets = new int[itemCount]; |
1512 |
if (getPartialBottomIndex() - topIndex + 1 != itemCount) { |
1512 |
|
1513 |
// number of visible lines has changed |
1513 |
for (int i = 0; i < itemCount; i++) { |
1514 |
parent.internalRedraw(); |
1514 |
oldLineOffsets[i] = visualContent.getOffsetAtLine(i + topIndex); |
1515 |
} |
1515 |
} |
1516 |
else { |
1516 |
redrawReset(startLine, lineCount, calculateMaxWidth); |
1517 |
for (int i = 0; i < itemCount; i++) { |
1517 |
// check for cases which will require a full redraw |
1518 |
if (visualContent.getOffsetAtLine(i + topIndex) != oldLineOffsets[i]) { |
1518 |
if (getPartialBottomIndex() - topIndex + 1 != itemCount) { |
1519 |
// wrapping of one of the visible lines has changed |
1519 |
// number of visible lines has changed |
1520 |
parent.internalRedraw(); |
1520 |
parent.internalRedraw(); |
1521 |
break; |
1521 |
} |
1522 |
} |
1522 |
else { |
1523 |
} |
1523 |
for (int i = 0; i < itemCount; i++) { |
1524 |
} |
1524 |
if (visualContent.getOffsetAtLine(i + topIndex) != oldLineOffsets[i]) { |
1525 |
} |
1525 |
// wrapping of one of the visible lines has changed |
1526 |
/** |
1526 |
parent.internalRedraw(); |
1527 |
* Passes the text change notification to the line wrap content. |
1527 |
break; |
1528 |
* <p> |
1528 |
} |
1529 |
* |
1529 |
} |
1530 |
* @param startOffset the start offset of the text change |
1530 |
} |
1531 |
* @param newLineCount the number of inserted lines |
1531 |
} |
1532 |
* @param replaceLineCount the number of deleted lines |
1532 |
/** |
1533 |
* @param newCharCount the number of new characters |
1533 |
* Passes the text change notification to the line wrap content. |
1534 |
* @param replaceCharCount the number of deleted characters |
1534 |
* <p> |
1535 |
*/ |
1535 |
* |
1536 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) { |
1536 |
* @param startOffset the start offset of the text change |
1537 |
int startLine = visualContent.getLineAtOffset(startOffset); |
1537 |
* @param newLineCount the number of inserted lines |
1538 |
|
1538 |
* @param replaceLineCount the number of deleted lines |
1539 |
visualContent.textChanged(startOffset, newLineCount, replaceLineCount, newCharCount, replaceCharCount); |
1539 |
* @param newCharCount the number of new characters |
1540 |
if (startLine <= getPartialBottomIndex()) { |
1540 |
* @param replaceCharCount the number of deleted characters |
1541 |
// only redraw if the text change is inside or above the |
1541 |
*/ |
1542 |
// visible lines. if it is below the visible lines it will |
1542 |
public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) { |
1543 |
// not affect the word wrapping. fixes bug 14047. |
1543 |
int startLine = visualContent.getLineAtOffset(startOffset); |
1544 |
parent.internalRedraw(); |
1544 |
|
1545 |
} |
1545 |
visualContent.textChanged(startOffset, newLineCount, replaceLineCount, newCharCount, replaceCharCount); |
1546 |
} |
1546 |
if (startLine <= getPartialBottomIndex()) { |
1547 |
} |
1547 |
// only redraw if the text change is inside or above the |
|
|
1548 |
// visible lines. if it is below the visible lines it will |
1549 |
// not affect the word wrapping. fixes bug 14047. |
1550 |
parent.internalRedraw(); |
1551 |
} |
1552 |
} |
1553 |
} |
1548 |
|
1554 |
|
1549 |
/** |
1555 |
/** |
1550 |
* Constructs a new instance of this class given its parent |
1556 |
* Constructs a new instance of this class given its parent |
Lines 1552-1558
Link Here
|
1552 |
* <p> |
1558 |
* <p> |
1553 |
* The style value is either one of the style constants defined in |
1559 |
* The style value is either one of the style constants defined in |
1554 |
* class <code>SWT</code> which is applicable to instances of this |
1560 |
* class <code>SWT</code> which is applicable to instances of this |
1555 |
* class, or must be built by <em>bitwise OR</em>'ing together |
1561 |
* class, or must be built by <em>bitwise OR</em>'ing together |
1556 |
* (that is, using the <code>int</code> "|" operator) two or more |
1562 |
* (that is, using the <code>int</code> "|" operator) two or more |
1557 |
* of those <code>SWT</code> style constants. The class description |
1563 |
* of those <code>SWT</code> style constants. The class description |
1558 |
* lists the style constants that are applicable to the class. |
1564 |
* lists the style constants that are applicable to the class. |
Lines 1577-1636
Link Here
|
1577 |
* @see #getStyle |
1583 |
* @see #getStyle |
1578 |
*/ |
1584 |
*/ |
1579 |
public StyledText(Composite parent, int style) { |
1585 |
public StyledText(Composite parent, int style) { |
1580 |
super(parent, checkStyle(style | SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND)); |
1586 |
super(parent, checkStyle(style | SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND)); |
1581 |
// set the bg/fg in the OS to ensure that these are the same as StyledText, necessary |
1587 |
// set the bg/fg in the OS to ensure that these are the same as StyledText, necessary |
1582 |
// for ensuring that the bg/fg the IME box uses is the same as what StyledText uses |
1588 |
// for ensuring that the bg/fg the IME box uses is the same as what StyledText uses |
1583 |
super.setForeground(getForeground()); |
1589 |
super.setForeground(getForeground()); |
1584 |
super.setBackground(getBackground()); |
1590 |
super.setBackground(getBackground()); |
1585 |
Display display = getDisplay(); |
1591 |
Display display = getDisplay(); |
1586 |
isBidi = StyledTextBidi.isBidiPlatform(); |
1592 |
isBidi = StyledTextBidi.isBidiPlatform(); |
1587 |
if ((style & SWT.READ_ONLY) != 0) { |
1593 |
if ((style & SWT.READ_ONLY) != 0) { |
1588 |
setEditable(false); |
1594 |
setEditable(false); |
1589 |
} |
1595 |
} |
1590 |
if ((style & SWT.BORDER) == 0 || (style & SWT.SINGLE) == 0) { |
1596 |
if ((style & SWT.BORDER) == 0 || (style & SWT.SINGLE) == 0) { |
1591 |
leftMargin = topMargin = rightMargin = bottomMargin = 0; |
1597 |
leftMargin = topMargin = rightMargin = bottomMargin = 0; |
1592 |
} |
1598 |
} |
1593 |
clipboard = new Clipboard(display); |
1599 |
clipboard = new Clipboard(display); |
1594 |
installDefaultContent(); |
1600 |
installDefaultContent(); |
1595 |
initializeRenderer(); |
1601 |
initializeRenderer(); |
1596 |
if ((style & SWT.WRAP) != 0) { |
1602 |
if ((style & SWT.WRAP) != 0) { |
1597 |
setWordWrap(true); |
1603 |
setWordWrap(true); |
1598 |
} |
1604 |
} |
1599 |
else { |
1605 |
else { |
1600 |
lineCache = new ContentWidthCache(this, content.getLineCount()); |
1606 |
lineCache = new ContentWidthCache(this, content.getLineCount()); |
1601 |
} |
1607 |
} |
1602 |
if (isBidi() == false) { |
1608 |
if (isBidi() == false) { |
1603 |
Caret caret = new Caret(this, SWT.NULL); |
1609 |
Caret caret = new Caret(this, SWT.NULL); |
1604 |
caret.setSize(1, caret.getSize().y); |
1610 |
caret.setSize(1, caret.getSize().y); |
1605 |
} |
1611 |
} |
1606 |
else { |
1612 |
else { |
1607 |
createCaretBitmaps(); |
1613 |
createCaretBitmaps(); |
1608 |
new Caret(this, SWT.NULL); |
1614 |
new Caret(this, SWT.NULL); |
1609 |
setBidiCaretDirection(); |
1615 |
setBidiCaretDirection(); |
1610 |
Runnable runnable = new Runnable() { |
1616 |
Runnable runnable = new Runnable() { |
1611 |
public void run() { |
1617 |
public void run() { |
1612 |
// setBidiCaretLocation calculates caret location like during |
1618 |
// setBidiCaretLocation calculates caret location like during |
1613 |
// cursor movement and takes keyboard language into account. |
1619 |
// cursor movement and takes keyboard language into account. |
1614 |
// Fixes 1GKPYMK |
1620 |
// Fixes 1GKPYMK |
1615 |
setBidiCaretLocation(null); |
1621 |
setBidiCaretLocation(null); |
1616 |
} |
1622 |
} |
1617 |
}; |
1623 |
}; |
1618 |
StyledTextBidi.addLanguageListener(this, runnable); |
1624 |
StyledTextBidi.addLanguageListener(this, runnable); |
1619 |
} |
1625 |
} |
1620 |
|
1626 |
|
1621 |
String platform= SWT.getPlatform(); |
1627 |
String platform= SWT.getPlatform(); |
1622 |
isCarbon = "carbon".equals(platform); |
1628 |
isCarbon = "carbon".equals(platform); |
1623 |
|
1629 |
|
1624 |
// set the caret width, the height of the caret will default to the line height |
1630 |
// set the caret width, the height of the caret will default to the line height |
1625 |
calculateScrollBars(); |
1631 |
calculateScrollBars(); |
1626 |
createKeyBindings(); |
1632 |
createKeyBindings(); |
1627 |
ibeamCursor = new Cursor(display, SWT.CURSOR_IBEAM); |
1633 |
|
1628 |
setCursor(ibeamCursor); |
1634 |
ibeamCursor = new Cursor(display, SWT.CURSOR_IBEAM); |
1629 |
installListeners(); |
1635 |
arrowCursor = new Cursor(display, SWT.CURSOR_ARROW); |
1630 |
installDefaultLineStyler(); |
1636 |
currentCursor = ibeamCursor; |
|
|
1637 |
super.setCursor(currentCursor); |
1638 |
|
1639 |
installListeners(); |
1640 |
installDefaultLineStyler(); |
1631 |
} |
1641 |
} |
1632 |
/** |
1642 |
/** |
1633 |
* Adds an extended modify listener. An ExtendedModify event is sent by the |
1643 |
* Adds an extended modify listener. An ExtendedModify event is sent by the |
1634 |
* widget when the widget text has changed. |
1644 |
* widget when the widget text has changed. |
1635 |
* <p> |
1645 |
* <p> |
1636 |
* |
1646 |
* |
Lines 1644-1718
Link Here
|
1644 |
* </ul> |
1654 |
* </ul> |
1645 |
*/ |
1655 |
*/ |
1646 |
public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { |
1656 |
public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { |
1647 |
checkWidget(); |
1657 |
checkWidget(); |
1648 |
if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1658 |
if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1649 |
StyledTextListener typedListener = new StyledTextListener(extendedModifyListener); |
1659 |
StyledTextListener typedListener = new StyledTextListener(extendedModifyListener); |
1650 |
addListener(ExtendedModify, typedListener); |
1660 |
addListener(ExtendedModify, typedListener); |
1651 |
} |
1661 |
} |
1652 |
/** |
1662 |
/** |
1653 |
* Maps a key to an action. |
1663 |
* Maps a key to an action. |
1654 |
* One action can be associated with N keys. However, each key can only |
1664 |
* One action can be associated with N keys. However, each key can only |
1655 |
* have one action (key:action is N:1 relation). |
1665 |
* have one action (key:action is N:1 relation). |
1656 |
* <p> |
1666 |
* <p> |
1657 |
* |
1667 |
* |
1658 |
* @param key a key code defined in SWT.java or a character. |
1668 |
* @param key a key code defined in SWT.java or a character. |
1659 |
* Optionally ORd with a state mask. Preferred state masks are one or more of |
1669 |
* Optionally ORd with a state mask. Preferred state masks are one or more of |
1660 |
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform |
1670 |
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform |
1661 |
* differences. However, there may be cases where using the specific state masks |
1671 |
* differences. However, there may be cases where using the specific state masks |
1662 |
* (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. |
1672 |
* (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. |
1663 |
* @param action one of the predefined actions defined in ST.java. |
1673 |
* @param action one of the predefined actions defined in ST.java. |
1664 |
* Use SWT.NULL to remove a key binding. |
1674 |
* Use SWT.NULL to remove a key binding. |
1665 |
* @exception SWTException <ul> |
1675 |
* @exception SWTException <ul> |
1666 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1676 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
1667 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1677 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
1668 |
* </ul> |
1678 |
* </ul> |
1669 |
*/ |
1679 |
*/ |
1670 |
public void setKeyBinding(int key, int action) { |
1680 |
public void setKeyBinding(int key, int action) { |
1671 |
checkWidget(); |
1681 |
checkWidget(); |
1672 |
|
1682 |
|
1673 |
int keyValue = key & SWT.KEY_MASK; |
1683 |
int keyValue = key & SWT.KEY_MASK; |
1674 |
int modifierValue = key & SWT.MODIFIER_MASK; |
1684 |
int modifierValue = key & SWT.MODIFIER_MASK; |
1675 |
char keyChar = (char)keyValue; |
1685 |
char keyChar = (char)keyValue; |
1676 |
|
1686 |
|
1677 |
if (Character.isLetter(keyChar)) { |
1687 |
if (Character.isLetter(keyChar)) { |
1678 |
// make the keybinding case insensitive by adding it |
1688 |
// make the keybinding case insensitive by adding it |
1679 |
// in its upper and lower case form |
1689 |
// in its upper and lower case form |
1680 |
char ch = Character.toUpperCase(keyChar); |
1690 |
char ch = Character.toUpperCase(keyChar); |
1681 |
int newKey = ch | modifierValue; |
1691 |
int newKey = ch | modifierValue; |
1682 |
if (action == SWT.NULL) { |
1692 |
if (action == SWT.NULL) { |
1683 |
keyActionMap.remove(new Integer(newKey)); |
1693 |
keyActionMap.remove(new Integer(newKey)); |
1684 |
} |
1694 |
} |
1685 |
else { |
1695 |
else { |
1686 |
keyActionMap.put(new Integer(newKey), new Integer(action)); |
1696 |
keyActionMap.put(new Integer(newKey), new Integer(action)); |
1687 |
} |
1697 |
} |
1688 |
ch = Character.toLowerCase(keyChar); |
1698 |
ch = Character.toLowerCase(keyChar); |
1689 |
newKey = ch | modifierValue; |
1699 |
newKey = ch | modifierValue; |
1690 |
if (action == SWT.NULL) { |
1700 |
if (action == SWT.NULL) { |
1691 |
keyActionMap.remove(new Integer(newKey)); |
1701 |
keyActionMap.remove(new Integer(newKey)); |
1692 |
} |
1702 |
} |
1693 |
else { |
1703 |
else { |
1694 |
keyActionMap.put(new Integer(newKey), new Integer(action)); |
1704 |
keyActionMap.put(new Integer(newKey), new Integer(action)); |
1695 |
} |
1705 |
} |
1696 |
} else { |
1706 |
} else { |
1697 |
if (action == SWT.NULL) { |
1707 |
if (action == SWT.NULL) { |
1698 |
keyActionMap.remove(new Integer(key)); |
1708 |
keyActionMap.remove(new Integer(key)); |
1699 |
} |
1709 |
} |
1700 |
else { |
1710 |
else { |
1701 |
keyActionMap.put(new Integer(key), new Integer(action)); |
1711 |
keyActionMap.put(new Integer(key), new Integer(action)); |
1702 |
} |
1712 |
} |
1703 |
} |
1713 |
} |
1704 |
|
1714 |
|
1705 |
} |
1715 |
} |
1706 |
/** |
1716 |
/** |
1707 |
* Adds a bidirectional segment listener. A BidiSegmentEvent is sent |
1717 |
* Adds a bidirectional segment listener. A BidiSegmentEvent is sent |
1708 |
* whenever a line of text is measured or rendered. The user can |
1718 |
* whenever a line of text is measured or rendered. The user can |
1709 |
* specify text ranges in the line that should be treated as if they |
1719 |
* specify text ranges in the line that should be treated as if they |
1710 |
* had a different direction than the surrounding text. |
1720 |
* had a different direction than the surrounding text. |
1711 |
* This may be used when adjacent segments of right-to-left text should |
1721 |
* This may be used when adjacent segments of right-to-left text should |
1712 |
* not be reordered relative to each other. |
1722 |
* not be reordered relative to each other. |
1713 |
* E.g., Multiple Java string literals in a right-to-left language |
1723 |
* E.g., Multiple Java string literals in a right-to-left language |
1714 |
* should generally remain in logical order to each other, that is, the |
1724 |
* should generally remain in logical order to each other, that is, the |
1715 |
* way they are stored. |
1725 |
* way they are stored. |
1716 |
* <p> |
1726 |
* <p> |
1717 |
* |
1727 |
* |
1718 |
* @param listener the listener |
1728 |
* @param listener the listener |
Lines 1727-1741
Link Here
|
1727 |
* @since 2.0 |
1737 |
* @since 2.0 |
1728 |
*/ |
1738 |
*/ |
1729 |
public void addBidiSegmentListener(BidiSegmentListener listener) { |
1739 |
public void addBidiSegmentListener(BidiSegmentListener listener) { |
1730 |
checkWidget(); |
1740 |
checkWidget(); |
1731 |
if (listener == null) { |
1741 |
if (listener == null) { |
1732 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1742 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1733 |
} |
1743 |
} |
1734 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1744 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1735 |
addListener(LineGetSegments, typedListener); |
1745 |
addListener(LineGetSegments, typedListener); |
1736 |
} |
1746 |
} |
1737 |
/** |
1747 |
/** |
1738 |
* Adds a line background listener. A LineGetBackground event is sent by the |
1748 |
* Adds a line background listener. A LineGetBackground event is sent by the |
1739 |
* widget to determine the background color for a line. |
1749 |
* widget to determine the background color for a line. |
1740 |
* <p> |
1750 |
* <p> |
1741 |
* |
1751 |
* |
Lines 1749-1766
Link Here
|
1749 |
* </ul> |
1759 |
* </ul> |
1750 |
*/ |
1760 |
*/ |
1751 |
public void addLineBackgroundListener(LineBackgroundListener listener) { |
1761 |
public void addLineBackgroundListener(LineBackgroundListener listener) { |
1752 |
checkWidget(); |
1762 |
checkWidget(); |
1753 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1763 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1754 |
if (userLineBackground == false) { |
1764 |
if (userLineBackground == false) { |
1755 |
removeLineBackgroundListener(defaultLineStyler); |
1765 |
removeLineBackgroundListener(defaultLineStyler); |
1756 |
defaultLineStyler.setLineBackground(0, logicalContent.getLineCount(), null); |
1766 |
defaultLineStyler.setLineBackground(0, logicalContent.getLineCount(), null); |
1757 |
userLineBackground = true; |
1767 |
userLineBackground = true; |
1758 |
} |
1768 |
} |
1759 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1769 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1760 |
addListener(LineGetBackground, typedListener); |
1770 |
addListener(LineGetBackground, typedListener); |
1761 |
} |
1771 |
} |
1762 |
/** |
1772 |
/** |
1763 |
* Adds a line style listener. A LineGetStyle event is sent by the widget to |
1773 |
* Adds a line style listener. A LineGetStyle event is sent by the widget to |
1764 |
* determine the styles for a line. |
1774 |
* determine the styles for a line. |
1765 |
* <p> |
1775 |
* <p> |
1766 |
* |
1776 |
* |
Lines 1774-1793
Link Here
|
1774 |
* </ul> |
1784 |
* </ul> |
1775 |
*/ |
1785 |
*/ |
1776 |
public void addLineStyleListener(LineStyleListener listener) { |
1786 |
public void addLineStyleListener(LineStyleListener listener) { |
1777 |
checkWidget(); |
1787 |
checkWidget(); |
1778 |
if (listener == null) { |
1788 |
if (listener == null) { |
1779 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1789 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1780 |
} |
1790 |
} |
1781 |
if (userLineStyle == false) { |
1791 |
if (userLineStyle == false) { |
1782 |
removeLineStyleListener(defaultLineStyler); |
1792 |
removeLineStyleListener(defaultLineStyler); |
1783 |
defaultLineStyler.setStyleRange(null); |
1793 |
defaultLineStyler.setStyleRange(null); |
1784 |
userLineStyle = true; |
1794 |
userLineStyle = true; |
1785 |
} |
1795 |
} |
1786 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1796 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1787 |
addListener(LineGetStyle, typedListener); |
1797 |
addListener(LineGetStyle, typedListener); |
1788 |
} |
1798 |
} |
1789 |
/** |
1799 |
/** |
1790 |
* Adds a modify listener. A Modify event is sent by the widget when the widget text |
1800 |
* Adds a modify listener. A Modify event is sent by the widget when the widget text |
1791 |
* has changed. |
1801 |
* has changed. |
1792 |
* <p> |
1802 |
* <p> |
1793 |
* |
1803 |
* |
Lines 1801-1815
Link Here
|
1801 |
* </ul> |
1811 |
* </ul> |
1802 |
*/ |
1812 |
*/ |
1803 |
public void addModifyListener(ModifyListener modifyListener) { |
1813 |
public void addModifyListener(ModifyListener modifyListener) { |
1804 |
checkWidget(); |
1814 |
checkWidget(); |
1805 |
if (modifyListener == null) { |
1815 |
if (modifyListener == null) { |
1806 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1816 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1807 |
} |
1817 |
} |
1808 |
TypedListener typedListener = new TypedListener(modifyListener); |
1818 |
TypedListener typedListener = new TypedListener(modifyListener); |
1809 |
addListener(SWT.Modify, typedListener); |
1819 |
addListener(SWT.Modify, typedListener); |
1810 |
} |
1820 |
} |
1811 |
/** |
1821 |
/** |
1812 |
* Adds a selection listener. A Selection event is sent by the widget when the |
1822 |
* Adds a selection listener. A Selection event is sent by the widget when the |
1813 |
* selection has changed. |
1823 |
* selection has changed. |
1814 |
* <p> |
1824 |
* <p> |
1815 |
* |
1825 |
* |
Lines 1823-1839
Link Here
|
1823 |
* </ul> |
1833 |
* </ul> |
1824 |
*/ |
1834 |
*/ |
1825 |
public void addSelectionListener(SelectionListener listener) { |
1835 |
public void addSelectionListener(SelectionListener listener) { |
1826 |
checkWidget(); |
1836 |
checkWidget(); |
1827 |
if (listener == null) { |
1837 |
if (listener == null) { |
1828 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1838 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1829 |
} |
1839 |
} |
1830 |
TypedListener typedListener = new TypedListener(listener); |
1840 |
TypedListener typedListener = new TypedListener(listener); |
1831 |
addListener(SWT.Selection, typedListener); |
1841 |
addListener(SWT.Selection, typedListener); |
1832 |
} |
1842 |
} |
1833 |
/** |
1843 |
/** |
1834 |
* Adds a verify key listener. A VerifyKey event is sent by the widget when a key |
1844 |
* Adds a verify key listener. A VerifyKey event is sent by the widget when a key |
1835 |
* is pressed. The widget ignores the key press if the listener sets the doit field |
1845 |
* is pressed. The widget ignores the key press if the listener sets the doit field |
1836 |
* of the event to false. |
1846 |
* of the event to false. |
1837 |
* <p> |
1847 |
* <p> |
1838 |
* |
1848 |
* |
1839 |
* @param listener the listener |
1849 |
* @param listener the listener |
Lines 1846-1862
Link Here
|
1846 |
* </ul> |
1856 |
* </ul> |
1847 |
*/ |
1857 |
*/ |
1848 |
public void addVerifyKeyListener(VerifyKeyListener listener) { |
1858 |
public void addVerifyKeyListener(VerifyKeyListener listener) { |
1849 |
checkWidget(); |
1859 |
checkWidget(); |
1850 |
if (listener == null) { |
1860 |
if (listener == null) { |
1851 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1861 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1852 |
} |
1862 |
} |
1853 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1863 |
StyledTextListener typedListener = new StyledTextListener(listener); |
1854 |
addListener(VerifyKey, typedListener); |
1864 |
addListener(VerifyKey, typedListener); |
1855 |
} |
1865 |
} |
1856 |
/** |
1866 |
/** |
1857 |
* Adds a verify listener. A Verify event is sent by the widget when the widget text |
1867 |
* Adds a verify listener. A Verify event is sent by the widget when the widget text |
1858 |
* is about to change. The listener can set the event text and the doit field to |
1868 |
* is about to change. The listener can set the event text and the doit field to |
1859 |
* change the text that is set in the widget or to force the widget to ignore the |
1869 |
* change the text that is set in the widget or to force the widget to ignore the |
1860 |
* text change. |
1870 |
* text change. |
1861 |
* <p> |
1871 |
* <p> |
1862 |
* |
1872 |
* |
Lines 1870-1883
Link Here
|
1870 |
* </ul> |
1880 |
* </ul> |
1871 |
*/ |
1881 |
*/ |
1872 |
public void addVerifyListener(VerifyListener verifyListener) { |
1882 |
public void addVerifyListener(VerifyListener verifyListener) { |
1873 |
checkWidget(); |
1883 |
checkWidget(); |
1874 |
if (verifyListener == null) { |
1884 |
if (verifyListener == null) { |
1875 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1885 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1876 |
} |
1886 |
} |
1877 |
TypedListener typedListener = new TypedListener(verifyListener); |
1887 |
TypedListener typedListener = new TypedListener(verifyListener); |
1878 |
addListener(SWT.Verify, typedListener); |
1888 |
addListener(SWT.Verify, typedListener); |
1879 |
} |
1889 |
} |
1880 |
/** |
1890 |
/** |
1881 |
* Appends a string to the text at the end of the widget. |
1891 |
* Appends a string to the text at the end of the widget. |
1882 |
* <p> |
1892 |
* <p> |
1883 |
* |
1893 |
* |
Lines 1892-1927
Link Here
|
1892 |
* </ul> |
1902 |
* </ul> |
1893 |
*/ |
1903 |
*/ |
1894 |
public void append(String string) { |
1904 |
public void append(String string) { |
1895 |
checkWidget(); |
1905 |
checkWidget(); |
1896 |
if (string == null) { |
1906 |
if (string == null) { |
1897 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1907 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
1898 |
} |
1908 |
} |
1899 |
int lastChar = Math.max(getCharCount(), 0); |
1909 |
int lastChar = Math.max(getCharCount(), 0); |
1900 |
replaceTextRange(lastChar, 0, string); |
1910 |
replaceTextRange(lastChar, 0, string); |
1901 |
} |
1911 |
} |
1902 |
/** |
1912 |
/** |
1903 |
* Calculates the width of the widest visible line. |
1913 |
* Calculates the width of the widest visible line. |
1904 |
*/ |
1914 |
*/ |
1905 |
void calculateContentWidth() { |
1915 |
void calculateContentWidth() { |
1906 |
if (lineHeight != 0) { |
1916 |
if (lineHeight != 0) { |
1907 |
lineCache = getLineCache(content); |
1917 |
lineCache = getLineCache(content); |
1908 |
lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); |
1918 |
lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); |
1909 |
} |
1919 |
} |
1910 |
} |
1920 |
} |
1911 |
/** |
1921 |
/** |
1912 |
* Calculates the scroll bars |
1922 |
* Calculates the scroll bars |
1913 |
*/ |
1923 |
*/ |
1914 |
void calculateScrollBars() { |
1924 |
void calculateScrollBars() { |
1915 |
ScrollBar horizontalBar = getHorizontalBar(); |
1925 |
ScrollBar horizontalBar = getHorizontalBar(); |
1916 |
ScrollBar verticalBar = getVerticalBar(); |
1926 |
ScrollBar verticalBar = getVerticalBar(); |
1917 |
|
1927 |
|
1918 |
setScrollBars(); |
1928 |
setScrollBars(); |
1919 |
if (verticalBar != null) { |
1929 |
if (verticalBar != null) { |
1920 |
verticalBar.setIncrement(getVerticalIncrement()); |
1930 |
verticalBar.setIncrement(getVerticalIncrement()); |
1921 |
} |
1931 |
} |
1922 |
if (horizontalBar != null) { |
1932 |
if (horizontalBar != null) { |
1923 |
horizontalBar.setIncrement(getHorizontalIncrement()); |
1933 |
horizontalBar.setIncrement(getHorizontalIncrement()); |
1924 |
} |
1934 |
} |
1925 |
} |
1935 |
} |
1926 |
/** |
1936 |
/** |
1927 |
* Calculates the top index based on the current vertical scroll offset. |
1937 |
* Calculates the top index based on the current vertical scroll offset. |
Lines 1930-2026
Link Here
|
1930 |
* The top index starts at 0. |
1940 |
* The top index starts at 0. |
1931 |
*/ |
1941 |
*/ |
1932 |
void calculateTopIndex() { |
1942 |
void calculateTopIndex() { |
1933 |
int oldTopIndex = topIndex; |
1943 |
int oldTopIndex = topIndex; |
1934 |
int verticalIncrement = getVerticalIncrement(); |
1944 |
int verticalIncrement = getVerticalIncrement(); |
1935 |
int clientAreaHeight = getClientArea().height; |
1945 |
int clientAreaHeight = getClientArea().height; |
1936 |
|
1946 |
|
1937 |
if (verticalIncrement == 0) { |
1947 |
if (verticalIncrement == 0) { |
1938 |
return; |
1948 |
return; |
1939 |
} |
1949 |
} |
1940 |
topIndex = Compatibility.ceil(verticalScrollOffset, verticalIncrement); |
1950 |
topIndex = Compatibility.ceil(verticalScrollOffset, verticalIncrement); |
1941 |
// Set top index to partially visible top line if no line is fully |
1951 |
// Set top index to partially visible top line if no line is fully |
1942 |
// visible but at least some of the widget client area is visible. |
1952 |
// visible but at least some of the widget client area is visible. |
1943 |
// Fixes bug 15088. |
1953 |
// Fixes bug 15088. |
1944 |
if (topIndex > 0) { |
1954 |
if (topIndex > 0) { |
1945 |
if (clientAreaHeight > 0) { |
1955 |
if (clientAreaHeight > 0) { |
1946 |
int bottomPixel = verticalScrollOffset + clientAreaHeight; |
1956 |
int bottomPixel = verticalScrollOffset + clientAreaHeight; |
1947 |
int fullLineTopPixel = topIndex * verticalIncrement; |
1957 |
int fullLineTopPixel = topIndex * verticalIncrement; |
1948 |
int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; |
1958 |
int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; |
1949 |
// set top index to partially visible line if no line fully fits in |
1959 |
// set top index to partially visible line if no line fully fits in |
1950 |
// client area or if space is available but not used (the latter should |
1960 |
// client area or if space is available but not used (the latter should |
1951 |
// never happen because we use claimBottomFreeSpace) |
1961 |
// never happen because we use claimBottomFreeSpace) |
1952 |
if (fullLineVisibleHeight < verticalIncrement) { |
1962 |
if (fullLineVisibleHeight < verticalIncrement) { |
1953 |
topIndex--; |
1963 |
topIndex--; |
1954 |
} |
1964 |
} |
1955 |
} |
1965 |
} |
1956 |
else |
1966 |
else |
1957 |
if (topIndex >= content.getLineCount()) { |
1967 |
if (topIndex >= content.getLineCount()) { |
1958 |
topIndex = content.getLineCount() - 1; |
1968 |
topIndex = content.getLineCount() - 1; |
1959 |
} |
1969 |
} |
1960 |
} |
1970 |
} |
1961 |
if (topIndex != oldTopIndex) { |
1971 |
if (topIndex != oldTopIndex) { |
1962 |
topOffset = content.getOffsetAtLine(topIndex); |
1972 |
topOffset = content.getOffsetAtLine(topIndex); |
1963 |
lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); |
1973 |
lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); |
1964 |
setHorizontalScrollBar(); |
1974 |
setHorizontalScrollBar(); |
1965 |
} |
1975 |
} |
1966 |
} |
1976 |
} |
1967 |
/** |
1977 |
/** |
1968 |
* Hides the scroll bars if widget is created in single line mode. |
1978 |
* Hides the scroll bars if widget is created in single line mode. |
1969 |
*/ |
1979 |
*/ |
1970 |
static int checkStyle(int style) { |
1980 |
static int checkStyle(int style) { |
1971 |
if ((style & SWT.SINGLE) != 0) { |
1981 |
if ((style & SWT.SINGLE) != 0) { |
1972 |
style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); |
1982 |
style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); |
1973 |
} |
1983 |
} |
1974 |
return style; |
1984 |
return style; |
1975 |
} |
1985 |
} |
1976 |
/** |
1986 |
/** |
1977 |
* Scrolls down the text to use new space made available by a resize or by |
1987 |
* Scrolls down the text to use new space made available by a resize or by |
1978 |
* deleted lines. |
1988 |
* deleted lines. |
1979 |
*/ |
1989 |
*/ |
1980 |
void claimBottomFreeSpace() { |
1990 |
void claimBottomFreeSpace() { |
1981 |
int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - getClientArea().height); |
1991 |
int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - getClientArea().height); |
1982 |
|
1992 |
|
1983 |
if (newVerticalOffset < verticalScrollOffset) { |
1993 |
if (newVerticalOffset < verticalScrollOffset) { |
1984 |
// Scroll up so that empty lines below last text line are used. |
1994 |
// Scroll up so that empty lines below last text line are used. |
1985 |
// Fixes 1GEYJM0 |
1995 |
// Fixes 1GEYJM0 |
1986 |
setVerticalScrollOffset(newVerticalOffset, true); |
1996 |
setVerticalScrollOffset(newVerticalOffset, true); |
1987 |
} |
1997 |
} |
1988 |
} |
1998 |
} |
1989 |
/** |
1999 |
/** |
1990 |
* Scrolls text to the right to use new space made available by a resize. |
2000 |
* Scrolls text to the right to use new space made available by a resize. |
1991 |
*/ |
2001 |
*/ |
1992 |
void claimRightFreeSpace() { |
2002 |
void claimRightFreeSpace() { |
1993 |
int newHorizontalOffset = Math.max(0, lineCache.getWidth() - (getClientArea().width - leftMargin - rightMargin)); |
2003 |
int newHorizontalOffset = Math.max(0, lineCache.getWidth() - (getClientArea().width - leftMargin - rightMargin)); |
1994 |
|
2004 |
|
1995 |
if (newHorizontalOffset < horizontalScrollOffset) { |
2005 |
if (newHorizontalOffset < horizontalScrollOffset) { |
1996 |
// item is no longer drawn past the right border of the client area |
2006 |
// item is no longer drawn past the right border of the client area |
1997 |
// align the right end of the item with the right border of the |
2007 |
// align the right end of the item with the right border of the |
1998 |
// client area (window is scrolled right). |
2008 |
// client area (window is scrolled right). |
1999 |
scrollHorizontalBar(newHorizontalOffset - horizontalScrollOffset); |
2009 |
scrollHorizontalBar(newHorizontalOffset - horizontalScrollOffset); |
2000 |
} |
2010 |
} |
2001 |
} |
2011 |
} |
2002 |
/** |
2012 |
/** |
2003 |
* Clears the widget margin. |
2013 |
* Clears the widget margin. |
2004 |
* |
2014 |
* |
2005 |
* @param gc GC to render on |
2015 |
* @param gc GC to render on |
2006 |
* @param background background color to use for clearing the margin |
2016 |
* @param background background color to use for clearing the margin |
2007 |
* @param clientArea widget client area dimensions |
2017 |
* @param clientArea widget client area dimensions |
2008 |
* @param renderHeight height in pixel of the rendered lines |
2018 |
* @param renderHeight height in pixel of the rendered lines |
2009 |
*/ |
2019 |
*/ |
2010 |
void clearMargin(GC gc, Color background, Rectangle clientArea, int renderHeight) { |
2020 |
void clearMargin(GC gc, Color background, Rectangle clientArea, int renderHeight) { |
2011 |
if (renderHeight + topMargin <= 0) { |
2021 |
if (renderHeight + topMargin <= 0) { |
2012 |
return; |
2022 |
return; |
2013 |
} |
2023 |
} |
2014 |
// clear the margin background |
2024 |
// clear the margin background |
2015 |
gc.setBackground(background); |
2025 |
gc.setBackground(background); |
2016 |
gc.fillRectangle(0, 0, clientArea.width, topMargin); |
2026 |
gc.fillRectangle(0, 0, clientArea.width, topMargin); |
2017 |
gc.fillRectangle(0, 0, leftMargin, renderHeight + topMargin); |
2027 |
gc.fillRectangle(0, 0, leftMargin, renderHeight + topMargin); |
2018 |
gc.fillRectangle( |
2028 |
gc.fillRectangle( |
2019 |
0, clientArea.height - bottomMargin, |
2029 |
0, clientArea.height - bottomMargin, |
2020 |
clientArea.width, bottomMargin); |
2030 |
clientArea.width, bottomMargin); |
2021 |
gc.fillRectangle( |
2031 |
gc.fillRectangle( |
2022 |
clientArea.width - rightMargin, 0, |
2032 |
clientArea.width - rightMargin, 0, |
2023 |
rightMargin, renderHeight + topMargin); |
2033 |
rightMargin, renderHeight + topMargin); |
2024 |
} |
2034 |
} |
2025 |
/** |
2035 |
/** |
2026 |
* Removes the widget selection. |
2036 |
* Removes the widget selection. |
Lines 2029-2052
Link Here
|
2029 |
* @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. |
2039 |
* @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. |
2030 |
*/ |
2040 |
*/ |
2031 |
void clearSelection(boolean sendEvent) { |
2041 |
void clearSelection(boolean sendEvent) { |
2032 |
int selectionStart = selection.x; |
2042 |
int selectionStart = selection.x; |
2033 |
int selectionEnd = selection.y; |
2043 |
int selectionEnd = selection.y; |
2034 |
int length = content.getCharCount(); |
2044 |
int length = content.getCharCount(); |
2035 |
|
2045 |
|
2036 |
resetSelection(); |
2046 |
resetSelection(); |
2037 |
// redraw old selection, if any |
2047 |
// redraw old selection, if any |
2038 |
if (selectionEnd - selectionStart > 0) { |
2048 |
if (selectionEnd - selectionStart > 0) { |
2039 |
// called internally to remove selection after text is removed |
2049 |
// called internally to remove selection after text is removed |
2040 |
// therefore make sure redraw range is valid. |
2050 |
// therefore make sure redraw range is valid. |
2041 |
int redrawStart = Math.min(selectionStart, length); |
2051 |
int redrawStart = Math.min(selectionStart, length); |
2042 |
int redrawEnd = Math.min(selectionEnd, length); |
2052 |
int redrawEnd = Math.min(selectionEnd, length); |
2043 |
if (redrawEnd - redrawStart > 0) { |
2053 |
if (redrawEnd - redrawStart > 0) { |
2044 |
internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); |
2054 |
internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); |
2045 |
} |
2055 |
} |
2046 |
if (sendEvent == true) { |
2056 |
if (sendEvent == true) { |
2047 |
sendSelectionEvent(); |
2057 |
sendSelectionEvent(); |
2048 |
} |
2058 |
} |
2049 |
} |
2059 |
} |
2050 |
} |
2060 |
} |
2051 |
/** |
2061 |
/** |
2052 |
* Computes the preferred size. |
2062 |
* Computes the preferred size. |
Lines 2057-2133
Link Here
|
2057 |
* </ul> |
2067 |
* </ul> |
2058 |
*/ |
2068 |
*/ |
2059 |
public Point computeSize (int wHint, int hHint, boolean changed) { |
2069 |
public Point computeSize (int wHint, int hHint, boolean changed) { |
2060 |
checkWidget(); |
2070 |
checkWidget(); |
2061 |
int count, width, height; |
2071 |
int count, width, height; |
2062 |
boolean singleLine = (getStyle() & SWT.SINGLE) != 0; |
2072 |
boolean singleLine = (getStyle() & SWT.SINGLE) != 0; |
2063 |
|
2073 |
|
2064 |
if (singleLine) { |
2074 |
if (singleLine) { |
2065 |
count = 1; |
2075 |
count = 1; |
2066 |
} else { |
2076 |
} else { |
2067 |
count = content.getLineCount(); |
2077 |
count = content.getLineCount(); |
2068 |
} |
2078 |
} |
2069 |
if (wHint != SWT.DEFAULT) { |
2079 |
if (wHint != SWT.DEFAULT) { |
2070 |
width = wHint; |
2080 |
width = wHint; |
2071 |
} |
2081 |
} |
2072 |
else { |
2082 |
else { |
2073 |
width = DEFAULT_WIDTH; |
2083 |
width = DEFAULT_WIDTH; |
2074 |
} |
2084 |
} |
2075 |
|
2085 |
|
2076 |
if (wordWrap) { |
2086 |
if (wordWrap) { |
2077 |
if (((WrappedContent) content).getVisualLineCount() != 0) { |
2087 |
if (((WrappedContent) content).getVisualLineCount() != 0) { |
2078 |
// lines have already been wrapped to a specific width. |
2088 |
// lines have already been wrapped to a specific width. |
2079 |
// use existing line count. fixes bug 9191 |
2089 |
// use existing line count. fixes bug 9191 |
2080 |
if (wHint == SWT.DEFAULT) { |
2090 |
if (wHint == SWT.DEFAULT) { |
2081 |
width = lineCache.getWidth(); |
2091 |
width = lineCache.getWidth(); |
2082 |
} else { |
2092 |
} else { |
2083 |
((WrappedContent) content).wrapLines(width); |
2093 |
((WrappedContent) content).wrapLines(width); |
2084 |
// caret may be on a different line after a rewrap |
2094 |
// caret may be on a different line after a rewrap |
2085 |
setCaretLocation(); |
2095 |
setCaretLocation(); |
2086 |
} |
2096 |
} |
2087 |
if (singleLine == false) { |
2097 |
if (singleLine == false) { |
2088 |
count = content.getLineCount(); |
2098 |
count = content.getLineCount(); |
2089 |
} |
2099 |
} |
2090 |
} |
2100 |
} |
2091 |
else { |
2101 |
else { |
2092 |
if (singleLine == false) { |
2102 |
if (singleLine == false) { |
2093 |
((WrappedContent) content).wrapLines(width); |
2103 |
((WrappedContent) content).wrapLines(width); |
2094 |
// caret may be on a different line after a rewrap |
2104 |
// caret may be on a different line after a rewrap |
2095 |
setCaretLocation(); |
2105 |
setCaretLocation(); |
2096 |
count = content.getLineCount(); |
2106 |
count = content.getLineCount(); |
2097 |
} |
2107 |
} |
2098 |
} |
2108 |
} |
2099 |
} |
2109 |
} |
2100 |
else if (wHint == SWT.DEFAULT) { |
2110 |
else if (wHint == SWT.DEFAULT) { |
2101 |
// Only calculate what can actually be displayed. |
2111 |
// Only calculate what can actually be displayed. |
2102 |
// Do this because measuring each text line is a |
2112 |
// Do this because measuring each text line is a |
2103 |
// time-consuming process. |
2113 |
// time-consuming process. |
2104 |
int visibleCount = Math.min (count, getDisplay().getBounds().height / lineHeight); |
2114 |
int visibleCount = Math.min (count, getDisplay().getBounds().height / lineHeight); |
2105 |
lineCache.calculate(0, visibleCount); |
2115 |
lineCache.calculate(0, visibleCount); |
2106 |
width = lineCache.getWidth() + leftMargin + rightMargin; |
2116 |
width = lineCache.getWidth() + leftMargin + rightMargin; |
2107 |
} |
2117 |
} |
2108 |
if (hHint != SWT.DEFAULT) { |
2118 |
if (hHint != SWT.DEFAULT) { |
2109 |
height = hHint; |
2119 |
height = hHint; |
2110 |
} |
2120 |
} |
2111 |
else { |
2121 |
else { |
2112 |
height = count * lineHeight + topMargin + bottomMargin; |
2122 |
height = count * lineHeight + topMargin + bottomMargin; |
2113 |
} |
2123 |
} |
2114 |
// Use default values if no text is defined. |
2124 |
// Use default values if no text is defined. |
2115 |
if (width == 0) { |
2125 |
if (width == 0) { |
2116 |
width = DEFAULT_WIDTH; |
2126 |
width = DEFAULT_WIDTH; |
2117 |
} |
2127 |
} |
2118 |
if (height == 0) { |
2128 |
if (height == 0) { |
2119 |
if (singleLine) { |
2129 |
if (singleLine) { |
2120 |
height = lineHeight; |
2130 |
height = lineHeight; |
2121 |
} |
2131 |
} |
2122 |
else { |
2132 |
else { |
2123 |
height = DEFAULT_HEIGHT; |
2133 |
height = DEFAULT_HEIGHT; |
2124 |
} |
2134 |
} |
2125 |
} |
2135 |
} |
2126 |
Rectangle rect = computeTrim(0, 0, width, height); |
2136 |
Rectangle rect = computeTrim(0, 0, width, height); |
2127 |
return new Point (rect.width, rect.height); |
2137 |
return new Point (rect.width, rect.height); |
2128 |
} |
2138 |
} |
2129 |
/** |
2139 |
/** |
2130 |
* Copies the selected text to the clipboard. The text will be put in the |
2140 |
* Copies the selected text to the clipboard. The text will be put in the |
2131 |
* clipboard in plain text format and RTF format. |
2141 |
* clipboard in plain text format and RTF format. |
2132 |
* <p> |
2142 |
* <p> |
2133 |
* |
2143 |
* |
Lines 2137-2271
Link Here
|
2137 |
* </ul> |
2147 |
* </ul> |
2138 |
*/ |
2148 |
*/ |
2139 |
public void copy() { |
2149 |
public void copy() { |
2140 |
checkWidget(); |
2150 |
checkWidget(); |
2141 |
int length = selection.y - selection.x; |
2151 |
int length = selection.y - selection.x; |
2142 |
if (length > 0) { |
2152 |
if (length > 0) { |
2143 |
try { |
2153 |
try { |
2144 |
setClipboardContent(selection.x, length); |
2154 |
setClipboardContent(selection.x, length); |
2145 |
} |
2155 |
} |
2146 |
catch (SWTError error) { |
2156 |
catch (SWTError error) { |
2147 |
// Copy to clipboard failed. This happens when another application |
2157 |
// Copy to clipboard failed. This happens when another application |
2148 |
// is accessing the clipboard while we copy. Ignore the error. |
2158 |
// is accessing the clipboard while we copy. Ignore the error. |
2149 |
// Fixes 1GDQAVN |
2159 |
// Fixes 1GDQAVN |
2150 |
// Rethrow all other errors. Fixes bug 17578. |
2160 |
// Rethrow all other errors. Fixes bug 17578. |
2151 |
if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { |
2161 |
if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { |
2152 |
throw error; |
2162 |
throw error; |
2153 |
} |
2163 |
} |
2154 |
} |
2164 |
} |
2155 |
} |
2165 |
} |
2156 |
} |
2166 |
} |
2157 |
/** |
2167 |
/** |
2158 |
* Returns a string that uses only the line delimiter specified by the |
2168 |
* Returns a string that uses only the line delimiter specified by the |
2159 |
* StyledTextContent implementation. |
2169 |
* StyledTextContent implementation. |
2160 |
* Returns only the first line if the widget has the SWT.SINGLE style. |
2170 |
* Returns only the first line if the widget has the SWT.SINGLE style. |
2161 |
* <p> |
2171 |
* <p> |
2162 |
* |
2172 |
* |
2163 |
* @param text the text that may have line delimiters that don't |
2173 |
* @param text the text that may have line delimiters that don't |
2164 |
* match the model line delimiter. Possible line delimiters |
2174 |
* match the model line delimiter. Possible line delimiters |
2165 |
* are CR ('\r'), LF ('\n'), CR/LF ("\r\n") |
2175 |
* are CR ('\r'), LF ('\n'), CR/LF ("\r\n") |
2166 |
* @return the converted text that only uses the line delimiter |
2176 |
* @return the converted text that only uses the line delimiter |
2167 |
* specified by the model. Returns only the first line if the widget |
2177 |
* specified by the model. Returns only the first line if the widget |
2168 |
* has the SWT.SINGLE style. |
2178 |
* has the SWT.SINGLE style. |
2169 |
*/ |
2179 |
*/ |
2170 |
String getModelDelimitedText(String text) { |
2180 |
String getModelDelimitedText(String text) { |
2171 |
StringBuffer convertedText; |
2181 |
StringBuffer convertedText; |
2172 |
String delimiter = getLineDelimiter(); |
2182 |
String delimiter = getLineDelimiter(); |
2173 |
int length = text.length(); |
2183 |
int length = text.length(); |
2174 |
int crIndex = 0; |
2184 |
int crIndex = 0; |
2175 |
int lfIndex = 0; |
2185 |
int lfIndex = 0; |
2176 |
int i = 0; |
2186 |
int i = 0; |
2177 |
|
2187 |
|
2178 |
if (length == 0) { |
2188 |
if (length == 0) { |
2179 |
return text; |
2189 |
return text; |
2180 |
} |
2190 |
} |
2181 |
convertedText = new StringBuffer(length); |
2191 |
convertedText = new StringBuffer(length); |
2182 |
while (i < length) { |
2192 |
while (i < length) { |
2183 |
if (crIndex != -1) { |
2193 |
if (crIndex != -1) { |
2184 |
crIndex = text.indexOf(SWT.CR, i); |
2194 |
crIndex = text.indexOf(SWT.CR, i); |
2185 |
} |
2195 |
} |
2186 |
if (lfIndex != -1) { |
2196 |
if (lfIndex != -1) { |
2187 |
lfIndex = text.indexOf(SWT.LF, i); |
2197 |
lfIndex = text.indexOf(SWT.LF, i); |
2188 |
} |
2198 |
} |
2189 |
if (lfIndex == -1 && crIndex == -1) { // no more line breaks? |
2199 |
if (lfIndex == -1 && crIndex == -1) { // no more line breaks? |
2190 |
break; |
2200 |
break; |
2191 |
} |
2201 |
} |
2192 |
else // CR occurs before LF or no LF present? |
2202 |
else // CR occurs before LF or no LF present? |
2193 |
if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { |
2203 |
if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { |
2194 |
convertedText.append(text.substring(i, crIndex)); |
2204 |
convertedText.append(text.substring(i, crIndex)); |
2195 |
if (lfIndex == crIndex + 1) { // CR/LF combination? |
2205 |
if (lfIndex == crIndex + 1) { // CR/LF combination? |
2196 |
i = lfIndex + 1; |
2206 |
i = lfIndex + 1; |
2197 |
} |
2207 |
} |
2198 |
else { |
2208 |
else { |
2199 |
i = crIndex + 1; |
2209 |
i = crIndex + 1; |
2200 |
} |
2210 |
} |
2201 |
} |
2211 |
} |
2202 |
else { // LF occurs before CR! |
2212 |
else { // LF occurs before CR! |
2203 |
convertedText.append(text.substring(i, lfIndex)); |
2213 |
convertedText.append(text.substring(i, lfIndex)); |
2204 |
i = lfIndex + 1; |
2214 |
i = lfIndex + 1; |
2205 |
} |
2215 |
} |
2206 |
if (isSingleLine()) { |
2216 |
if (isSingleLine()) { |
2207 |
break; |
2217 |
break; |
2208 |
} |
2218 |
} |
2209 |
convertedText.append(delimiter); |
2219 |
convertedText.append(delimiter); |
2210 |
} |
2220 |
} |
2211 |
// copy remaining text if any and if not in single line mode or no |
2221 |
// copy remaining text if any and if not in single line mode or no |
2212 |
// text copied thus far (because there only is one line) |
2222 |
// text copied thus far (because there only is one line) |
2213 |
if (i < length && (isSingleLine() == false || convertedText.length() == 0)) { |
2223 |
if (i < length && (isSingleLine() == false || convertedText.length() == 0)) { |
2214 |
convertedText.append(text.substring(i)); |
2224 |
convertedText.append(text.substring(i)); |
2215 |
} |
2225 |
} |
2216 |
return convertedText.toString(); |
2226 |
return convertedText.toString(); |
2217 |
} |
2227 |
} |
2218 |
/** |
2228 |
/** |
2219 |
* Creates default key bindings. |
2229 |
* Creates default key bindings. |
2220 |
*/ |
2230 |
*/ |
2221 |
void createKeyBindings() { |
2231 |
void createKeyBindings() { |
2222 |
// Navigation |
2232 |
// Navigation |
2223 |
setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); |
2233 |
setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); |
2224 |
setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); |
2234 |
setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); |
2225 |
setKeyBinding(SWT.HOME, ST.LINE_START); |
2235 |
setKeyBinding(SWT.HOME, ST.LINE_START); |
2226 |
setKeyBinding(SWT.END, ST.LINE_END); |
2236 |
setKeyBinding(SWT.END, ST.LINE_END); |
2227 |
setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS); |
2237 |
setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS); |
2228 |
setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT); |
2238 |
setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT); |
2229 |
setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); |
2239 |
setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); |
2230 |
setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); |
2240 |
setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); |
2231 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS); |
2241 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS); |
2232 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT); |
2242 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT); |
2233 |
setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); |
2243 |
setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); |
2234 |
setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); |
2244 |
setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); |
2235 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); |
2245 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); |
2236 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); |
2246 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); |
2237 |
// Selection |
2247 |
// Selection |
2238 |
setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); |
2248 |
setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); |
2239 |
setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); |
2249 |
setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); |
2240 |
setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); |
2250 |
setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); |
2241 |
setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); |
2251 |
setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); |
2242 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); |
2252 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); |
2243 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT); |
2253 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT); |
2244 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); |
2254 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); |
2245 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); |
2255 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); |
2246 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); |
2256 |
setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); |
2247 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); |
2257 |
setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); |
2248 |
setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); |
2258 |
setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); |
2249 |
setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); |
2259 |
setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); |
2250 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); |
2260 |
setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); |
2251 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); |
2261 |
setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); |
2252 |
|
2262 |
|
2253 |
// Modification |
2263 |
// Modification |
2254 |
// Cut, Copy, Paste |
2264 |
// Cut, Copy, Paste |
2255 |
setKeyBinding('X' | SWT.MOD1, ST.CUT); |
2265 |
setKeyBinding('X' | SWT.MOD1, ST.CUT); |
2256 |
setKeyBinding('C' | SWT.MOD1, ST.COPY); |
2266 |
setKeyBinding('C' | SWT.MOD1, ST.COPY); |
2257 |
setKeyBinding('V' | SWT.MOD1, ST.PASTE); |
2267 |
setKeyBinding('V' | SWT.MOD1, ST.PASTE); |
2258 |
// Cut, Copy, Paste Wordstar style |
2268 |
// Cut, Copy, Paste Wordstar style |
2259 |
setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); |
2269 |
setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); |
2260 |
setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); |
2270 |
setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); |
2261 |
setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); |
2271 |
setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); |
2262 |
setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); |
2272 |
setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); |
2263 |
|
2273 |
|
2264 |
setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); |
2274 |
setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); |
2265 |
setKeyBinding(SWT.DEL, ST.DELETE_NEXT); |
2275 |
setKeyBinding(SWT.DEL, ST.DELETE_NEXT); |
2266 |
|
2276 |
|
2267 |
// Miscellaneous |
2277 |
// Miscellaneous |
2268 |
setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); |
2278 |
setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); |
2269 |
} |
2279 |
} |
2270 |
/** |
2280 |
/** |
2271 |
* Create the bitmaps to use for the caret in bidi mode. This |
2281 |
* Create the bitmaps to use for the caret in bidi mode. This |
Lines 2273-2309
Link Here
|
2273 |
* font changes (the caret bitmap height needs to match font height). |
2283 |
* font changes (the caret bitmap height needs to match font height). |
2274 |
*/ |
2284 |
*/ |
2275 |
void createCaretBitmaps() { |
2285 |
void createCaretBitmaps() { |
2276 |
int caretWidth = BIDI_CARET_WIDTH; |
2286 |
int caretWidth = BIDI_CARET_WIDTH; |
2277 |
|
2287 |
|
2278 |
Display display = getDisplay(); |
2288 |
Display display = getDisplay(); |
2279 |
if (caretPalette == null) { |
2289 |
if (caretPalette == null) { |
2280 |
caretPalette = new PaletteData(new RGB[] {new RGB (0,0,0), new RGB (255,255,255)}); |
2290 |
caretPalette = new PaletteData(new RGB[] {new RGB (0,0,0), new RGB (255,255,255)}); |
2281 |
} |
2291 |
} |
2282 |
if (leftCaretBitmap != null) { |
2292 |
if (leftCaretBitmap != null) { |
2283 |
leftCaretBitmap.dispose(); |
2293 |
leftCaretBitmap.dispose(); |
2284 |
} |
2294 |
} |
2285 |
ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette); |
2295 |
ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette); |
2286 |
leftCaretBitmap = new Image(display, imageData); |
2296 |
leftCaretBitmap = new Image(display, imageData); |
2287 |
GC gc = new GC (leftCaretBitmap); |
2297 |
GC gc = new GC (leftCaretBitmap); |
2288 |
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); |
2298 |
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); |
2289 |
gc.drawLine(0,0,0,lineHeight); |
2299 |
gc.drawLine(0,0,0,lineHeight); |
2290 |
gc.drawLine(0,0,caretWidth-1,0); |
2300 |
gc.drawLine(0,0,caretWidth-1,0); |
2291 |
gc.drawLine(0,1,1,1); |
2301 |
gc.drawLine(0,1,1,1); |
2292 |
gc.dispose(); |
2302 |
gc.dispose(); |
2293 |
|
2303 |
|
2294 |
if (rightCaretBitmap != null) { |
2304 |
if (rightCaretBitmap != null) { |
2295 |
rightCaretBitmap.dispose(); |
2305 |
rightCaretBitmap.dispose(); |
2296 |
} |
2306 |
} |
2297 |
rightCaretBitmap = new Image(display, imageData); |
2307 |
rightCaretBitmap = new Image(display, imageData); |
2298 |
gc = new GC (rightCaretBitmap); |
2308 |
gc = new GC (rightCaretBitmap); |
2299 |
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); |
2309 |
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); |
2300 |
gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); |
2310 |
gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); |
2301 |
gc.drawLine(0,0,caretWidth-1,0); |
2311 |
gc.drawLine(0,0,caretWidth-1,0); |
2302 |
gc.drawLine(caretWidth-1,1,1,1); |
2312 |
gc.drawLine(caretWidth-1,1,1,1); |
2303 |
gc.dispose(); |
2313 |
gc.dispose(); |
2304 |
} |
2314 |
} |
2305 |
/** |
2315 |
/** |
2306 |
* Moves the selected text to the clipboard. The text will be put in the |
2316 |
* Moves the selected text to the clipboard. The text will be put in the |
2307 |
* clipboard in plain text format and RTF format. |
2317 |
* clipboard in plain text format and RTF format. |
2308 |
* <p> |
2318 |
* <p> |
2309 |
* |
2319 |
* |
Lines 2313-2876
Link Here
|
2313 |
* </ul> |
2323 |
* </ul> |
2314 |
*/ |
2324 |
*/ |
2315 |
public void cut(){ |
2325 |
public void cut(){ |
2316 |
checkWidget(); |
2326 |
checkWidget(); |
2317 |
int length = selection.y - selection.x; |
2327 |
int length = selection.y - selection.x; |
2318 |
|
2328 |
|
2319 |
if (length > 0) { |
2329 |
if (length > 0) { |
2320 |
try { |
2330 |
try { |
2321 |
setClipboardContent(selection.x, length); |
2331 |
setClipboardContent(selection.x, length); |
2322 |
} |
2332 |
} |
2323 |
catch (SWTError error) { |
2333 |
catch (SWTError error) { |
2324 |
// Copy to clipboard failed. This happens when another application |
2334 |
// Copy to clipboard failed. This happens when another application |
2325 |
// is accessing the clipboard while we copy. Ignore the error. |
2335 |
// is accessing the clipboard while we copy. Ignore the error. |
2326 |
// Fixes 1GDQAVN |
2336 |
// Fixes 1GDQAVN |
2327 |
// Rethrow all other errors. Fixes bug 17578. |
2337 |
// Rethrow all other errors. Fixes bug 17578. |
2328 |
if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { |
2338 |
if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { |
2329 |
throw error; |
2339 |
throw error; |
2330 |
} |
2340 |
} |
2331 |
// Abort cut operation if copy to clipboard fails. |
2341 |
// Abort cut operation if copy to clipboard fails. |
2332 |
// Fixes bug 21030. |
2342 |
// Fixes bug 21030. |
2333 |
return; |
2343 |
return; |
2334 |
} |
2344 |
} |
2335 |
doDelete(); |
2345 |
doDelete(); |
2336 |
} |
2346 |
} |
2337 |
} |
2347 |
} |
2338 |
/** |
2348 |
/** |
2339 |
* A mouse move event has occurred. See if we should start autoscrolling. If |
2349 |
* A mouse move event has occurred. See if we should start autoscrolling. If |
2340 |
* the move position is outside of the client area, initiate autoscrolling. |
2350 |
* the move position is outside of the client area, initiate autoscrolling. |
2341 |
* Otherwise, we've moved back into the widget so end autoscrolling. |
2351 |
* Otherwise, we've moved back into the widget so end autoscrolling. |
2342 |
*/ |
2352 |
*/ |
2343 |
void doAutoScroll(Event event) { |
2353 |
void doAutoScroll(Event event) { |
2344 |
Rectangle area = getClientArea(); |
2354 |
Rectangle area = getClientArea(); |
2345 |
|
2355 |
|
2346 |
if (event.y > area.height) { |
2356 |
if (event.y > area.height) { |
2347 |
doAutoScroll(SWT.DOWN); |
2357 |
doAutoScroll(SWT.DOWN); |
2348 |
} |
2358 |
} |
2349 |
else |
2359 |
else |
2350 |
if (event.y < 0) { |
2360 |
if (event.y < 0) { |
2351 |
doAutoScroll(SWT.UP); |
2361 |
doAutoScroll(SWT.UP); |
2352 |
} |
2362 |
} |
2353 |
else |
2363 |
else |
2354 |
if (event.x < leftMargin && wordWrap == false) { |
2364 |
if (event.x < leftMargin && wordWrap == false) { |
2355 |
doAutoScroll(SWT.LEFT); |
2365 |
doAutoScroll(SWT.LEFT); |
2356 |
} |
2366 |
} |
2357 |
else |
2367 |
else |
2358 |
if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) { |
2368 |
if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) { |
2359 |
doAutoScroll(SWT.RIGHT); |
2369 |
doAutoScroll(SWT.RIGHT); |
2360 |
} |
2370 |
} |
2361 |
else { |
2371 |
else { |
2362 |
endAutoScroll(); |
2372 |
endAutoScroll(); |
2363 |
} |
2373 |
} |
2364 |
} |
2374 |
} |
2365 |
/** |
2375 |
/** |
2366 |
* Initiates autoscrolling. |
2376 |
* Initiates autoscrolling. |
2367 |
* <p> |
2377 |
* <p> |
2368 |
* |
2378 |
* |
2369 |
* @param direction SWT.UP, SWT.DOWN, SWT.RIGHT, SWT.LEFT |
2379 |
* @param direction SWT.UP, SWT.DOWN, SWT.RIGHT, SWT.LEFT |
2370 |
*/ |
2380 |
*/ |
2371 |
void doAutoScroll(int direction) { |
2381 |
void doAutoScroll(int direction) { |
2372 |
Runnable timer = null; |
2382 |
Runnable timer = null; |
2373 |
final int TIMER_INTERVAL = 5; |
2383 |
final int TIMER_INTERVAL = 5; |
2374 |
|
2384 |
|
2375 |
// If we're already autoscrolling in the given direction do nothing |
2385 |
// If we're already autoscrolling in the given direction do nothing |
2376 |
if (autoScrollDirection == direction) { |
2386 |
if (autoScrollDirection == direction) { |
2377 |
return; |
2387 |
return; |
2378 |
} |
2388 |
} |
2379 |
|
2389 |
|
2380 |
final Display display = getDisplay(); |
2390 |
final Display display = getDisplay(); |
2381 |
// Set a timer that will simulate the user pressing and holding |
2391 |
// Set a timer that will simulate the user pressing and holding |
2382 |
// down a cursor key (i.e., arrowUp, arrowDown). |
2392 |
// down a cursor key (i.e., arrowUp, arrowDown). |
2383 |
if (direction == SWT.UP) { |
2393 |
if (direction == SWT.UP) { |
2384 |
timer = new Runnable() { |
2394 |
timer = new Runnable() { |
2385 |
public void run() { |
2395 |
public void run() { |
2386 |
if (autoScrollDirection == SWT.UP) { |
2396 |
if (autoScrollDirection == SWT.UP) { |
2387 |
doSelectionLineUp(); |
2397 |
doSelectionLineUp(); |
2388 |
display.timerExec(TIMER_INTERVAL, this); |
2398 |
display.timerExec(TIMER_INTERVAL, this); |
2389 |
} |
2399 |
} |
2390 |
} |
2400 |
} |
2391 |
}; |
2401 |
}; |
2392 |
} else if (direction == SWT.DOWN) { |
2402 |
} else if (direction == SWT.DOWN) { |
2393 |
timer = new Runnable() { |
2403 |
timer = new Runnable() { |
2394 |
public void run() { |
2404 |
public void run() { |
2395 |
if (autoScrollDirection == SWT.DOWN) { |
2405 |
if (autoScrollDirection == SWT.DOWN) { |
2396 |
doSelectionLineDown(); |
2406 |
doSelectionLineDown(); |
2397 |
display.timerExec(TIMER_INTERVAL, this); |
2407 |
display.timerExec(TIMER_INTERVAL, this); |
2398 |
} |
2408 |
} |
2399 |
} |
2409 |
} |
2400 |
}; |
2410 |
}; |
2401 |
} else if (direction == SWT.RIGHT) { |
2411 |
} else if (direction == SWT.RIGHT) { |
2402 |
timer = new Runnable() { |
2412 |
timer = new Runnable() { |
2403 |
public void run() { |
2413 |
public void run() { |
2404 |
if (autoScrollDirection == SWT.RIGHT) { |
2414 |
if (autoScrollDirection == SWT.RIGHT) { |
2405 |
doColumnRight(); |
2415 |
doColumnRight(); |
2406 |
setMouseWordSelectionAnchor(); |
2416 |
setMouseWordSelectionAnchor(); |
2407 |
doSelection(SWT.RIGHT); |
2417 |
doSelection(SWT.RIGHT); |
2408 |
display.timerExec(TIMER_INTERVAL, this); |
2418 |
display.timerExec(TIMER_INTERVAL, this); |
2409 |
} |
2419 |
} |
2410 |
} |
2420 |
} |
2411 |
}; |
2421 |
}; |
2412 |
} else if (direction == SWT.LEFT) { |
2422 |
} else if (direction == SWT.LEFT) { |
2413 |
timer = new Runnable() { |
2423 |
timer = new Runnable() { |
2414 |
public void run() { |
2424 |
public void run() { |
2415 |
if (autoScrollDirection == SWT.LEFT) { |
2425 |
if (autoScrollDirection == SWT.LEFT) { |
2416 |
doColumnLeft(); |
2426 |
doColumnLeft(); |
2417 |
setMouseWordSelectionAnchor(); |
2427 |
setMouseWordSelectionAnchor(); |
2418 |
doSelection(SWT.LEFT); |
2428 |
doSelection(SWT.LEFT); |
2419 |
display.timerExec(TIMER_INTERVAL, this); |
2429 |
display.timerExec(TIMER_INTERVAL, this); |
2420 |
} |
2430 |
} |
2421 |
} |
2431 |
} |
2422 |
}; |
2432 |
}; |
2423 |
} |
2433 |
} |
2424 |
if (timer != null) { |
2434 |
if (timer != null) { |
2425 |
autoScrollDirection = direction; |
2435 |
autoScrollDirection = direction; |
2426 |
display.timerExec(TIMER_INTERVAL, timer); |
2436 |
display.timerExec(TIMER_INTERVAL, timer); |
2427 |
} |
2437 |
} |
2428 |
} |
2438 |
} |
2429 |
/** |
2439 |
/** |
2430 |
* Deletes the previous character. Delete the selected text if any. |
2440 |
* Deletes the previous character. Delete the selected text if any. |
2431 |
* Move the caret in front of the deleted text. |
2441 |
* Move the caret in front of the deleted text. |
2432 |
*/ |
2442 |
*/ |
2433 |
void doBackspace() { |
2443 |
void doBackspace() { |
2434 |
Event event = new Event(); |
2444 |
Event event = new Event(); |
2435 |
event.text = ""; |
2445 |
event.text = ""; |
2436 |
if (selection.x != selection.y) { |
2446 |
if (selection.x != selection.y) { |
2437 |
event.start = selection.x; |
2447 |
event.start = selection.x; |
2438 |
event.end = selection.y; |
2448 |
event.end = selection.y; |
2439 |
sendKeyEvent(event); |
2449 |
sendKeyEvent(event); |
2440 |
} |
2450 |
} |
2441 |
else |
2451 |
else |
2442 |
if (caretOffset > 0) { |
2452 |
if (caretOffset > 0) { |
2443 |
int line = content.getLineAtOffset(caretOffset); |
2453 |
int line = content.getLineAtOffset(caretOffset); |
2444 |
int lineOffset = content.getOffsetAtLine(line); |
2454 |
int lineOffset = content.getOffsetAtLine(line); |
2445 |
|
2455 |
|
2446 |
if (caretOffset == lineOffset) { |
2456 |
if (caretOffset == lineOffset) { |
2447 |
lineOffset = content.getOffsetAtLine(line - 1); |
2457 |
lineOffset = content.getOffsetAtLine(line - 1); |
2448 |
event.start = lineOffset + content.getLine(line - 1).length(); |
2458 |
event.start = lineOffset + content.getLine(line - 1).length(); |
2449 |
event.end = caretOffset; |
2459 |
event.end = caretOffset; |
2450 |
} |
2460 |
} |
2451 |
else { |
2461 |
else { |
2452 |
event.start = caretOffset - 1; |
2462 |
event.start = caretOffset - 1; |
2453 |
event.end = caretOffset; |
2463 |
event.end = caretOffset; |
2454 |
} |
2464 |
} |
2455 |
sendKeyEvent(event); |
2465 |
sendKeyEvent(event); |
2456 |
} |
2466 |
} |
2457 |
} |
2467 |
} |
2458 |
/** |
2468 |
/** |
2459 |
* Moves the caret one character to the left. Do not go to the previous line. |
2469 |
* Moves the caret one character to the left. Do not go to the previous line. |
2460 |
* When in a bidi locale and at a R2L character the caret is moved to the |
2470 |
* When in a bidi locale and at a R2L character the caret is moved to the |
2461 |
* beginning of the R2L segment (visually right) and then one character to the |
2471 |
* beginning of the R2L segment (visually right) and then one character to the |
2462 |
* left (visually left because it's now in a L2R segment). |
2472 |
* left (visually left because it's now in a L2R segment). |
2463 |
*/ |
2473 |
*/ |
2464 |
void doColumnLeft() { |
2474 |
void doColumnLeft() { |
2465 |
int line = content.getLineAtOffset(caretOffset); |
2475 |
int line = content.getLineAtOffset(caretOffset); |
2466 |
int lineOffset = content.getOffsetAtLine(line); |
2476 |
int lineOffset = content.getOffsetAtLine(line); |
2467 |
int offsetInLine = caretOffset - lineOffset; |
2477 |
int offsetInLine = caretOffset - lineOffset; |
2468 |
|
2478 |
|
2469 |
if (isBidi()) { |
2479 |
if (isBidi()) { |
2470 |
String lineText = content.getLine(line); |
2480 |
String lineText = content.getLine(line); |
2471 |
int lineLength = lineText.length(); |
2481 |
int lineLength = lineText.length(); |
2472 |
GC gc = getGC(); |
2482 |
GC gc = getGC(); |
2473 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
2483 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
2474 |
|
2484 |
|
2475 |
if (horizontalScrollOffset > 0 || offsetInLine > 0) { |
2485 |
if (horizontalScrollOffset > 0 || offsetInLine > 0) { |
2476 |
if (offsetInLine < lineLength && bidi.isRightToLeft(offsetInLine)) { |
2486 |
if (offsetInLine < lineLength && bidi.isRightToLeft(offsetInLine)) { |
2477 |
// advance caret logically if in R2L segment (move visually left) |
2487 |
// advance caret logically if in R2L segment (move visually left) |
2478 |
caretOffset++; |
2488 |
caretOffset++; |
2479 |
doSelection(SWT.RIGHT); |
2489 |
doSelection(SWT.RIGHT); |
2480 |
if (caretOffset - lineOffset == lineLength) { |
2490 |
if (caretOffset - lineOffset == lineLength) { |
2481 |
// if the line end is reached in a R2L segment, make the |
2491 |
// if the line end is reached in a R2L segment, make the |
2482 |
// caret position (visual left border) visible before |
2492 |
// caret position (visual left border) visible before |
2483 |
// jumping to segment start |
2493 |
// jumping to segment start |
2484 |
showCaret(); |
2494 |
showCaret(); |
2485 |
} |
2495 |
} |
2486 |
// end of R2L segment reached (visual left side)? |
2496 |
// end of R2L segment reached (visual left side)? |
2487 |
if (bidi.isRightToLeft(caretOffset - lineOffset) == false) { |
2497 |
if (bidi.isRightToLeft(caretOffset - lineOffset) == false) { |
2488 |
if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { |
2498 |
if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { |
2489 |
// make beginning of R2L segment visible before going |
2499 |
// make beginning of R2L segment visible before going |
2490 |
// left, to L2R segment important if R2L segment ends |
2500 |
// left, to L2R segment important if R2L segment ends |
2491 |
// at visual left in order to scroll all the way to the |
2501 |
// at visual left in order to scroll all the way to the |
2492 |
// left. Fixes 1GKM3XS |
2502 |
// left. Fixes 1GKM3XS |
2493 |
showCaret(); |
2503 |
showCaret(); |
2494 |
} |
2504 |
} |
2495 |
// go to beginning of R2L segment (visually end of next L2R |
2505 |
// go to beginning of R2L segment (visually end of next L2R |
2496 |
// segment)/beginning of line |
2506 |
// segment)/beginning of line |
2497 |
caretOffset--; |
2507 |
caretOffset--; |
2498 |
while (caretOffset - lineOffset > 0 && |
2508 |
while (caretOffset - lineOffset > 0 && |
2499 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2509 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2500 |
caretOffset--; |
2510 |
caretOffset--; |
2501 |
} |
2511 |
} |
2502 |
} |
2512 |
} |
2503 |
} |
2513 |
} |
2504 |
else |
2514 |
else |
2505 |
if (offsetInLine == lineLength && |
2515 |
if (offsetInLine == lineLength && |
2506 |
bidi.getTextPosition(lineLength) != XINSET) { |
2516 |
bidi.getTextPosition(lineLength) != XINSET) { |
2507 |
// at logical line end in R2L segment but there's more text (a |
2517 |
// at logical line end in R2L segment but there's more text (a |
2508 |
// L2R segment) go to end of R2L segment (visually left of next |
2518 |
// L2R segment) go to end of R2L segment (visually left of next |
2509 |
// L2R segment)/end of line |
2519 |
// L2R segment)/end of line |
2510 |
caretOffset--; |
2520 |
caretOffset--; |
2511 |
while (caretOffset - lineOffset > 0 && |
2521 |
while (caretOffset - lineOffset > 0 && |
2512 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2522 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2513 |
caretOffset--; |
2523 |
caretOffset--; |
2514 |
} |
2524 |
} |
2515 |
} |
2525 |
} |
2516 |
else |
2526 |
else |
2517 |
if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { |
2527 |
if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { |
2518 |
// decrease caret logically if in L2R segment (move visually left) |
2528 |
// decrease caret logically if in L2R segment (move visually left) |
2519 |
caretOffset--; |
2529 |
caretOffset--; |
2520 |
doSelection(SWT.LEFT); |
2530 |
doSelection(SWT.LEFT); |
2521 |
// end of L2R segment reached (visual left side of preceeding R2L |
2531 |
// end of L2R segment reached (visual left side of preceeding R2L |
2522 |
// segment)? |
2532 |
// segment)? |
2523 |
if (caretOffset - lineOffset > 0 && |
2533 |
if (caretOffset - lineOffset > 0 && |
2524 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2534 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2525 |
// go to beginning of R2L segment (visually start of next L2R |
2535 |
// go to beginning of R2L segment (visually start of next L2R |
2526 |
// segment)/beginning of line |
2536 |
// segment)/beginning of line |
2527 |
caretOffset--; |
2537 |
caretOffset--; |
2528 |
while (caretOffset - lineOffset > 0 && |
2538 |
while (caretOffset - lineOffset > 0 && |
2529 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2539 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2530 |
caretOffset--; |
2540 |
caretOffset--; |
2531 |
} |
2541 |
} |
2532 |
} |
2542 |
} |
2533 |
} |
2543 |
} |
2534 |
// if new caret position is to the left of the client area |
2544 |
// if new caret position is to the left of the client area |
2535 |
if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { |
2545 |
if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { |
2536 |
// scroll to the caret position |
2546 |
// scroll to the caret position |
2537 |
showCaret(); |
2547 |
showCaret(); |
2538 |
} |
2548 |
} |
2539 |
else { |
2549 |
else { |
2540 |
// otherwise just update caret position without scrolling it into view |
2550 |
// otherwise just update caret position without scrolling it into view |
2541 |
setBidiCaretLocation(null); |
2551 |
setBidiCaretLocation(null); |
2542 |
setBidiKeyboardLanguage(); |
2552 |
setBidiKeyboardLanguage(); |
2543 |
} |
2553 |
} |
2544 |
// Beginning of line reached (auto scroll finished) but not scrolled |
2554 |
// Beginning of line reached (auto scroll finished) but not scrolled |
2545 |
// completely to the left? Fixes 1GKM193 |
2555 |
// completely to the left? Fixes 1GKM193 |
2546 |
if (caretOffset - lineOffset == 0 && horizontalScrollOffset > 0 && |
2556 |
if (caretOffset - lineOffset == 0 && horizontalScrollOffset > 0 && |
2547 |
horizontalScrollOffset <= XINSET) { |
2557 |
horizontalScrollOffset <= XINSET) { |
2548 |
scrollHorizontalBar(-horizontalScrollOffset); |
2558 |
scrollHorizontalBar(-horizontalScrollOffset); |
2549 |
} |
2559 |
} |
2550 |
} |
2560 |
} |
2551 |
gc.dispose(); |
2561 |
gc.dispose(); |
2552 |
} |
2562 |
} |
2553 |
else |
2563 |
else |
2554 |
if (offsetInLine > 0) { |
2564 |
if (offsetInLine > 0) { |
2555 |
caretOffset--; |
2565 |
caretOffset--; |
2556 |
showCaret(); |
2566 |
showCaret(); |
2557 |
} |
2567 |
} |
2558 |
} |
2568 |
} |
2559 |
/** |
2569 |
/** |
2560 |
* Moves the caret one character to the right. Do not go to the next line. |
2570 |
* Moves the caret one character to the right. Do not go to the next line. |
2561 |
* When in a bidi locale and at a R2L character the caret is moved to the |
2571 |
* When in a bidi locale and at a R2L character the caret is moved to the |
2562 |
* end of the R2L segment (visually left) and then one character to the |
2572 |
* end of the R2L segment (visually left) and then one character to the |
2563 |
* right (visually right because it's now in a L2R segment). |
2573 |
* right (visually right because it's now in a L2R segment). |
2564 |
*/ |
2574 |
*/ |
2565 |
void doColumnRight() { |
2575 |
void doColumnRight() { |
2566 |
int line = content.getLineAtOffset(caretOffset); |
2576 |
int line = content.getLineAtOffset(caretOffset); |
2567 |
int lineOffset = content.getOffsetAtLine(line); |
2577 |
int lineOffset = content.getOffsetAtLine(line); |
2568 |
int offsetInLine = caretOffset - lineOffset; |
2578 |
int offsetInLine = caretOffset - lineOffset; |
2569 |
String lineText = content.getLine(line); |
2579 |
String lineText = content.getLine(line); |
2570 |
int lineLength = lineText.length(); |
2580 |
int lineLength = lineText.length(); |
2571 |
|
2581 |
|
2572 |
if (isBidi()) { |
2582 |
if (isBidi()) { |
2573 |
GC gc = getGC(); |
2583 |
GC gc = getGC(); |
2574 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
2584 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
2575 |
if (bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || |
2585 |
if (bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || |
2576 |
offsetInLine < lineLength) { |
2586 |
offsetInLine < lineLength) { |
2577 |
if (bidi.isRightToLeft(offsetInLine) == false && |
2587 |
if (bidi.isRightToLeft(offsetInLine) == false && |
2578 |
offsetInLine < lineLength) { |
2588 |
offsetInLine < lineLength) { |
2579 |
// advance caret logically if in L2R segment (move visually right) |
2589 |
// advance caret logically if in L2R segment (move visually right) |
2580 |
caretOffset++; |
2590 |
caretOffset++; |
2581 |
doSelection(SWT.RIGHT); |
2591 |
doSelection(SWT.RIGHT); |
2582 |
// end of L2R segment reached (visual right side)? |
2592 |
// end of L2R segment reached (visual right side)? |
2583 |
if (bidi.isRightToLeft(caretOffset - lineOffset)) { |
2593 |
if (bidi.isRightToLeft(caretOffset - lineOffset)) { |
2584 |
// go to end of R2L segment (visually left of next R2L segment)/ |
2594 |
// go to end of R2L segment (visually left of next R2L segment)/ |
2585 |
// end of line |
2595 |
// end of line |
2586 |
caretOffset++; |
2596 |
caretOffset++; |
2587 |
while (caretOffset < lineOffset + lineLength && |
2597 |
while (caretOffset < lineOffset + lineLength && |
2588 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2598 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2589 |
caretOffset++; |
2599 |
caretOffset++; |
2590 |
} |
2600 |
} |
2591 |
} |
2601 |
} |
2592 |
} |
2602 |
} |
2593 |
else |
2603 |
else |
2594 |
if (offsetInLine > 0 && |
2604 |
if (offsetInLine > 0 && |
2595 |
(bidi.isRightToLeft(offsetInLine) || |
2605 |
(bidi.isRightToLeft(offsetInLine) || |
2596 |
bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || |
2606 |
bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || |
2597 |
offsetInLine < lineLength)) { |
2607 |
offsetInLine < lineLength)) { |
2598 |
// advance caret visually if in R2L segment or logically at line end |
2608 |
// advance caret visually if in R2L segment or logically at line end |
2599 |
// but right end of line is not fully visible yet |
2609 |
// but right end of line is not fully visible yet |
2600 |
caretOffset--; |
2610 |
caretOffset--; |
2601 |
doSelection(SWT.LEFT); |
2611 |
doSelection(SWT.LEFT); |
2602 |
offsetInLine = caretOffset - lineOffset; |
2612 |
offsetInLine = caretOffset - lineOffset; |
2603 |
// end of R2L segment reached (visual right side)? |
2613 |
// end of R2L segment reached (visual right side)? |
2604 |
if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { |
2614 |
if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { |
2605 |
// go to end of R2L segment (visually left of next L2R segment)/ |
2615 |
// go to end of R2L segment (visually left of next L2R segment)/ |
2606 |
// end of line |
2616 |
// end of line |
2607 |
caretOffset++; |
2617 |
caretOffset++; |
2608 |
while (caretOffset < lineOffset + lineLength && |
2618 |
while (caretOffset < lineOffset + lineLength && |
2609 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2619 |
bidi.isRightToLeft(caretOffset - lineOffset)) { |
2610 |
caretOffset++; |
2620 |
caretOffset++; |
2611 |
} |
2621 |
} |
2612 |
} |
2622 |
} |
2613 |
} |
2623 |
} |
2614 |
else |
2624 |
else |
2615 |
if (offsetInLine == 0 && bidi.getTextPosition(0) != bidi.getTextWidth()) { |
2625 |
if (offsetInLine == 0 && bidi.getTextPosition(0) != bidi.getTextWidth()) { |
2616 |
// at logical line start in R2L segment but there's more text (a L2R |
2626 |
// at logical line start in R2L segment but there's more text (a L2R |
2617 |
// segment) go to end of R2L segment (visually left of next L2R |
2627 |
// segment) go to end of R2L segment (visually left of next L2R |
2618 |
// segment)/end of line |
2628 |
// segment)/end of line |
2619 |
caretOffset++; |
2629 |
caretOffset++; |
2620 |
while (caretOffset < lineOffset + lineLength && |
2630 |
while (caretOffset < lineOffset + lineLength && |
2621 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2631 |
bidi.isRightToLeft(caretOffset - lineOffset - 1)) { |
2622 |
caretOffset++; |
2632 |
caretOffset++; |
2623 |
} |
2633 |
} |
2624 |
} |
2634 |
} |
2625 |
offsetInLine = caretOffset - lineOffset; |
2635 |
offsetInLine = caretOffset - lineOffset; |
2626 |
// if new caret position is to the right of the client area |
2636 |
// if new caret position is to the right of the client area |
2627 |
if (bidi.getTextPosition(offsetInLine) >= horizontalScrollOffset) { |
2637 |
if (bidi.getTextPosition(offsetInLine) >= horizontalScrollOffset) { |
2628 |
// scroll to the caret position |
2638 |
// scroll to the caret position |
2629 |
showCaret(); |
2639 |
showCaret(); |
2630 |
} |
2640 |
} |
2631 |
else { |
2641 |
else { |
2632 |
// otherwise just update caret position without scrolling it into view |
2642 |
// otherwise just update caret position without scrolling it into view |
2633 |
setBidiCaretLocation(null); |
2643 |
setBidiCaretLocation(null); |
2634 |
setBidiKeyboardLanguage(); |
2644 |
setBidiKeyboardLanguage(); |
2635 |
} |
2645 |
} |
2636 |
if (offsetInLine > 0 && offsetInLine < lineLength - 1) { |
2646 |
if (offsetInLine > 0 && offsetInLine < lineLength - 1) { |
2637 |
int clientAreaEnd = horizontalScrollOffset + getClientArea().width; |
2647 |
int clientAreaEnd = horizontalScrollOffset + getClientArea().width; |
2638 |
boolean directionChange = bidi.isRightToLeft(offsetInLine - 1) == false && bidi.isRightToLeft(offsetInLine); |
2648 |
boolean directionChange = bidi.isRightToLeft(offsetInLine - 1) == false && bidi.isRightToLeft(offsetInLine); |
2639 |
int textWidth = bidi.getTextWidth() + leftMargin; |
2649 |
int textWidth = bidi.getTextWidth() + leftMargin; |
2640 |
// between L2R and R2L segment and second character of R2L segment is |
2650 |
// between L2R and R2L segment and second character of R2L segment is |
2641 |
// left of right border and logical line end is left of right border |
2651 |
// left of right border and logical line end is left of right border |
2642 |
// but visual line end is not left of right border |
2652 |
// but visual line end is not left of right border |
2643 |
if (directionChange && |
2653 |
if (directionChange && |
2644 |
bidi.isRightToLeft(offsetInLine + 1) && |
2654 |
bidi.isRightToLeft(offsetInLine + 1) && |
2645 |
bidi.getTextPosition(offsetInLine + 1) + leftMargin < clientAreaEnd && |
2655 |
bidi.getTextPosition(offsetInLine + 1) + leftMargin < clientAreaEnd && |
2646 |
bidi.getTextPosition(lineLength) + leftMargin < clientAreaEnd && textWidth > clientAreaEnd) { |
2656 |
bidi.getTextPosition(lineLength) + leftMargin < clientAreaEnd && textWidth > clientAreaEnd) { |
2647 |
// make visual line end visible |
2657 |
// make visual line end visible |
2648 |
scrollHorizontalBar(textWidth - clientAreaEnd); |
2658 |
scrollHorizontalBar(textWidth - clientAreaEnd); |
2649 |
} |
2659 |
} |
2650 |
} |
2660 |
} |
2651 |
} |
2661 |
} |
2652 |
gc.dispose(); |
2662 |
gc.dispose(); |
2653 |
} |
2663 |
} |
2654 |
else |
2664 |
else |
2655 |
if (offsetInLine < lineLength) { |
2665 |
if (offsetInLine < lineLength) { |
2656 |
caretOffset++; |
2666 |
caretOffset++; |
2657 |
showCaret(); |
2667 |
showCaret(); |
2658 |
} |
2668 |
} |
2659 |
} |
2669 |
} |
2660 |
/** |
2670 |
/** |
2661 |
* Replaces the selection with the character or insert the character at the |
2671 |
* Replaces the selection with the character or insert the character at the |
2662 |
* current caret position if no selection exists. |
2672 |
* current caret position if no selection exists. |
2663 |
* If a carriage return was typed replace it with the line break character |
2673 |
* If a carriage return was typed replace it with the line break character |
2664 |
* used by the widget on this platform. |
2674 |
* used by the widget on this platform. |
2665 |
* <p> |
2675 |
* <p> |
2666 |
* |
2676 |
* |
2667 |
* @param key the character typed by the user |
2677 |
* @param key the character typed by the user |
2668 |
*/ |
2678 |
*/ |
2669 |
void doContent(char key) { |
2679 |
void doContent(char key) { |
2670 |
Event event; |
2680 |
Event event; |
2671 |
|
2681 |
|
2672 |
if (textLimit > 0 && |
2682 |
if (textLimit > 0 && |
2673 |
content.getCharCount() - (selection.y - selection.x) >= textLimit) { |
2683 |
content.getCharCount() - (selection.y - selection.x) >= textLimit) { |
2674 |
return; |
2684 |
return; |
2675 |
} |
2685 |
} |
2676 |
event = new Event(); |
2686 |
event = new Event(); |
2677 |
event.start = selection.x; |
2687 |
event.start = selection.x; |
2678 |
event.end = selection.y; |
2688 |
event.end = selection.y; |
2679 |
// replace a CR line break with the widget line break |
2689 |
// replace a CR line break with the widget line break |
2680 |
// CR does not make sense on Windows since most (all?) applications |
2690 |
// CR does not make sense on Windows since most (all?) applications |
2681 |
// don't recognize CR as a line break. |
2691 |
// don't recognize CR as a line break. |
2682 |
if (key == SWT.CR || key == SWT.LF) { |
2692 |
if (key == SWT.CR || key == SWT.LF) { |
2683 |
if (isSingleLine() == false) { |
2693 |
if (isSingleLine() == false) { |
2684 |
event.text = getLineDelimiter(); |
2694 |
event.text = getLineDelimiter(); |
2685 |
} |
2695 |
} |
2686 |
} |
2696 |
} |
2687 |
// no selection and overwrite mode is on and the typed key is not a |
2697 |
// no selection and overwrite mode is on and the typed key is not a |
2688 |
// tab character (tabs are always inserted without overwriting)? |
2698 |
// tab character (tabs are always inserted without overwriting)? |
2689 |
else |
2699 |
else |
2690 |
if (selection.x == selection.y && overwrite == true && key != TAB) { |
2700 |
if (selection.x == selection.y && overwrite == true && key != TAB) { |
2691 |
int lineIndex = content.getLineAtOffset(event.end); |
2701 |
int lineIndex = content.getLineAtOffset(event.end); |
2692 |
int lineOffset = content.getOffsetAtLine(lineIndex); |
2702 |
int lineOffset = content.getOffsetAtLine(lineIndex); |
2693 |
String line = content.getLine(lineIndex); |
2703 |
String line = content.getLine(lineIndex); |
2694 |
// replace character at caret offset if the caret is not at the |
2704 |
// replace character at caret offset if the caret is not at the |
2695 |
// end of the line |
2705 |
// end of the line |
2696 |
if (event.end < lineOffset + line.length()) { |
2706 |
if (event.end < lineOffset + line.length()) { |
2697 |
event.end++; |
2707 |
event.end++; |
2698 |
} |
2708 |
} |
2699 |
event.text = new String(new char[] {key}); |
2709 |
event.text = new String(new char[] {key}); |
2700 |
} |
2710 |
} |
2701 |
else { |
2711 |
else { |
2702 |
event.text = new String(new char[] {key}); |
2712 |
event.text = new String(new char[] {key}); |
2703 |
} |
2713 |
} |
2704 |
if (event.text != null) { |
2714 |
if (event.text != null) { |
2705 |
sendKeyEvent(event); |
2715 |
sendKeyEvent(event); |
2706 |
} |
2716 |
} |
2707 |
} |
2717 |
} |
2708 |
/** |
2718 |
/** |
2709 |
* Moves the caret after the last character of the widget content. |
2719 |
* Moves the caret after the last character of the widget content. |
2710 |
*/ |
2720 |
*/ |
2711 |
void doContentEnd() { |
2721 |
void doContentEnd() { |
2712 |
// place caret at end of first line if receiver is in single |
2722 |
// place caret at end of first line if receiver is in single |
2713 |
// line mode. fixes 4820. |
2723 |
// line mode. fixes 4820. |
2714 |
if (isSingleLine()) { |
2724 |
if (isSingleLine()) { |
2715 |
doLineEnd(); |
2725 |
doLineEnd(); |
2716 |
} |
2726 |
} |
2717 |
else { |
2727 |
else { |
2718 |
int length = content.getCharCount(); |
2728 |
int length = content.getCharCount(); |
2719 |
if (caretOffset < length) { |
2729 |
if (caretOffset < length) { |
2720 |
caretOffset = length; |
2730 |
caretOffset = length; |
2721 |
showCaret(); |
2731 |
showCaret(); |
2722 |
} |
2732 |
} |
2723 |
} |
2733 |
} |
2724 |
} |
2734 |
} |
2725 |
/** |
2735 |
/** |
2726 |
* Moves the caret in front of the first character of the widget content. |
2736 |
* Moves the caret in front of the first character of the widget content. |
2727 |
*/ |
2737 |
*/ |
2728 |
void doContentStart() { |
2738 |
void doContentStart() { |
2729 |
if (caretOffset > 0) { |
2739 |
if (caretOffset > 0) { |
2730 |
caretOffset = 0; |
2740 |
caretOffset = 0; |
2731 |
showCaret(); |
2741 |
showCaret(); |
2732 |
} |
2742 |
} |
2733 |
} |
2743 |
} |
2734 |
/** |
2744 |
/** |
2735 |
* Moves the caret to the start of the selection if a selection exists. |
2745 |
* Moves the caret to the start of the selection if a selection exists. |
2736 |
* Otherwise, if no selection exists move the cursor according to the |
2746 |
* Otherwise, if no selection exists move the cursor according to the |
2737 |
* cursor selection rules. |
2747 |
* cursor selection rules. |
2738 |
* <p> |
2748 |
* <p> |
2739 |
* |
2749 |
* |
2740 |
* @see #doSelectionCursorPrevious |
2750 |
* @see #doSelectionCursorPrevious |
2741 |
*/ |
2751 |
*/ |
2742 |
void doCursorPrevious() { |
2752 |
void doCursorPrevious() { |
2743 |
if (selection.y - selection.x > 0) { |
2753 |
if (selection.y - selection.x > 0) { |
2744 |
int caretLine; |
2754 |
int caretLine; |
2745 |
|
2755 |
|
2746 |
caretOffset = selection.x; |
2756 |
caretOffset = selection.x; |
2747 |
caretLine = getCaretLine(); |
2757 |
caretLine = getCaretLine(); |
2748 |
showCaret(caretLine); |
2758 |
showCaret(caretLine); |
2749 |
} |
2759 |
} |
2750 |
else { |
2760 |
else { |
2751 |
doSelectionCursorPrevious(); |
2761 |
doSelectionCursorPrevious(); |
2752 |
} |
2762 |
} |
2753 |
} |
2763 |
} |
2754 |
/** |
2764 |
/** |
2755 |
* Moves the caret to the end of the selection if a selection exists. |
2765 |
* Moves the caret to the end of the selection if a selection exists. |
2756 |
* Otherwise, if no selection exists move the cursor according to the |
2766 |
* Otherwise, if no selection exists move the cursor according to the |
2757 |
* cursor selection rules. |
2767 |
* cursor selection rules. |
2758 |
* <p> |
2768 |
* <p> |
2759 |
* |
2769 |
* |
2760 |
* @see #doSelectionCursorNext |
2770 |
* @see #doSelectionCursorNext |
2761 |
*/ |
2771 |
*/ |
2762 |
void doCursorNext() { |
2772 |
void doCursorNext() { |
2763 |
if (selection.y - selection.x > 0) { |
2773 |
if (selection.y - selection.x > 0) { |
2764 |
int caretLine; |
2774 |
int caretLine; |
2765 |
|
2775 |
|
2766 |
caretOffset = selection.y; |
2776 |
caretOffset = selection.y; |
2767 |
caretLine = getCaretLine(); |
2777 |
caretLine = getCaretLine(); |
2768 |
showCaret(caretLine); |
2778 |
showCaret(caretLine); |
2769 |
} |
2779 |
} |
2770 |
else { |
2780 |
else { |
2771 |
doSelectionCursorNext(); |
2781 |
doSelectionCursorNext(); |
2772 |
} |
2782 |
} |
2773 |
} |
2783 |
} |
2774 |
/** |
2784 |
/** |
2775 |
* Deletes the next character. Delete the selected text if any. |
2785 |
* Deletes the next character. Delete the selected text if any. |
2776 |
*/ |
2786 |
*/ |
2777 |
void doDelete() { |
2787 |
void doDelete() { |
2778 |
Event event = new Event(); |
2788 |
Event event = new Event(); |
2779 |
|
2789 |
|
2780 |
event.text = ""; |
2790 |
event.text = ""; |
2781 |
if (selection.x != selection.y) { |
2791 |
if (selection.x != selection.y) { |
2782 |
event.start = selection.x; |
2792 |
event.start = selection.x; |
2783 |
event.end = selection.y; |
2793 |
event.end = selection.y; |
2784 |
sendKeyEvent(event); |
2794 |
sendKeyEvent(event); |
2785 |
} |
2795 |
} |
2786 |
else |
2796 |
else |
2787 |
if (caretOffset < content.getCharCount()) { |
2797 |
if (caretOffset < content.getCharCount()) { |
2788 |
int line = content.getLineAtOffset(caretOffset); |
2798 |
int line = content.getLineAtOffset(caretOffset); |
2789 |
int lineOffset = content.getOffsetAtLine(line); |
2799 |
int lineOffset = content.getOffsetAtLine(line); |
2790 |
int lineLength = content.getLine(line).length(); |
2800 |
int lineLength = content.getLine(line).length(); |
2791 |
|
2801 |
|
2792 |
if (caretOffset == lineOffset + lineLength) { |
2802 |
if (caretOffset == lineOffset + lineLength) { |
2793 |
event.start = caretOffset; |
2803 |
event.start = caretOffset; |
2794 |
event.end = content.getOffsetAtLine(line + 1); |
2804 |
event.end = content.getOffsetAtLine(line + 1); |
2795 |
} |
2805 |
} |
2796 |
else { |
2806 |
else { |
2797 |
event.start = caretOffset; |
2807 |
event.start = caretOffset; |
2798 |
event.end = caretOffset + 1; |
2808 |
event.end = caretOffset + 1; |
2799 |
} |
2809 |
} |
2800 |
sendKeyEvent(event); |
2810 |
sendKeyEvent(event); |
2801 |
} |
2811 |
} |
2802 |
} |
2812 |
} |
2803 |
/** |
2813 |
/** |
2804 |
* Moves the caret one line down and to the same character offset relative |
2814 |
* Moves the caret one line down and to the same character offset relative |
2805 |
* to the beginning of the line. Move the caret to the end of the new line |
2815 |
* to the beginning of the line. Move the caret to the end of the new line |
2806 |
* if the new line is shorter than the character offset. |
2816 |
* if the new line is shorter than the character offset. |
2807 |
* |
2817 |
* |
2808 |
* @return index of the new line relative to the first line in the document |
2818 |
* @return index of the new line relative to the first line in the document |
2809 |
*/ |
2819 |
*/ |
2810 |
int doLineDown() { |
2820 |
int doLineDown() { |
2811 |
if (isSingleLine()) { |
2821 |
if (isSingleLine()) { |
2812 |
return 0; |
2822 |
return 0; |
2813 |
} |
2823 |
} |
2814 |
// allow line down action only if receiver is not in single line mode. |
2824 |
// allow line down action only if receiver is not in single line mode. |
2815 |
// fixes 4820. |
2825 |
// fixes 4820. |
2816 |
int caretLine = getCaretLine(); |
2826 |
int caretLine = getCaretLine(); |
2817 |
if (caretLine < content.getLineCount() - 1) { |
2827 |
if (caretLine < content.getLineCount() - 1) { |
2818 |
caretLine++; |
2828 |
caretLine++; |
2819 |
if (isBidi()) { |
2829 |
if (isBidi()) { |
2820 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
2830 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
2821 |
} |
2831 |
} |
2822 |
else { |
2832 |
else { |
2823 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
2833 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
2824 |
} |
2834 |
} |
2825 |
} |
2835 |
} |
2826 |
return caretLine; |
2836 |
return caretLine; |
2827 |
} |
2837 |
} |
2828 |
/** |
2838 |
/** |
2829 |
* Moves the caret to the end of the line. |
2839 |
* Moves the caret to the end of the line. |
2830 |
*/ |
2840 |
*/ |
2831 |
void doLineEnd() { |
2841 |
void doLineEnd() { |
2832 |
int caretLine = getCaretLine(); |
2842 |
int caretLine = getCaretLine(); |
2833 |
int lineOffset = content.getOffsetAtLine(caretLine); |
2843 |
int lineOffset = content.getOffsetAtLine(caretLine); |
2834 |
int lineLength = content.getLine(caretLine).length(); |
2844 |
int lineLength = content.getLine(caretLine).length(); |
2835 |
int lineEndOffset = lineOffset + lineLength; |
2845 |
int lineEndOffset = lineOffset + lineLength; |
2836 |
|
2846 |
|
2837 |
if (caretOffset < lineEndOffset) { |
2847 |
if (caretOffset < lineEndOffset) { |
2838 |
caretOffset = lineEndOffset; |
2848 |
caretOffset = lineEndOffset; |
2839 |
showCaret(); |
2849 |
showCaret(); |
2840 |
} |
2850 |
} |
2841 |
} |
2851 |
} |
2842 |
/** |
2852 |
/** |
2843 |
* Moves the caret to the beginning of the line. |
2853 |
* Moves the caret to the beginning of the line. |
2844 |
*/ |
2854 |
*/ |
2845 |
void doLineStart() { |
2855 |
void doLineStart() { |
2846 |
int caretLine = getCaretLine(); |
2856 |
int caretLine = getCaretLine(); |
2847 |
int lineOffset = content.getOffsetAtLine(caretLine); |
2857 |
int lineOffset = content.getOffsetAtLine(caretLine); |
2848 |
|
2858 |
|
2849 |
if (caretOffset > lineOffset) { |
2859 |
if (caretOffset > lineOffset) { |
2850 |
caretOffset = lineOffset; |
2860 |
caretOffset = lineOffset; |
2851 |
showCaret(caretLine); |
2861 |
showCaret(caretLine); |
2852 |
} |
2862 |
} |
2853 |
} |
2863 |
} |
2854 |
/** |
2864 |
/** |
2855 |
* Moves the caret one line up and to the same character offset relative |
2865 |
* Moves the caret one line up and to the same character offset relative |
2856 |
* to the beginning of the line. Move the caret to the end of the new line |
2866 |
* to the beginning of the line. Move the caret to the end of the new line |
2857 |
* if the new line is shorter than the character offset. |
2867 |
* if the new line is shorter than the character offset. |
2858 |
* |
2868 |
* |
2859 |
* @return index of the new line relative to the first line in the document |
2869 |
* @return index of the new line relative to the first line in the document |
2860 |
*/ |
2870 |
*/ |
2861 |
int doLineUp() { |
2871 |
int doLineUp() { |
2862 |
int caretLine = getCaretLine(); |
2872 |
int caretLine = getCaretLine(); |
2863 |
|
2873 |
|
2864 |
if (caretLine > 0) { |
2874 |
if (caretLine > 0) { |
2865 |
caretLine--; |
2875 |
caretLine--; |
2866 |
if (isBidi()) { |
2876 |
if (isBidi()) { |
2867 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
2877 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
2868 |
} |
2878 |
} |
2869 |
else { |
2879 |
else { |
2870 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
2880 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
2871 |
} |
2881 |
} |
2872 |
} |
2882 |
} |
2873 |
return caretLine; |
2883 |
return caretLine; |
2874 |
} |
2884 |
} |
2875 |
/** |
2885 |
/** |
2876 |
* Moves the caret to the specified location. |
2886 |
* Moves the caret to the specified location. |
Lines 2879-3248
Link Here
|
2879 |
* @param x x location of the new caret position |
2889 |
* @param x x location of the new caret position |
2880 |
* @param y y location of the new caret position |
2890 |
* @param y y location of the new caret position |
2881 |
* @param select the location change is a selection operation. |
2891 |
* @param select the location change is a selection operation. |
2882 |
* include the line delimiter in the selection |
2892 |
* include the line delimiter in the selection |
2883 |
*/ |
2893 |
*/ |
2884 |
void doMouseLocationChange(int x, int y, boolean select) { |
2894 |
void doMouseLocationChange(int x, int y, boolean select) { |
2885 |
int line = (y + verticalScrollOffset) / lineHeight; |
2895 |
int line = (y + verticalScrollOffset) / lineHeight; |
2886 |
int lineCount = content.getLineCount(); |
2896 |
int lineCount = content.getLineCount(); |
2887 |
int newCaretOffset; |
2897 |
int newCaretOffset; |
2888 |
int newCaretLine; |
2898 |
int newCaretLine; |
2889 |
|
2899 |
|
2890 |
if (line > lineCount - 1) { |
2900 |
if (line > lineCount - 1) { |
2891 |
line = lineCount - 1; |
2901 |
line = lineCount - 1; |
2892 |
} |
2902 |
} |
2893 |
// allow caret to be placed below first line only if receiver is |
2903 |
// allow caret to be placed below first line only if receiver is |
2894 |
// not in single line mode. fixes 4820. |
2904 |
// not in single line mode. fixes 4820. |
2895 |
if (line < 0 || (isSingleLine() && line > 0)) { |
2905 |
if (line < 0 || (isSingleLine() && line > 0)) { |
2896 |
return; |
2906 |
return; |
2897 |
} |
2907 |
} |
2898 |
if (isBidi()) { |
2908 |
if (isBidi()) { |
2899 |
newCaretOffset = getBidiOffsetAtMouseLocation(x, line); |
2909 |
newCaretOffset = getBidiOffsetAtMouseLocation(x, line); |
2900 |
} |
2910 |
} |
2901 |
else { |
2911 |
else { |
2902 |
newCaretOffset = getOffsetAtMouseLocation(x, line); |
2912 |
newCaretOffset = getOffsetAtMouseLocation(x, line); |
2903 |
} |
2913 |
} |
2904 |
if (mouseDoubleClick) { |
2914 |
if (mouseDoubleClick) { |
2905 |
// double click word select the previous/next word. fixes bug 15610 |
2915 |
// double click word select the previous/next word. fixes bug 15610 |
2906 |
newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); |
2916 |
newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); |
2907 |
} |
2917 |
} |
2908 |
newCaretLine = content.getLineAtOffset(newCaretOffset); |
2918 |
newCaretLine = content.getLineAtOffset(newCaretOffset); |
2909 |
// Is the mouse within the left client area border or on |
2919 |
// Is the mouse within the left client area border or on |
2910 |
// a different line? If not the autoscroll selection |
2920 |
// a different line? If not the autoscroll selection |
2911 |
// could be incorrectly reset. Fixes 1GKM3XS |
2921 |
// could be incorrectly reset. Fixes 1GKM3XS |
2912 |
if (y >= 0 && y < getClientArea().height && |
2922 |
if (y >= 0 && y < getClientArea().height && |
2913 |
(x >= 0 || newCaretLine != content.getLineAtOffset(caretOffset))) { |
2923 |
(x >= 0 || newCaretLine != content.getLineAtOffset(caretOffset))) { |
2914 |
if (newCaretOffset != caretOffset) { |
2924 |
if (newCaretOffset != caretOffset) { |
2915 |
caretOffset = newCaretOffset; |
2925 |
caretOffset = newCaretOffset; |
2916 |
if (select) { |
2926 |
if (select) { |
2917 |
doMouseSelection(); |
2927 |
doMouseSelection(); |
2918 |
} |
2928 |
} |
2919 |
showCaret(); |
2929 |
showCaret(); |
2920 |
} |
2930 |
} |
2921 |
} |
2931 |
} |
2922 |
if (select == false) { |
2932 |
if (select == false) { |
2923 |
clearSelection(true); |
2933 |
clearSelection(true); |
2924 |
} |
2934 |
} |
2925 |
} |
2935 |
} |
2926 |
/** |
2936 |
/** |
2927 |
* Updates the selection based on the caret position |
2937 |
* Updates the selection based on the caret position |
2928 |
*/ |
2938 |
*/ |
2929 |
void doMouseSelection() { |
2939 |
void doMouseSelection() { |
2930 |
if (caretOffset <= selection.x || |
2940 |
if (caretOffset <= selection.x || |
2931 |
(caretOffset > selection.x && |
2941 |
(caretOffset > selection.x && |
2932 |
caretOffset < selection.y && selectionAnchor == selection.x)) { |
2942 |
caretOffset < selection.y && selectionAnchor == selection.x)) { |
2933 |
doSelection(SWT.LEFT); |
2943 |
doSelection(SWT.LEFT); |
2934 |
} |
2944 |
} |
2935 |
else { |
2945 |
else { |
2936 |
doSelection(SWT.RIGHT); |
2946 |
doSelection(SWT.RIGHT); |
2937 |
} |
2947 |
} |
2938 |
} |
2948 |
} |
2939 |
/** |
2949 |
/** |
2940 |
* Returns the offset of the word at the specified offset. |
2950 |
* Returns the offset of the word at the specified offset. |
2941 |
* If the current selection extends from high index to low index |
2951 |
* If the current selection extends from high index to low index |
2942 |
* (i.e., right to left, or caret is at left border of selecton on |
2952 |
* (i.e., right to left, or caret is at left border of selecton on |
2943 |
* non-bidi platforms) the start offset of the word preceeding the |
2953 |
* non-bidi platforms) the start offset of the word preceeding the |
2944 |
* selection is returned. If the current selection extends from |
2954 |
* selection is returned. If the current selection extends from |
2945 |
* low index to high index the end offset of the word following |
2955 |
* low index to high index the end offset of the word following |
2946 |
* the selection is returned. |
2956 |
* the selection is returned. |
2947 |
* |
2957 |
* |
2948 |
* @param x mouse x location |
2958 |
* @param x mouse x location |
2949 |
* @param newCaretOffset caret offset of the mouse cursor location |
2959 |
* @param newCaretOffset caret offset of the mouse cursor location |
2950 |
* @param line line index of the mouse cursor location |
2960 |
* @param line line index of the mouse cursor location |
2951 |
*/ |
2961 |
*/ |
2952 |
int doMouseWordSelect(int x, int newCaretOffset, int line) { |
2962 |
int doMouseWordSelect(int x, int newCaretOffset, int line) { |
2953 |
int wordOffset; |
2963 |
int wordOffset; |
2954 |
|
2964 |
|
2955 |
// flip selection anchor based on word selection direction from |
2965 |
// flip selection anchor based on word selection direction from |
2956 |
// base double click. Always do this here (and don't rely on doAutoScroll) |
2966 |
// base double click. Always do this here (and don't rely on doAutoScroll) |
2957 |
// because auto scroll only does not cover all possible mouse selections |
2967 |
// because auto scroll only does not cover all possible mouse selections |
2958 |
// (e.g., mouse x < 0 && mouse y > caret line y) |
2968 |
// (e.g., mouse x < 0 && mouse y > caret line y) |
2959 |
if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) { |
2969 |
if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) { |
2960 |
selectionAnchor = doubleClickSelection.y; |
2970 |
selectionAnchor = doubleClickSelection.y; |
2961 |
} |
2971 |
} |
2962 |
else |
2972 |
else |
2963 |
if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) { |
2973 |
if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) { |
2964 |
selectionAnchor = doubleClickSelection.x; |
2974 |
selectionAnchor = doubleClickSelection.x; |
2965 |
} |
2975 |
} |
2966 |
if (x >= 0 && x < getClientArea().width) { |
2976 |
if (x >= 0 && x < getClientArea().width) { |
2967 |
// find the previous/next word |
2977 |
// find the previous/next word |
2968 |
if (caretOffset == selection.x) { |
2978 |
if (caretOffset == selection.x) { |
2969 |
wordOffset = getWordStart(newCaretOffset); |
2979 |
wordOffset = getWordStart(newCaretOffset); |
2970 |
} |
2980 |
} |
2971 |
else { |
2981 |
else { |
2972 |
wordOffset = getWordEndNoSpaces(newCaretOffset); |
2982 |
wordOffset = getWordEndNoSpaces(newCaretOffset); |
2973 |
} |
2983 |
} |
2974 |
// mouse word select only on same line mouse cursor is on |
2984 |
// mouse word select only on same line mouse cursor is on |
2975 |
if (content.getLineAtOffset(wordOffset) == line) { |
2985 |
if (content.getLineAtOffset(wordOffset) == line) { |
2976 |
newCaretOffset = wordOffset; |
2986 |
newCaretOffset = wordOffset; |
2977 |
} |
2987 |
} |
2978 |
} |
2988 |
} |
2979 |
return newCaretOffset; |
2989 |
return newCaretOffset; |
2980 |
} |
2990 |
} |
2981 |
/** |
2991 |
/** |
2982 |
* Scrolls one page down so that the last line (truncated or whole) |
2992 |
* Scrolls one page down so that the last line (truncated or whole) |
2983 |
* of the current page becomes the fully visible top line. |
2993 |
* of the current page becomes the fully visible top line. |
2984 |
* The caret is scrolled the same number of lines so that its location |
2994 |
* The caret is scrolled the same number of lines so that its location |
2985 |
* relative to the top line remains the same. The exception is the end |
2995 |
* relative to the top line remains the same. The exception is the end |
2986 |
* of the text where a full page scroll is not possible. In this case |
2996 |
* of the text where a full page scroll is not possible. In this case |
2987 |
* the caret is moved after the last character. |
2997 |
* the caret is moved after the last character. |
2988 |
* <p> |
2998 |
* <p> |
2989 |
* |
2999 |
* |
2990 |
* @param select whether or not to select the page |
3000 |
* @param select whether or not to select the page |
2991 |
*/ |
3001 |
*/ |
2992 |
void doPageDown(boolean select) { |
3002 |
void doPageDown(boolean select) { |
2993 |
int lineCount = content.getLineCount(); |
3003 |
int lineCount = content.getLineCount(); |
2994 |
int oldColumnX = columnX; |
3004 |
int oldColumnX = columnX; |
2995 |
int caretLine; |
3005 |
int caretLine; |
2996 |
|
3006 |
|
2997 |
// do nothing if in single line mode. fixes 5673 |
3007 |
// do nothing if in single line mode. fixes 5673 |
2998 |
if (isSingleLine()) { |
3008 |
if (isSingleLine()) { |
2999 |
return; |
3009 |
return; |
3000 |
} |
3010 |
} |
3001 |
caretLine = getCaretLine(); |
3011 |
caretLine = getCaretLine(); |
3002 |
if (caretLine < lineCount - 1) { |
3012 |
if (caretLine < lineCount - 1) { |
3003 |
int verticalMaximum = lineCount * getVerticalIncrement(); |
3013 |
int verticalMaximum = lineCount * getVerticalIncrement(); |
3004 |
int pageSize = getClientArea().height; |
3014 |
int pageSize = getClientArea().height; |
3005 |
int scrollLines = Math.min(lineCount - caretLine - 1, getLineCountWhole()); |
3015 |
int scrollLines = Math.min(lineCount - caretLine - 1, getLineCountWhole()); |
3006 |
int scrollOffset; |
3016 |
int scrollOffset; |
3007 |
|
3017 |
|
3008 |
// ensure that scrollLines never gets negative and at leat one |
3018 |
// ensure that scrollLines never gets negative and at leat one |
3009 |
// line is scrolled. fixes bug 5602. |
3019 |
// line is scrolled. fixes bug 5602. |
3010 |
scrollLines = Math.max(1, scrollLines); |
3020 |
scrollLines = Math.max(1, scrollLines); |
3011 |
caretLine += scrollLines; |
3021 |
caretLine += scrollLines; |
3012 |
if (isBidi()) { |
3022 |
if (isBidi()) { |
3013 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
3023 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
3014 |
} |
3024 |
} |
3015 |
else { |
3025 |
else { |
3016 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
3026 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
3017 |
} |
3027 |
} |
3018 |
if (select) { |
3028 |
if (select) { |
3019 |
doSelection(SWT.RIGHT); |
3029 |
doSelection(SWT.RIGHT); |
3020 |
} |
3030 |
} |
3021 |
// scroll one page down or to the bottom |
3031 |
// scroll one page down or to the bottom |
3022 |
scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); |
3032 |
scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); |
3023 |
if (scrollOffset + pageSize > verticalMaximum) { |
3033 |
if (scrollOffset + pageSize > verticalMaximum) { |
3024 |
scrollOffset = verticalMaximum - pageSize; |
3034 |
scrollOffset = verticalMaximum - pageSize; |
3025 |
} |
3035 |
} |
3026 |
if (scrollOffset > verticalScrollOffset) { |
3036 |
if (scrollOffset > verticalScrollOffset) { |
3027 |
setVerticalScrollOffset(scrollOffset, true); |
3037 |
setVerticalScrollOffset(scrollOffset, true); |
3028 |
} |
3038 |
} |
3029 |
} |
3039 |
} |
3030 |
// explicitly go to the calculated caret line. may be different |
3040 |
// explicitly go to the calculated caret line. may be different |
3031 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3041 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3032 |
showCaret(caretLine); |
3042 |
showCaret(caretLine); |
3033 |
// save the original horizontal caret position |
3043 |
// save the original horizontal caret position |
3034 |
columnX = oldColumnX; |
3044 |
columnX = oldColumnX; |
3035 |
} |
3045 |
} |
3036 |
/** |
3046 |
/** |
3037 |
* Moves the cursor to the end of the last fully visible line. |
3047 |
* Moves the cursor to the end of the last fully visible line. |
3038 |
*/ |
3048 |
*/ |
3039 |
void doPageEnd() { |
3049 |
void doPageEnd() { |
3040 |
// go to end of line if in single line mode. fixes 5673 |
3050 |
// go to end of line if in single line mode. fixes 5673 |
3041 |
if (isSingleLine()) { |
3051 |
if (isSingleLine()) { |
3042 |
doLineEnd(); |
3052 |
doLineEnd(); |
3043 |
} |
3053 |
} |
3044 |
else { |
3054 |
else { |
3045 |
int line = getBottomIndex(); |
3055 |
int line = getBottomIndex(); |
3046 |
int bottomCaretOffset = content.getOffsetAtLine(line) + content.getLine(line).length(); |
3056 |
int bottomCaretOffset = content.getOffsetAtLine(line) + content.getLine(line).length(); |
3047 |
|
3057 |
|
3048 |
if (caretOffset < bottomCaretOffset) { |
3058 |
if (caretOffset < bottomCaretOffset) { |
3049 |
caretOffset = bottomCaretOffset; |
3059 |
caretOffset = bottomCaretOffset; |
3050 |
showCaret(); |
3060 |
showCaret(); |
3051 |
} |
3061 |
} |
3052 |
} |
3062 |
} |
3053 |
} |
3063 |
} |
3054 |
/** |
3064 |
/** |
3055 |
* Moves the cursor to the beginning of the first fully visible line. |
3065 |
* Moves the cursor to the beginning of the first fully visible line. |
3056 |
*/ |
3066 |
*/ |
3057 |
void doPageStart() { |
3067 |
void doPageStart() { |
3058 |
int topCaretOffset = content.getOffsetAtLine(topIndex); |
3068 |
int topCaretOffset = content.getOffsetAtLine(topIndex); |
3059 |
|
3069 |
|
3060 |
if (caretOffset > topCaretOffset) { |
3070 |
if (caretOffset > topCaretOffset) { |
3061 |
caretOffset = topCaretOffset; |
3071 |
caretOffset = topCaretOffset; |
3062 |
// explicitly go to the calculated caret line. may be different |
3072 |
// explicitly go to the calculated caret line. may be different |
3063 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3073 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3064 |
showCaret(topIndex); |
3074 |
showCaret(topIndex); |
3065 |
} |
3075 |
} |
3066 |
} |
3076 |
} |
3067 |
/** |
3077 |
/** |
3068 |
* Scrolls one page up so that the first line (truncated or whole) |
3078 |
* Scrolls one page up so that the first line (truncated or whole) |
3069 |
* of the current page becomes the fully visible last line. |
3079 |
* of the current page becomes the fully visible last line. |
3070 |
* The caret is scrolled the same number of lines so that its location |
3080 |
* The caret is scrolled the same number of lines so that its location |
3071 |
* relative to the top line remains the same. The exception is the beginning |
3081 |
* relative to the top line remains the same. The exception is the beginning |
3072 |
* of the text where a full page scroll is not possible. In this case the |
3082 |
* of the text where a full page scroll is not possible. In this case the |
3073 |
* caret is moved in front of the first character. |
3083 |
* caret is moved in front of the first character. |
3074 |
*/ |
3084 |
*/ |
3075 |
void doPageUp() { |
3085 |
void doPageUp() { |
3076 |
int oldColumnX = columnX; |
3086 |
int oldColumnX = columnX; |
3077 |
int caretLine = getCaretLine(); |
3087 |
int caretLine = getCaretLine(); |
3078 |
|
3088 |
|
3079 |
if (caretLine > 0) { |
3089 |
if (caretLine > 0) { |
3080 |
int scrollLines = Math.max(1, Math.min(caretLine, getLineCountWhole())); |
3090 |
int scrollLines = Math.max(1, Math.min(caretLine, getLineCountWhole())); |
3081 |
int scrollOffset; |
3091 |
int scrollOffset; |
3082 |
|
3092 |
|
3083 |
caretLine -= scrollLines; |
3093 |
caretLine -= scrollLines; |
3084 |
if (isBidi()) { |
3094 |
if (isBidi()) { |
3085 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
3095 |
caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); |
3086 |
} |
3096 |
} |
3087 |
else { |
3097 |
else { |
3088 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
3098 |
caretOffset = getOffsetAtMouseLocation(columnX, caretLine); |
3089 |
} |
3099 |
} |
3090 |
// scroll one page up or to the top |
3100 |
// scroll one page up or to the top |
3091 |
scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); |
3101 |
scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); |
3092 |
if (scrollOffset < verticalScrollOffset) { |
3102 |
if (scrollOffset < verticalScrollOffset) { |
3093 |
setVerticalScrollOffset(scrollOffset, true); |
3103 |
setVerticalScrollOffset(scrollOffset, true); |
3094 |
} |
3104 |
} |
3095 |
} |
3105 |
} |
3096 |
// explicitly go to the calculated caret line. may be different |
3106 |
// explicitly go to the calculated caret line. may be different |
3097 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3107 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3098 |
showCaret(caretLine); |
3108 |
showCaret(caretLine); |
3099 |
// save the original horizontal caret position |
3109 |
// save the original horizontal caret position |
3100 |
columnX = oldColumnX; |
3110 |
columnX = oldColumnX; |
3101 |
} |
3111 |
} |
3102 |
/** |
3112 |
/** |
3103 |
* Updates the selection to extend to the current caret position. |
3113 |
* Updates the selection to extend to the current caret position. |
3104 |
*/ |
3114 |
*/ |
3105 |
void doSelection(int direction) { |
3115 |
void doSelection(int direction) { |
3106 |
int redrawStart = -1; |
3116 |
int redrawStart = -1; |
3107 |
int redrawEnd = -1; |
3117 |
int redrawEnd = -1; |
3108 |
|
3118 |
|
3109 |
if (selectionAnchor == -1) { |
3119 |
if (selectionAnchor == -1) { |
3110 |
selectionAnchor = selection.x; |
3120 |
selectionAnchor = selection.x; |
3111 |
} |
3121 |
} |
3112 |
if (direction == SWT.LEFT) { |
3122 |
if (direction == SWT.LEFT) { |
3113 |
if (caretOffset < selection.x) { |
3123 |
if (caretOffset < selection.x) { |
3114 |
// grow selection |
3124 |
// grow selection |
3115 |
redrawEnd = selection.x; |
3125 |
redrawEnd = selection.x; |
3116 |
redrawStart = selection.x = caretOffset; |
3126 |
redrawStart = selection.x = caretOffset; |
3117 |
// check if selection has reversed direction |
3127 |
// check if selection has reversed direction |
3118 |
if (selection.y != selectionAnchor) { |
3128 |
if (selection.y != selectionAnchor) { |
3119 |
redrawEnd = selection.y; |
3129 |
redrawEnd = selection.y; |
3120 |
selection.y = selectionAnchor; |
3130 |
selection.y = selectionAnchor; |
3121 |
} |
3131 |
} |
3122 |
} |
3132 |
} |
3123 |
else // test whether selection actually changed. Fixes 1G71EO1 |
3133 |
else // test whether selection actually changed. Fixes 1G71EO1 |
3124 |
if (selectionAnchor == selection.x && caretOffset < selection.y) { |
3134 |
if (selectionAnchor == selection.x && caretOffset < selection.y) { |
3125 |
// caret moved towards selection anchor (left side of selection). |
3135 |
// caret moved towards selection anchor (left side of selection). |
3126 |
// shrink selection |
3136 |
// shrink selection |
3127 |
redrawEnd = selection.y; |
3137 |
redrawEnd = selection.y; |
3128 |
redrawStart = selection.y = caretOffset; |
3138 |
redrawStart = selection.y = caretOffset; |
3129 |
} |
3139 |
} |
3130 |
} |
3140 |
} |
3131 |
else { |
3141 |
else { |
3132 |
if (caretOffset > selection.y) { |
3142 |
if (caretOffset > selection.y) { |
3133 |
// grow selection |
3143 |
// grow selection |
3134 |
redrawStart = selection.y; |
3144 |
redrawStart = selection.y; |
3135 |
redrawEnd = selection.y = caretOffset; |
3145 |
redrawEnd = selection.y = caretOffset; |
3136 |
// check if selection has reversed direction |
3146 |
// check if selection has reversed direction |
3137 |
if (selection.x != selectionAnchor) { |
3147 |
if (selection.x != selectionAnchor) { |
3138 |
redrawStart = selection.x; |
3148 |
redrawStart = selection.x; |
3139 |
selection.x = selectionAnchor; |
3149 |
selection.x = selectionAnchor; |
3140 |
} |
3150 |
} |
3141 |
} |
3151 |
} |
3142 |
else // test whether selection actually changed. Fixes 1G71EO1 |
3152 |
else // test whether selection actually changed. Fixes 1G71EO1 |
3143 |
if (selectionAnchor == selection.y && caretOffset > selection.x) { |
3153 |
if (selectionAnchor == selection.y && caretOffset > selection.x) { |
3144 |
// caret moved towards selection anchor (right side of selection). |
3154 |
// caret moved towards selection anchor (right side of selection). |
3145 |
// shrink selection |
3155 |
// shrink selection |
3146 |
redrawStart = selection.x; |
3156 |
redrawStart = selection.x; |
3147 |
redrawEnd = selection.x = caretOffset; |
3157 |
redrawEnd = selection.x = caretOffset; |
3148 |
} |
3158 |
} |
3149 |
} |
3159 |
} |
3150 |
if (redrawStart != -1 && redrawEnd != -1) { |
3160 |
if (redrawStart != -1 && redrawEnd != -1) { |
3151 |
internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); |
3161 |
internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); |
3152 |
sendSelectionEvent(); |
3162 |
sendSelectionEvent(); |
3153 |
} |
3163 |
} |
3154 |
} |
3164 |
} |
3155 |
/** |
3165 |
/** |
3156 |
* Moves the caret to the next character or to the beginning of the |
3166 |
* Moves the caret to the next character or to the beginning of the |
3157 |
* next line if the cursor is at the end of a line. |
3167 |
* next line if the cursor is at the end of a line. |
3158 |
*/ |
3168 |
*/ |
3159 |
void doSelectionCursorNext() { |
3169 |
void doSelectionCursorNext() { |
3160 |
int caretLine = getCaretLine(); |
3170 |
int caretLine = getCaretLine(); |
3161 |
int lineOffset = content.getOffsetAtLine(caretLine); |
3171 |
int lineOffset = content.getOffsetAtLine(caretLine); |
3162 |
int offsetInLine = caretOffset - lineOffset; |
3172 |
int offsetInLine = caretOffset - lineOffset; |
3163 |
|
3173 |
|
3164 |
if (offsetInLine < content.getLine(caretLine).length()) { |
3174 |
if (offsetInLine < content.getLine(caretLine).length()) { |
3165 |
// Remember the last direction. Always update lastCaretDirection, |
3175 |
// Remember the last direction. Always update lastCaretDirection, |
3166 |
// even though it's not used in non-bidi mode in order to avoid |
3176 |
// even though it's not used in non-bidi mode in order to avoid |
3167 |
// extra methods. |
3177 |
// extra methods. |
3168 |
lastCaretDirection = ST.COLUMN_NEXT; |
3178 |
lastCaretDirection = ST.COLUMN_NEXT; |
3169 |
caretOffset++; |
3179 |
caretOffset++; |
3170 |
showCaret(); |
3180 |
showCaret(); |
3171 |
} |
3181 |
} |
3172 |
else |
3182 |
else |
3173 |
if (caretLine < content.getLineCount() - 1 && isSingleLine() == false) { |
3183 |
if (caretLine < content.getLineCount() - 1 && isSingleLine() == false) { |
3174 |
// only go to next line if not in single line mode. fixes 5673 |
3184 |
// only go to next line if not in single line mode. fixes 5673 |
3175 |
caretLine++; |
3185 |
caretLine++; |
3176 |
caretOffset = content.getOffsetAtLine(caretLine); |
3186 |
caretOffset = content.getOffsetAtLine(caretLine); |
3177 |
// explicitly go to the calculated caret line. may be different |
3187 |
// explicitly go to the calculated caret line. may be different |
3178 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3188 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3179 |
showCaret(caretLine); |
3189 |
showCaret(caretLine); |
3180 |
} |
3190 |
} |
3181 |
} |
3191 |
} |
3182 |
/** |
3192 |
/** |
3183 |
* Moves the caret to the previous character or to the end of the previous |
3193 |
* Moves the caret to the previous character or to the end of the previous |
3184 |
* line if the cursor is at the beginning of a line. |
3194 |
* line if the cursor is at the beginning of a line. |
3185 |
*/ |
3195 |
*/ |
3186 |
void doSelectionCursorPrevious() { |
3196 |
void doSelectionCursorPrevious() { |
3187 |
int caretLine = getCaretLine(); |
3197 |
int caretLine = getCaretLine(); |
3188 |
int lineOffset = content.getOffsetAtLine(caretLine); |
3198 |
int lineOffset = content.getOffsetAtLine(caretLine); |
3189 |
int offsetInLine = caretOffset - lineOffset; |
3199 |
int offsetInLine = caretOffset - lineOffset; |
3190 |
|
3200 |
|
3191 |
if (offsetInLine > 0) { |
3201 |
if (offsetInLine > 0) { |
3192 |
// Remember the last direction. Always update lastCaretDirection, |
3202 |
// Remember the last direction. Always update lastCaretDirection, |
3193 |
// even though it's not used in non-bidi mode in order to avoid |
3203 |
// even though it's not used in non-bidi mode in order to avoid |
3194 |
// extra methods. |
3204 |
// extra methods. |
3195 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
3205 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
3196 |
caretOffset--; |
3206 |
caretOffset--; |
3197 |
// explicitly go to the calculated caret line. may be different |
3207 |
// explicitly go to the calculated caret line. may be different |
3198 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3208 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3199 |
showCaret(caretLine); |
3209 |
showCaret(caretLine); |
3200 |
} |
3210 |
} |
3201 |
else |
3211 |
else |
3202 |
if (caretLine > 0) { |
3212 |
if (caretLine > 0) { |
3203 |
caretLine--; |
3213 |
caretLine--; |
3204 |
lineOffset = content.getOffsetAtLine(caretLine); |
3214 |
lineOffset = content.getOffsetAtLine(caretLine); |
3205 |
caretOffset = lineOffset + content.getLine(caretLine).length(); |
3215 |
caretOffset = lineOffset + content.getLine(caretLine).length(); |
3206 |
showCaret(); |
3216 |
showCaret(); |
3207 |
} |
3217 |
} |
3208 |
} |
3218 |
} |
3209 |
/** |
3219 |
/** |
3210 |
* Moves the caret one line down and to the same character offset relative |
3220 |
* Moves the caret one line down and to the same character offset relative |
3211 |
* to the beginning of the line. Moves the caret to the end of the new line |
3221 |
* to the beginning of the line. Moves the caret to the end of the new line |
3212 |
* if the new line is shorter than the character offset. |
3222 |
* if the new line is shorter than the character offset. |
3213 |
* Moves the caret to the end of the text if the caret already is on the |
3223 |
* Moves the caret to the end of the text if the caret already is on the |
3214 |
* last line. |
3224 |
* last line. |
3215 |
* Adjusts the selection according to the caret change. This can either add |
3225 |
* Adjusts the selection according to the caret change. This can either add |
3216 |
* to or subtract from the old selection, depending on the previous selection |
3226 |
* to or subtract from the old selection, depending on the previous selection |
3217 |
* direction. |
3227 |
* direction. |
3218 |
*/ |
3228 |
*/ |
3219 |
void doSelectionLineDown() { |
3229 |
void doSelectionLineDown() { |
3220 |
int oldColumnX = columnX; |
3230 |
int oldColumnX = columnX; |
3221 |
int caretLine; |
3231 |
int caretLine; |
3222 |
|
3232 |
|
3223 |
if (isSingleLine()) { |
3233 |
if (isSingleLine()) { |
3224 |
return; |
3234 |
return; |
3225 |
} |
3235 |
} |
3226 |
caretLine = getCaretLine(); |
3236 |
caretLine = getCaretLine(); |
3227 |
if (caretLine == content.getLineCount() - 1) { |
3237 |
if (caretLine == content.getLineCount() - 1) { |
3228 |
caretOffset = content.getCharCount(); |
3238 |
caretOffset = content.getCharCount(); |
3229 |
} |
3239 |
} |
3230 |
else { |
3240 |
else { |
3231 |
caretLine = doLineDown(); |
3241 |
caretLine = doLineDown(); |
3232 |
} |
3242 |
} |
3233 |
setMouseWordSelectionAnchor(); |
3243 |
setMouseWordSelectionAnchor(); |
3234 |
// select first and then scroll to reduce flash when key |
3244 |
// select first and then scroll to reduce flash when key |
3235 |
// repeat scrolls lots of lines |
3245 |
// repeat scrolls lots of lines |
3236 |
doSelection(SWT.RIGHT); |
3246 |
doSelection(SWT.RIGHT); |
3237 |
// explicitly go to the calculated caret line. may be different |
3247 |
// explicitly go to the calculated caret line. may be different |
3238 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3248 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3239 |
showCaret(caretLine); |
3249 |
showCaret(caretLine); |
3240 |
// save the original horizontal caret position |
3250 |
// save the original horizontal caret position |
3241 |
columnX = oldColumnX; |
3251 |
columnX = oldColumnX; |
3242 |
} |
3252 |
} |
3243 |
/** |
3253 |
/** |
3244 |
* Moves the caret one line up and to the same character offset relative |
3254 |
* Moves the caret one line up and to the same character offset relative |
3245 |
* to the beginning of the line. Moves the caret to the end of the new line |
3255 |
* to the beginning of the line. Moves the caret to the end of the new line |
3246 |
* if the new line is shorter than the character offset. |
3256 |
* if the new line is shorter than the character offset. |
3247 |
* Moves the caret to the beginning of the document if it is already on the |
3257 |
* Moves the caret to the beginning of the document if it is already on the |
3248 |
* first line. |
3258 |
* first line. |
Lines 3251-3304
Link Here
|
3251 |
* direction. |
3261 |
* direction. |
3252 |
*/ |
3262 |
*/ |
3253 |
void doSelectionLineUp() { |
3263 |
void doSelectionLineUp() { |
3254 |
int oldColumnX = columnX; |
3264 |
int oldColumnX = columnX; |
3255 |
int caretLine = getCaretLine(); |
3265 |
int caretLine = getCaretLine(); |
3256 |
|
3266 |
|
3257 |
if (caretLine == 0) { |
3267 |
if (caretLine == 0) { |
3258 |
caretOffset = 0; |
3268 |
caretOffset = 0; |
3259 |
} |
3269 |
} |
3260 |
else { |
3270 |
else { |
3261 |
caretLine = doLineUp(); |
3271 |
caretLine = doLineUp(); |
3262 |
} |
3272 |
} |
3263 |
setMouseWordSelectionAnchor(); |
3273 |
setMouseWordSelectionAnchor(); |
3264 |
// explicitly go to the calculated caret line. may be different |
3274 |
// explicitly go to the calculated caret line. may be different |
3265 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3275 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
3266 |
showCaret(caretLine); |
3276 |
showCaret(caretLine); |
3267 |
doSelection(SWT.LEFT); |
3277 |
doSelection(SWT.LEFT); |
3268 |
// save the original horizontal caret position |
3278 |
// save the original horizontal caret position |
3269 |
columnX = oldColumnX; |
3279 |
columnX = oldColumnX; |
3270 |
} |
3280 |
} |
3271 |
/** |
3281 |
/** |
3272 |
* Moves the caret to the end of the next word . |
3282 |
* Moves the caret to the end of the next word . |
3273 |
*/ |
3283 |
*/ |
3274 |
void doSelectionWordNext() { |
3284 |
void doSelectionWordNext() { |
3275 |
int newCaretOffset = getWordEnd(caretOffset); |
3285 |
int newCaretOffset = getWordEnd(caretOffset); |
3276 |
|
3286 |
|
3277 |
// don't change caret position if in single line mode and the cursor |
3287 |
// don't change caret position if in single line mode and the cursor |
3278 |
// would be on a different line. fixes 5673 |
3288 |
// would be on a different line. fixes 5673 |
3279 |
if (isSingleLine() == false || |
3289 |
if (isSingleLine() == false || |
3280 |
content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) { |
3290 |
content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) { |
3281 |
lastCaretDirection = ST.COLUMN_NEXT; |
3291 |
lastCaretDirection = ST.COLUMN_NEXT; |
3282 |
caretOffset = newCaretOffset; |
3292 |
caretOffset = newCaretOffset; |
3283 |
showCaret(); |
3293 |
showCaret(); |
3284 |
} |
3294 |
} |
3285 |
} |
3295 |
} |
3286 |
/** |
3296 |
/** |
3287 |
* Moves the caret to the start of the previous word. |
3297 |
* Moves the caret to the start of the previous word. |
3288 |
*/ |
3298 |
*/ |
3289 |
void doSelectionWordPrevious() { |
3299 |
void doSelectionWordPrevious() { |
3290 |
int caretLine; |
3300 |
int caretLine; |
3291 |
|
3301 |
|
3292 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
3302 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
3293 |
caretOffset = getWordStart(caretOffset); |
3303 |
caretOffset = getWordStart(caretOffset); |
3294 |
caretLine = content.getLineAtOffset(caretOffset); |
3304 |
caretLine = content.getLineAtOffset(caretOffset); |
3295 |
// word previous always comes from bottom line. when |
3305 |
// word previous always comes from bottom line. when |
3296 |
// wrapping lines, stay on bottom line when on line boundary |
3306 |
// wrapping lines, stay on bottom line when on line boundary |
3297 |
if (wordWrap && caretLine < content.getLineCount() - 1 && |
3307 |
if (wordWrap && caretLine < content.getLineCount() - 1 && |
3298 |
caretOffset == content.getOffsetAtLine(caretLine + 1)) { |
3308 |
caretOffset == content.getOffsetAtLine(caretLine + 1)) { |
3299 |
caretLine++; |
3309 |
caretLine++; |
3300 |
} |
3310 |
} |
3301 |
showCaret(caretLine); |
3311 |
showCaret(caretLine); |
3302 |
} |
3312 |
} |
3303 |
/** |
3313 |
/** |
3304 |
* Moves the caret to the end of the next word. |
3314 |
* Moves the caret to the end of the next word. |
Lines 3306-3321
Link Here
|
3306 |
* and remove the selection. |
3316 |
* and remove the selection. |
3307 |
*/ |
3317 |
*/ |
3308 |
void doWordNext() { |
3318 |
void doWordNext() { |
3309 |
if (selection.y - selection.x > 0) { |
3319 |
if (selection.y - selection.x > 0) { |
3310 |
int caretLine; |
3320 |
int caretLine; |
3311 |
|
3321 |
|
3312 |
caretOffset = selection.y; |
3322 |
caretOffset = selection.y; |
3313 |
caretLine = getCaretLine(); |
3323 |
caretLine = getCaretLine(); |
3314 |
showCaret(caretLine); |
3324 |
showCaret(caretLine); |
3315 |
} |
3325 |
} |
3316 |
else { |
3326 |
else { |
3317 |
doSelectionWordNext(); |
3327 |
doSelectionWordNext(); |
3318 |
} |
3328 |
} |
3319 |
} |
3329 |
} |
3320 |
/** |
3330 |
/** |
3321 |
* Moves the caret to the start of the previous word. |
3331 |
* Moves the caret to the start of the previous word. |
Lines 3323-3342
Link Here
|
3323 |
* and remove the selection. |
3333 |
* and remove the selection. |
3324 |
*/ |
3334 |
*/ |
3325 |
void doWordPrevious() { |
3335 |
void doWordPrevious() { |
3326 |
if (selection.y - selection.x > 0) { |
3336 |
if (selection.y - selection.x > 0) { |
3327 |
int caretLine; |
3337 |
int caretLine; |
3328 |
|
3338 |
|
3329 |
caretOffset = selection.x; |
3339 |
caretOffset = selection.x; |
3330 |
caretLine = getCaretLine(); |
3340 |
caretLine = getCaretLine(); |
3331 |
showCaret(caretLine); |
3341 |
showCaret(caretLine); |
3332 |
} |
3342 |
} |
3333 |
else { |
3343 |
else { |
3334 |
doSelectionWordPrevious(); |
3344 |
doSelectionWordPrevious(); |
3335 |
} |
3345 |
} |
3336 |
} |
3346 |
} |
3337 |
/** |
3347 |
/** |
3338 |
* Draws the specified rectangle. |
3348 |
* Draws the specified rectangle. |
3339 |
* Draw directly without invalidating the affected area when clearBackground is |
3349 |
* Draw directly without invalidating the affected area when clearBackground is |
3340 |
* false. |
3350 |
* false. |
3341 |
* <p> |
3351 |
* <p> |
3342 |
* |
3352 |
* |
Lines 3344-3396
Link Here
|
3344 |
* @param y the y position |
3354 |
* @param y the y position |
3345 |
* @param width the width |
3355 |
* @param width the width |
3346 |
* @param height the height |
3356 |
* @param height the height |
3347 |
* @param clearBackground true=clear the background by invalidating the requested |
3357 |
* @param clearBackground true=clear the background by invalidating the requested |
3348 |
* redraw area, false=draw the foreground directly without invalidating the |
3358 |
* redraw area, false=draw the foreground directly without invalidating the |
3349 |
* redraw area. |
3359 |
* redraw area. |
3350 |
*/ |
3360 |
*/ |
3351 |
void draw(int x, int y, int width, int height, boolean clearBackground) { |
3361 |
void draw(int x, int y, int width, int height, boolean clearBackground) { |
3352 |
if (clearBackground) { |
3362 |
if (clearBackground) { |
3353 |
redraw(x + leftMargin, y + topMargin, width, height, true); |
3363 |
redraw(x + leftMargin, y + topMargin, width, height, true); |
3354 |
} |
3364 |
} |
3355 |
else { |
3365 |
else { |
3356 |
int startLine = (y + verticalScrollOffset) / lineHeight; |
3366 |
int startLine = (y + verticalScrollOffset) / lineHeight; |
3357 |
int endY = y + height; |
3367 |
int endY = y + height; |
3358 |
int paintYFromTopLine = (startLine - topIndex) * lineHeight; |
3368 |
int paintYFromTopLine = (startLine - topIndex) * lineHeight; |
3359 |
int topLineOffset = (topIndex * lineHeight - verticalScrollOffset); |
3369 |
int topLineOffset = (topIndex * lineHeight - verticalScrollOffset); |
3360 |
int paintY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling |
3370 |
int paintY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling |
3361 |
int lineCount = content.getLineCount(); |
3371 |
int lineCount = content.getLineCount(); |
3362 |
Color background = getBackground(); |
3372 |
Color background = getBackground(); |
3363 |
Color foreground = getForeground(); |
3373 |
Color foreground = getForeground(); |
3364 |
GC gc = getGC(); |
3374 |
GC gc = getGC(); |
3365 |
|
3375 |
|
3366 |
if (isSingleLine()) { |
3376 |
if (isSingleLine()) { |
3367 |
lineCount = 1; |
3377 |
lineCount = 1; |
3368 |
if (startLine > 1) { |
3378 |
if (startLine > 1) { |
3369 |
startLine = 1; |
3379 |
startLine = 1; |
3370 |
} |
3380 |
} |
3371 |
} |
3381 |
} |
3372 |
for (int i = startLine; paintY < endY && i < lineCount; i++, paintY += lineHeight) { |
3382 |
for (int i = startLine; paintY < endY && i < lineCount; i++, paintY += lineHeight) { |
3373 |
String line = content.getLine(i); |
3383 |
String line = content.getLine(i); |
3374 |
renderer.drawLine(line, i, paintY, gc, background, foreground, clearBackground); |
3384 |
renderer.drawLine(line, i, paintY, gc, background, foreground, clearBackground); |
3375 |
} |
3385 |
} |
3376 |
gc.dispose(); |
3386 |
gc.dispose(); |
3377 |
} |
3387 |
} |
3378 |
} |
3388 |
} |
3379 |
/** |
3389 |
/** |
3380 |
* Ends the autoscroll process. |
3390 |
* Ends the autoscroll process. |
3381 |
*/ |
3391 |
*/ |
3382 |
void endAutoScroll() { |
3392 |
void endAutoScroll() { |
3383 |
autoScrollDirection = SWT.NULL; |
3393 |
autoScrollDirection = SWT.NULL; |
3384 |
} |
3394 |
} |
3385 |
/** |
3395 |
/** |
3386 |
* @see org.eclipse.swt.widgets.Control#getBackground |
3396 |
* @see org.eclipse.swt.widgets.Control#getBackground |
3387 |
*/ |
3397 |
*/ |
3388 |
public Color getBackground() { |
3398 |
public Color getBackground() { |
3389 |
checkWidget(); |
3399 |
checkWidget(); |
3390 |
if (background == null) { |
3400 |
if (background == null) { |
3391 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); |
3401 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); |
3392 |
} |
3402 |
} |
3393 |
return background; |
3403 |
return background; |
3394 |
} |
3404 |
} |
3395 |
/** |
3405 |
/** |
3396 |
* Gets the BIDI coloring mode. When true the BIDI text display |
3406 |
* Gets the BIDI coloring mode. When true the BIDI text display |
Lines 3407-3476
Link Here
|
3407 |
* </p> |
3417 |
* </p> |
3408 |
*/ |
3418 |
*/ |
3409 |
public boolean getBidiColoring() { |
3419 |
public boolean getBidiColoring() { |
3410 |
checkWidget(); |
3420 |
checkWidget(); |
3411 |
return bidiColoring; |
3421 |
return bidiColoring; |
3412 |
} |
3422 |
} |
3413 |
/** |
3423 |
/** |
3414 |
* Returns the offset at the specified x location in the specified line. |
3424 |
* Returns the offset at the specified x location in the specified line. |
3415 |
* Also sets the caret direction so that the caret is placed correctly |
3425 |
* Also sets the caret direction so that the caret is placed correctly |
3416 |
* depending on whether the mouse location is in a R2L or L2R segment. |
3426 |
* depending on whether the mouse location is in a R2L or L2R segment. |
3417 |
* <p> |
3427 |
* <p> |
3418 |
* |
3428 |
* |
3419 |
* @param x x location of the mouse location |
3429 |
* @param x x location of the mouse location |
3420 |
* @param line line the mouse location is in |
3430 |
* @param line line the mouse location is in |
3421 |
* @return the offset at the specified x location in the specified line, |
3431 |
* @return the offset at the specified x location in the specified line, |
3422 |
* relative to the beginning of the document |
3432 |
* relative to the beginning of the document |
3423 |
*/ |
3433 |
*/ |
3424 |
int getBidiOffsetAtMouseLocation(int x, int line) { |
3434 |
int getBidiOffsetAtMouseLocation(int x, int line) { |
3425 |
String lineText = content.getLine(line); |
3435 |
String lineText = content.getLine(line); |
3426 |
int lineOffset = content.getOffsetAtLine(line); |
3436 |
int lineOffset = content.getOffsetAtLine(line); |
3427 |
GC gc = getGC(); |
3437 |
GC gc = getGC(); |
3428 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
3438 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
3429 |
int[] values; |
3439 |
int[] values; |
3430 |
int offsetInLine; |
3440 |
int offsetInLine; |
3431 |
x += horizontalScrollOffset; |
3441 |
x += horizontalScrollOffset; |
3432 |
values = bidi.getCaretOffsetAndDirectionAtX(x - leftMargin); |
3442 |
values = bidi.getCaretOffsetAndDirectionAtX(x - leftMargin); |
3433 |
offsetInLine = values[0]; |
3443 |
offsetInLine = values[0]; |
3434 |
lastCaretDirection = values[1]; |
3444 |
lastCaretDirection = values[1]; |
3435 |
gc.dispose(); |
3445 |
gc.dispose(); |
3436 |
|
3446 |
|
3437 |
return lineOffset + offsetInLine; |
3447 |
return lineOffset + offsetInLine; |
3438 |
} |
3448 |
} |
3439 |
/** |
3449 |
/** |
3440 |
* Returns the x position of the character at the specified offset |
3450 |
* Returns the x position of the character at the specified offset |
3441 |
* relative to the first character in the line. |
3451 |
* relative to the first character in the line. |
3442 |
* </p> |
3452 |
* </p> |
3443 |
* |
3453 |
* |
3444 |
* @param text text to be measured. |
3454 |
* @param text text to be measured. |
3445 |
* @param endOffset offset of the character |
3455 |
* @param endOffset offset of the character |
3446 |
* @param bidi the bidi object to use for measuring text in bidi |
3456 |
* @param bidi the bidi object to use for measuring text in bidi |
3447 |
* locales. |
3457 |
* locales. |
3448 |
* @return x position of the character at the specified offset. |
3458 |
* @return x position of the character at the specified offset. |
3449 |
* 0 if the length is outside the specified text. |
3459 |
* 0 if the length is outside the specified text. |
3450 |
*/ |
3460 |
*/ |
3451 |
int getBidiTextPosition(String text, int endOffset, StyledTextBidi bidi) { |
3461 |
int getBidiTextPosition(String text, int endOffset, StyledTextBidi bidi) { |
3452 |
if (endOffset > text.length()) { |
3462 |
if (endOffset > text.length()) { |
3453 |
return 0; |
3463 |
return 0; |
3454 |
} |
3464 |
} |
3455 |
// Use lastCaretDirection in order to get same results as during |
3465 |
// Use lastCaretDirection in order to get same results as during |
3456 |
// caret positioning (setBidiCaretLocation). Fixes 1GKU4C5. |
3466 |
// caret positioning (setBidiCaretLocation). Fixes 1GKU4C5. |
3457 |
return bidi.getTextPosition(endOffset, lastCaretDirection); |
3467 |
return bidi.getTextPosition(endOffset, lastCaretDirection); |
3458 |
} |
3468 |
} |
3459 |
/** |
3469 |
/** |
3460 |
* Returns the index of the last fully visible line. |
3470 |
* Returns the index of the last fully visible line. |
3461 |
* <p> |
3471 |
* <p> |
3462 |
* |
3472 |
* |
3463 |
* @return index of the last fully visible line. |
3473 |
* @return index of the last fully visible line. |
3464 |
*/ |
3474 |
*/ |
3465 |
int getBottomIndex() { |
3475 |
int getBottomIndex() { |
3466 |
int lineCount = 1; |
3476 |
int lineCount = 1; |
3467 |
|
3477 |
|
3468 |
if (lineHeight != 0) { |
3478 |
if (lineHeight != 0) { |
3469 |
// calculate the number of lines that are fully visible |
3479 |
// calculate the number of lines that are fully visible |
3470 |
int partialTopLineHeight = topIndex * lineHeight - verticalScrollOffset; |
3480 |
int partialTopLineHeight = topIndex * lineHeight - verticalScrollOffset; |
3471 |
lineCount = (getClientArea().height - partialTopLineHeight) / lineHeight; |
3481 |
lineCount = (getClientArea().height - partialTopLineHeight) / lineHeight; |
3472 |
} |
3482 |
} |
3473 |
return Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); |
3483 |
return Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); |
3474 |
} |
3484 |
} |
3475 |
/** |
3485 |
/** |
3476 |
* Returns the caret position relative to the start of the text. |
3486 |
* Returns the caret position relative to the start of the text. |
Lines 3483-3535
Link Here
|
3483 |
* </ul> |
3493 |
* </ul> |
3484 |
*/ |
3494 |
*/ |
3485 |
public int getCaretOffset() { |
3495 |
public int getCaretOffset() { |
3486 |
checkWidget(); |
3496 |
checkWidget(); |
3487 |
|
3497 |
|
3488 |
return caretOffset; |
3498 |
return caretOffset; |
3489 |
} |
3499 |
} |
3490 |
/** |
3500 |
/** |
3491 |
* Returns the caret offset at the given x location in the line. |
3501 |
* Returns the caret offset at the given x location in the line. |
3492 |
* The caret offset is the offset of the character where the caret will be |
3502 |
* The caret offset is the offset of the character where the caret will be |
3493 |
* placed when a mouse click occurs. The caret offset will be the offset of |
3503 |
* placed when a mouse click occurs. The caret offset will be the offset of |
3494 |
* the character after the clicked one if the mouse click occurs at the second |
3504 |
* the character after the clicked one if the mouse click occurs at the second |
3495 |
* half of a character. |
3505 |
* half of a character. |
3496 |
* Doesn't properly handle ligatures and other context dependent characters |
3506 |
* Doesn't properly handle ligatures and other context dependent characters |
3497 |
* unless the current locale is a bidi locale. |
3507 |
* unless the current locale is a bidi locale. |
3498 |
* Ligatures are handled properly as long as they don't occur at lineXOffset. |
3508 |
* Ligatures are handled properly as long as they don't occur at lineXOffset. |
3499 |
* <p> |
3509 |
* <p> |
3500 |
* |
3510 |
* |
3501 |
* @param line text of the line to calculate the offset in |
3511 |
* @param line text of the line to calculate the offset in |
3502 |
* @param lineOffset offset of the first character in the line. |
3512 |
* @param lineOffset offset of the first character in the line. |
3503 |
* 0 based from the beginning of the document. |
3513 |
* 0 based from the beginning of the document. |
3504 |
* @param lineXOffset x location in the line |
3514 |
* @param lineXOffset x location in the line |
3505 |
* @return caret offset at the x location relative to the start of the line. |
3515 |
* @return caret offset at the x location relative to the start of the line. |
3506 |
*/ |
3516 |
*/ |
3507 |
int getCaretOffsetAtX(String line, int lineOffset, int lineXOffset) { |
3517 |
int getCaretOffsetAtX(String line, int lineOffset, int lineXOffset) { |
3508 |
int offset = 0; |
3518 |
int offset = 0; |
3509 |
GC gc = getGC(); |
3519 |
GC gc = getGC(); |
3510 |
StyleRange[] styles = null; |
3520 |
StyleRange[] styles = null; |
3511 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
3521 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
3512 |
|
3522 |
|
3513 |
lineXOffset += horizontalScrollOffset; |
3523 |
lineXOffset += horizontalScrollOffset; |
3514 |
if (event != null) { |
3524 |
if (event != null) { |
3515 |
styles = renderer.filterLineStyles(event.styles); |
3525 |
styles = renderer.filterLineStyles(event.styles); |
3516 |
} |
3526 |
} |
3517 |
int low = -1; |
3527 |
int low = -1; |
3518 |
int high = line.length(); |
3528 |
int high = line.length(); |
3519 |
while (high - low > 1) { |
3529 |
while (high - low > 1) { |
3520 |
offset = (high + low) / 2; |
3530 |
offset = (high + low) / 2; |
3521 |
int x = renderer.getTextPosition(line, lineOffset, offset, styles, gc) + leftMargin; |
3531 |
int x = renderer.getTextPosition(line, lineOffset, offset, styles, gc) + leftMargin; |
3522 |
int charWidth = renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc) + leftMargin - x; |
3532 |
int charWidth = renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc) + leftMargin - x; |
3523 |
if (lineXOffset <= x + charWidth / 2) { |
3533 |
if (lineXOffset <= x + charWidth / 2) { |
3524 |
high = offset; |
3534 |
high = offset; |
3525 |
} |
3535 |
} |
3526 |
else { |
3536 |
else { |
3527 |
low = offset; |
3537 |
low = offset; |
3528 |
} |
3538 |
} |
3529 |
} |
3539 |
} |
3530 |
offset = high; |
3540 |
offset = high; |
3531 |
gc.dispose(); |
3541 |
gc.dispose(); |
3532 |
return offset; |
3542 |
return offset; |
3533 |
} |
3543 |
} |
3534 |
/** |
3544 |
/** |
3535 |
* Returns the caret width. |
3545 |
* Returns the caret width. |
Lines 3538-3553
Link Here
|
3538 |
* @return the caret width, 0 if caret is null. |
3548 |
* @return the caret width, 0 if caret is null. |
3539 |
*/ |
3549 |
*/ |
3540 |
int getCaretWidth() { |
3550 |
int getCaretWidth() { |
3541 |
Caret caret = getCaret(); |
3551 |
Caret caret = getCaret(); |
3542 |
if (caret == null) return 0; |
3552 |
if (caret == null) return 0; |
3543 |
return caret.getSize().x; |
3553 |
return caret.getSize().x; |
3544 |
} |
3554 |
} |
3545 |
/** |
3555 |
/** |
3546 |
* Returns the content implementation that is used for text storage |
3556 |
* Returns the content implementation that is used for text storage |
3547 |
* or null if no user defined content implementation has been set. |
3557 |
* or null if no user defined content implementation has been set. |
3548 |
* <p> |
3558 |
* <p> |
3549 |
* |
3559 |
* |
3550 |
* @return content implementation that is used for text storage or null |
3560 |
* @return content implementation that is used for text storage or null |
3551 |
* if no user defined content implementation has been set. |
3561 |
* if no user defined content implementation has been set. |
3552 |
* @exception SWTException <ul> |
3562 |
* @exception SWTException <ul> |
3553 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3563 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 3555-3565
Link Here
|
3555 |
* </ul> |
3565 |
* </ul> |
3556 |
*/ |
3566 |
*/ |
3557 |
public StyledTextContent getContent() { |
3567 |
public StyledTextContent getContent() { |
3558 |
checkWidget(); |
3568 |
checkWidget(); |
3559 |
|
3569 |
|
3560 |
return logicalContent; |
3570 |
return logicalContent; |
3561 |
} |
3571 |
} |
3562 |
/** |
3572 |
/** |
3563 |
* Returns whether the widget implements double click mouse behavior. |
3573 |
* Returns whether the widget implements double click mouse behavior. |
3564 |
* <p> |
3574 |
* <p> |
3565 |
* |
3575 |
* |
Lines 3571-3578
Link Here
|
3571 |
* </ul> |
3581 |
* </ul> |
3572 |
*/ |
3582 |
*/ |
3573 |
public boolean getDoubleClickEnabled() { |
3583 |
public boolean getDoubleClickEnabled() { |
3574 |
checkWidget(); |
3584 |
checkWidget(); |
3575 |
return doubleClickEnabled; |
3585 |
return doubleClickEnabled; |
3576 |
} |
3586 |
} |
3577 |
/** |
3587 |
/** |
3578 |
* Returns whether the widget content can be edited. |
3588 |
* Returns whether the widget content can be edited. |
Lines 3585-3604
Link Here
|
3585 |
* </ul> |
3595 |
* </ul> |
3586 |
*/ |
3596 |
*/ |
3587 |
public boolean getEditable() { |
3597 |
public boolean getEditable() { |
3588 |
checkWidget(); |
3598 |
checkWidget(); |
3589 |
return editable; |
3599 |
return editable; |
3590 |
} |
3600 |
} |
3591 |
/** |
3601 |
/** |
3592 |
* @see org.eclipse.swt.widgets.Control#getForeground |
3602 |
* @see org.eclipse.swt.widgets.Control#getForeground |
3593 |
*/ |
3603 |
*/ |
3594 |
public Color getForeground() { |
3604 |
public Color getForeground() { |
3595 |
checkWidget(); |
3605 |
checkWidget(); |
3596 |
if (foreground == null) { |
3606 |
if (foreground == null) { |
3597 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); |
3607 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); |
3598 |
} |
3608 |
} |
3599 |
return foreground; |
3609 |
return foreground; |
3600 |
} |
3610 |
} |
3601 |
/** |
3611 |
/** |
3602 |
* Return a GC to use for rendering and update the cached font style to |
3612 |
* Return a GC to use for rendering and update the cached font style to |
3603 |
* represent the current style. |
3613 |
* represent the current style. |
3604 |
* <p> |
3614 |
* <p> |
Lines 3606-3628
Link Here
|
3606 |
* @return GC. |
3616 |
* @return GC. |
3607 |
*/ |
3617 |
*/ |
3608 |
GC getGC() { |
3618 |
GC getGC() { |
3609 |
renderer.setCurrentFontStyle(SWT.NORMAL); |
3619 |
renderer.setCurrentFontStyle(SWT.NORMAL); |
3610 |
return new GC(this); |
3620 |
return new GC(this); |
3611 |
} |
3621 |
} |
3612 |
/** |
3622 |
/** |
3613 |
* Returns the horizontal scroll increment. |
3623 |
* Returns the horizontal scroll increment. |
3614 |
* <p> |
3624 |
* <p> |
3615 |
* |
3625 |
* |
3616 |
* @return horizontal scroll increment. |
3626 |
* @return horizontal scroll increment. |
3617 |
*/ |
3627 |
*/ |
3618 |
int getHorizontalIncrement() { |
3628 |
int getHorizontalIncrement() { |
3619 |
GC gc = getGC(); |
3629 |
GC gc = getGC(); |
3620 |
int increment = gc.getFontMetrics().getAverageCharWidth(); |
3630 |
int increment = gc.getFontMetrics().getAverageCharWidth(); |
3621 |
|
3631 |
|
3622 |
gc.dispose(); |
3632 |
gc.dispose(); |
3623 |
return increment; |
3633 |
return increment; |
3624 |
} |
3634 |
} |
3625 |
/** |
3635 |
/** |
3626 |
* Returns the horizontal scroll offset relative to the start of the line. |
3636 |
* Returns the horizontal scroll offset relative to the start of the line. |
3627 |
* <p> |
3637 |
* <p> |
3628 |
* |
3638 |
* |
Lines 3633-3643
Link Here
|
3633 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3643 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3634 |
* </ul> |
3644 |
* </ul> |
3635 |
*/ |
3645 |
*/ |
3636 |
public int getHorizontalIndex() { |
3646 |
public int getHorizontalIndex() { |
3637 |
checkWidget(); |
3647 |
checkWidget(); |
3638 |
return horizontalScrollOffset / getHorizontalIncrement(); |
3648 |
return horizontalScrollOffset / getHorizontalIncrement(); |
3639 |
} |
3649 |
} |
3640 |
/** |
3650 |
/** |
3641 |
* Returns the horizontal scroll offset relative to the start of the line. |
3651 |
* Returns the horizontal scroll offset relative to the start of the line. |
3642 |
* <p> |
3652 |
* <p> |
3643 |
* |
3653 |
* |
Lines 3648-3686
Link Here
|
3648 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3658 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3649 |
* </ul> |
3659 |
* </ul> |
3650 |
*/ |
3660 |
*/ |
3651 |
public int getHorizontalPixel() { |
3661 |
public int getHorizontalPixel() { |
3652 |
checkWidget(); |
3662 |
checkWidget(); |
3653 |
return horizontalScrollOffset; |
3663 |
return horizontalScrollOffset; |
3654 |
} |
3664 |
} |
3655 |
/** |
3665 |
/** |
3656 |
* Returns the action assigned to the key. |
3666 |
* Returns the action assigned to the key. |
3657 |
* Returns SWT.NULL if there is no action associated with the key. |
3667 |
* Returns SWT.NULL if there is no action associated with the key. |
3658 |
* <p> |
3668 |
* <p> |
3659 |
* |
3669 |
* |
3660 |
* @param key a key code defined in SWT.java or a character. |
3670 |
* @param key a key code defined in SWT.java or a character. |
3661 |
* Optionally ORd with a state mask. Preferred state masks are one or more of |
3671 |
* Optionally ORd with a state mask. Preferred state masks are one or more of |
3662 |
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform |
3672 |
* SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform |
3663 |
* differences. However, there may be cases where using the specific state masks |
3673 |
* differences. However, there may be cases where using the specific state masks |
3664 |
* (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. |
3674 |
* (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. |
3665 |
* @return one of the predefined actions defined in ST.java or SWT.NULL |
3675 |
* @return one of the predefined actions defined in ST.java or SWT.NULL |
3666 |
* if there is no action associated with the key. |
3676 |
* if there is no action associated with the key. |
3667 |
* @exception SWTException <ul> |
3677 |
* @exception SWTException <ul> |
3668 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3678 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3669 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3679 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3670 |
* </ul> |
3680 |
* </ul> |
3671 |
*/ |
3681 |
*/ |
3672 |
public int getKeyBinding(int key) { |
3682 |
public int getKeyBinding(int key) { |
3673 |
checkWidget(); |
3683 |
checkWidget(); |
3674 |
Integer action = (Integer) keyActionMap.get(new Integer(key)); |
3684 |
Integer action = (Integer) keyActionMap.get(new Integer(key)); |
3675 |
int intAction; |
3685 |
int intAction; |
3676 |
|
3686 |
|
3677 |
if (action == null) { |
3687 |
if (action == null) { |
3678 |
intAction = SWT.NULL; |
3688 |
intAction = SWT.NULL; |
3679 |
} |
3689 |
} |
3680 |
else { |
3690 |
else { |
3681 |
intAction = action.intValue(); |
3691 |
intAction = action.intValue(); |
3682 |
} |
3692 |
} |
3683 |
return intAction; |
3693 |
return intAction; |
3684 |
} |
3694 |
} |
3685 |
/** |
3695 |
/** |
3686 |
* Gets the number of characters. |
3696 |
* Gets the number of characters. |
Lines 3693-3704
Link Here
|
3693 |
* </ul> |
3703 |
* </ul> |
3694 |
*/ |
3704 |
*/ |
3695 |
public int getCharCount() { |
3705 |
public int getCharCount() { |
3696 |
checkWidget(); |
3706 |
checkWidget(); |
3697 |
return content.getCharCount(); |
3707 |
return content.getCharCount(); |
3698 |
} |
3708 |
} |
3699 |
/** |
3709 |
/** |
3700 |
* Returns the background color of the line at the given index. |
3710 |
* Returns the background color of the line at the given index. |
3701 |
* Returns null if a LineBackgroundListener has been set or if no background |
3711 |
* Returns null if a LineBackgroundListener has been set or if no background |
3702 |
* color has been specified for the line. Should not be called if a |
3712 |
* color has been specified for the line. Should not be called if a |
3703 |
* LineBackgroundListener has been set since the listener maintains the |
3713 |
* LineBackgroundListener has been set since the listener maintains the |
3704 |
* line background colors. |
3714 |
* line background colors. |
Lines 3714-3743
Link Here
|
3714 |
* </ul> |
3724 |
* </ul> |
3715 |
*/ |
3725 |
*/ |
3716 |
public Color getLineBackground(int index) { |
3726 |
public Color getLineBackground(int index) { |
3717 |
checkWidget(); |
3727 |
checkWidget(); |
3718 |
Color lineBackground = null; |
3728 |
Color lineBackground = null; |
3719 |
|
3729 |
|
3720 |
if (index < 0 || index > logicalContent.getLineCount()) { |
3730 |
if (index < 0 || index > logicalContent.getLineCount()) { |
3721 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
3731 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
3722 |
} |
3732 |
} |
3723 |
if (userLineBackground == false) { |
3733 |
if (userLineBackground == false) { |
3724 |
lineBackground = defaultLineStyler.getLineBackground(index); |
3734 |
lineBackground = defaultLineStyler.getLineBackground(index); |
3725 |
} |
3735 |
} |
3726 |
return lineBackground; |
3736 |
return lineBackground; |
3727 |
} |
3737 |
} |
3728 |
/** |
3738 |
/** |
3729 |
* Returns the line background data for the given line or null if |
3739 |
* Returns the line background data for the given line or null if |
3730 |
* there is none. |
3740 |
* there is none. |
3731 |
* <p> |
3741 |
* <p> |
3732 |
* @param lineOffset offset of the line start relative to the start |
3742 |
* @param lineOffset offset of the line start relative to the start |
3733 |
* of the content. |
3743 |
* of the content. |
3734 |
* @param line line to get line background data for |
3744 |
* @param line line to get line background data for |
3735 |
* @return line background data for the given line. |
3745 |
* @return line background data for the given line. |
3736 |
*/ |
3746 |
*/ |
3737 |
StyledTextEvent getLineBackgroundData(int lineOffset, String line) { |
3747 |
StyledTextEvent getLineBackgroundData(int lineOffset, String line) { |
3738 |
return sendLineEvent(LineGetBackground, lineOffset, line); |
3748 |
return sendLineEvent(LineGetBackground, lineOffset, line); |
3739 |
} |
3749 |
} |
3740 |
/** |
3750 |
/** |
3741 |
* Gets the number of text lines. |
3751 |
* Gets the number of text lines. |
3742 |
* <p> |
3752 |
* <p> |
3743 |
* |
3753 |
* |
Lines 3748-3774
Link Here
|
3748 |
* </ul> |
3758 |
* </ul> |
3749 |
*/ |
3759 |
*/ |
3750 |
public int getLineCount() { |
3760 |
public int getLineCount() { |
3751 |
checkWidget(); |
3761 |
checkWidget(); |
3752 |
return getLineAtOffset(getCharCount()) + 1; |
3762 |
return getLineAtOffset(getCharCount()) + 1; |
3753 |
} |
3763 |
} |
3754 |
/** |
3764 |
/** |
3755 |
* Returns the number of lines that can be completely displayed in the |
3765 |
* Returns the number of lines that can be completely displayed in the |
3756 |
* widget client area. |
3766 |
* widget client area. |
3757 |
* <p> |
3767 |
* <p> |
3758 |
* |
3768 |
* |
3759 |
* @return number of lines that can be completely displayed in the widget |
3769 |
* @return number of lines that can be completely displayed in the widget |
3760 |
* client area. |
3770 |
* client area. |
3761 |
*/ |
3771 |
*/ |
3762 |
int getLineCountWhole() { |
3772 |
int getLineCountWhole() { |
3763 |
int lineCount; |
3773 |
int lineCount; |
3764 |
|
3774 |
|
3765 |
if (lineHeight != 0) { |
3775 |
if (lineHeight != 0) { |
3766 |
lineCount = getClientArea().height / lineHeight; |
3776 |
lineCount = getClientArea().height / lineHeight; |
3767 |
} |
3777 |
} |
3768 |
else { |
3778 |
else { |
3769 |
lineCount = 1; |
3779 |
lineCount = 1; |
3770 |
} |
3780 |
} |
3771 |
return lineCount; |
3781 |
return lineCount; |
3772 |
} |
3782 |
} |
3773 |
/** |
3783 |
/** |
3774 |
* Returns the line at the specified offset in the text. |
3784 |
* Returns the line at the specified offset in the text. |
Lines 3776-3799
Link Here
|
3776 |
* returns the line of the insert location. |
3786 |
* returns the line of the insert location. |
3777 |
* <p> |
3787 |
* <p> |
3778 |
* |
3788 |
* |
3779 |
* @param offset offset relative to the start of the content. |
3789 |
* @param offset offset relative to the start of the content. |
3780 |
* 0 <= offset <= getCharCount() |
3790 |
* 0 <= offset <= getCharCount() |
3781 |
* @return line at the specified offset in the text |
3791 |
* @return line at the specified offset in the text |
3782 |
* @exception SWTException <ul> |
3792 |
* @exception SWTException <ul> |
3783 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3793 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3784 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3794 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3785 |
* </ul> |
3795 |
* </ul> |
3786 |
* @exception IllegalArgumentException <ul> |
3796 |
* @exception IllegalArgumentException <ul> |
3787 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3797 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3788 |
* </ul> |
3798 |
* </ul> |
3789 |
*/ |
3799 |
*/ |
3790 |
public int getLineAtOffset(int offset) { |
3800 |
public int getLineAtOffset(int offset) { |
3791 |
checkWidget(); |
3801 |
checkWidget(); |
3792 |
|
3802 |
|
3793 |
if (offset < 0 || offset > getCharCount()) { |
3803 |
if (offset < 0 || offset > getCharCount()) { |
3794 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3804 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3795 |
} |
3805 |
} |
3796 |
return logicalContent.getLineAtOffset(offset); |
3806 |
return logicalContent.getLineAtOffset(offset); |
3797 |
} |
3807 |
} |
3798 |
/** |
3808 |
/** |
3799 |
* Returns the line delimiter used for entering new lines by key down |
3809 |
* Returns the line delimiter used for entering new lines by key down |
Lines 3808-3850
Link Here
|
3808 |
* </ul> |
3818 |
* </ul> |
3809 |
*/ |
3819 |
*/ |
3810 |
public String getLineDelimiter() { |
3820 |
public String getLineDelimiter() { |
3811 |
checkWidget(); |
3821 |
checkWidget(); |
3812 |
return content.getLineDelimiter(); |
3822 |
return content.getLineDelimiter(); |
3813 |
} |
3823 |
} |
3814 |
/** |
3824 |
/** |
3815 |
* Returns a StyledTextEvent that can be used to request data such |
3825 |
* Returns a StyledTextEvent that can be used to request data such |
3816 |
* as styles and background color for a line. |
3826 |
* as styles and background color for a line. |
3817 |
* The specified line may be a visual (wrapped) line if in word |
3827 |
* The specified line may be a visual (wrapped) line if in word |
3818 |
* wrap mode. The returned object will always be for a logical |
3828 |
* wrap mode. The returned object will always be for a logical |
3819 |
* (unwrapped) line. |
3829 |
* (unwrapped) line. |
3820 |
* <p> |
3830 |
* <p> |
3821 |
* |
3831 |
* |
3822 |
* @param lineOffset offset of the line. This may be the offset of |
3832 |
* @param lineOffset offset of the line. This may be the offset of |
3823 |
* a visual line if the widget is in word wrap mode. |
3833 |
* a visual line if the widget is in word wrap mode. |
3824 |
* @param line line text. This may be the text of a visualline if |
3834 |
* @param line line text. This may be the text of a visualline if |
3825 |
* the widget is in word wrap mode. |
3835 |
* the widget is in word wrap mode. |
3826 |
* @return StyledTextEvent that can be used to request line data |
3836 |
* @return StyledTextEvent that can be used to request line data |
3827 |
* for the given line. |
3837 |
* for the given line. |
3828 |
*/ |
3838 |
*/ |
3829 |
StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { |
3839 |
StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { |
3830 |
StyledTextEvent event = null; |
3840 |
StyledTextEvent event = null; |
3831 |
|
3841 |
|
3832 |
if (isListening(eventType)) { |
3842 |
if (isListening(eventType)) { |
3833 |
event = new StyledTextEvent(logicalContent); |
3843 |
event = new StyledTextEvent(logicalContent); |
3834 |
if (wordWrap) { |
3844 |
if (wordWrap) { |
3835 |
// if word wrap is on, the line offset and text may be visual (wrapped) |
3845 |
// if word wrap is on, the line offset and text may be visual (wrapped) |
3836 |
int lineIndex = logicalContent.getLineAtOffset(lineOffset); |
3846 |
int lineIndex = logicalContent.getLineAtOffset(lineOffset); |
3837 |
|
3847 |
|
3838 |
event.detail = logicalContent.getOffsetAtLine(lineIndex); |
3848 |
event.detail = logicalContent.getOffsetAtLine(lineIndex); |
3839 |
event.text = logicalContent.getLine(lineIndex); |
3849 |
event.text = logicalContent.getLine(lineIndex); |
3840 |
} |
3850 |
} |
3841 |
else { |
3851 |
else { |
3842 |
event.detail = lineOffset; |
3852 |
event.detail = lineOffset; |
3843 |
event.text = line; |
3853 |
event.text = line; |
3844 |
} |
3854 |
} |
3845 |
notifyListeners(eventType, event); |
3855 |
notifyListeners(eventType, event); |
3846 |
} |
3856 |
} |
3847 |
return event; |
3857 |
return event; |
3848 |
} |
3858 |
} |
3849 |
/** |
3859 |
/** |
3850 |
* Returns the line height. |
3860 |
* Returns the line height. |
Lines 3857-3964
Link Here
|
3857 |
* </ul> |
3867 |
* </ul> |
3858 |
*/ |
3868 |
*/ |
3859 |
public int getLineHeight() { |
3869 |
public int getLineHeight() { |
3860 |
checkWidget(); |
3870 |
checkWidget(); |
3861 |
return lineHeight; |
3871 |
return lineHeight; |
3862 |
} |
3872 |
} |
3863 |
/** |
3873 |
/** |
3864 |
* Returns a LineCache implementation. Depending on whether or not |
3874 |
* Returns a LineCache implementation. Depending on whether or not |
3865 |
* word wrap is on this may be a line wrapping or line width |
3875 |
* word wrap is on this may be a line wrapping or line width |
3866 |
* calculating implementaiton. |
3876 |
* calculating implementaiton. |
3867 |
* <p> |
3877 |
* <p> |
3868 |
* |
3878 |
* |
3869 |
* @param content StyledTextContent to create the LineCache on. |
3879 |
* @param content StyledTextContent to create the LineCache on. |
3870 |
* @return a LineCache implementation |
3880 |
* @return a LineCache implementation |
3871 |
*/ |
3881 |
*/ |
3872 |
LineCache getLineCache(StyledTextContent content) { |
3882 |
LineCache getLineCache(StyledTextContent content) { |
3873 |
LineCache lineCache; |
3883 |
LineCache lineCache; |
3874 |
|
3884 |
|
3875 |
if (wordWrap) { |
3885 |
if (wordWrap) { |
3876 |
lineCache = new WordWrapCache(this, (WrappedContent) content); |
3886 |
lineCache = new WordWrapCache(this, (WrappedContent) content); |
3877 |
} |
3887 |
} |
3878 |
else { |
3888 |
else { |
3879 |
lineCache = new ContentWidthCache(this, content.getLineCount()); |
3889 |
lineCache = new ContentWidthCache(this, content.getLineCount()); |
3880 |
} |
3890 |
} |
3881 |
return lineCache; |
3891 |
return lineCache; |
3882 |
} |
3892 |
} |
3883 |
/** |
3893 |
/** |
3884 |
* Returns the line style data for the given line or null if there is |
3894 |
* Returns the line style data for the given line or null if there is |
3885 |
* none. If there is a LineStyleListener but it does not set any styles, |
3895 |
* none. If there is a LineStyleListener but it does not set any styles, |
3886 |
* the StyledTextEvent.styles field will be initialized to an empty |
3896 |
* the StyledTextEvent.styles field will be initialized to an empty |
3887 |
* array. |
3897 |
* array. |
3888 |
* <p> |
3898 |
* <p> |
3889 |
* |
3899 |
* |
3890 |
* @param lineOffset offset of the line start relative to the start of |
3900 |
* @param lineOffset offset of the line start relative to the start of |
3891 |
* the content. |
3901 |
* the content. |
3892 |
* @param line line to get line styles for |
3902 |
* @param line line to get line styles for |
3893 |
* @return line style data for the given line. Styles may start before |
3903 |
* @return line style data for the given line. Styles may start before |
3894 |
* line start and end after line end |
3904 |
* line start and end after line end |
3895 |
*/ |
3905 |
*/ |
3896 |
StyledTextEvent getLineStyleData(int lineOffset, String line) { |
3906 |
StyledTextEvent getLineStyleData(int lineOffset, String line) { |
3897 |
return sendLineEvent(LineGetStyle, lineOffset, line); |
3907 |
return sendLineEvent(LineGetStyle, lineOffset, line); |
3898 |
} |
3908 |
} |
3899 |
/** |
3909 |
/** |
3900 |
* Returns the x, y location of the upper left corner of the character |
3910 |
* Returns the x, y location of the upper left corner of the character |
3901 |
* bounding box at the specified offset in the text. The point is |
3911 |
* bounding box at the specified offset in the text. The point is |
3902 |
* relative to the upper left corner of the widget client area. |
3912 |
* relative to the upper left corner of the widget client area. |
3903 |
* <p> |
3913 |
* <p> |
3904 |
* |
3914 |
* |
3905 |
* @param offset offset relative to the start of the content. |
3915 |
* @param offset offset relative to the start of the content. |
3906 |
* 0 <= offset <= getCharCount() |
3916 |
* 0 <= offset <= getCharCount() |
3907 |
* @return x, y location of the upper left corner of the character |
3917 |
* @return x, y location of the upper left corner of the character |
3908 |
* bounding box at the specified offset in the text. |
3918 |
* bounding box at the specified offset in the text. |
3909 |
* @exception SWTException <ul> |
3919 |
* @exception SWTException <ul> |
3910 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3920 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3911 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3921 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3912 |
* </ul> |
3922 |
* </ul> |
3913 |
* @exception IllegalArgumentException <ul> |
3923 |
* @exception IllegalArgumentException <ul> |
3914 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3924 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3915 |
* </ul> |
3925 |
* </ul> |
3916 |
*/ |
3926 |
*/ |
3917 |
public Point getLocationAtOffset(int offset) { |
3927 |
public Point getLocationAtOffset(int offset) { |
3918 |
checkWidget(); |
3928 |
checkWidget(); |
3919 |
if (offset < 0 || offset > getCharCount()) { |
3929 |
if (offset < 0 || offset > getCharCount()) { |
3920 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3930 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3921 |
} |
3931 |
} |
3922 |
int line = content.getLineAtOffset(offset); |
3932 |
int line = content.getLineAtOffset(offset); |
3923 |
int lineOffset = content.getOffsetAtLine(line); |
3933 |
int lineOffset = content.getOffsetAtLine(line); |
3924 |
String lineContent = content.getLine(line); |
3934 |
String lineContent = content.getLine(line); |
3925 |
int x = getXAtOffset(lineContent, line, offset - lineOffset); |
3935 |
int x = getXAtOffset(lineContent, line, offset - lineOffset); |
3926 |
int y = line * lineHeight - verticalScrollOffset; |
3936 |
int y = line * lineHeight - verticalScrollOffset; |
3927 |
|
3937 |
|
3928 |
return new Point(x, y); |
3938 |
return new Point(x, y); |
3929 |
} |
3939 |
} |
3930 |
/** |
3940 |
/** |
3931 |
* Returns the character offset of the first character of the given line. |
3941 |
* Returns the character offset of the first character of the given line. |
3932 |
* <p> |
3942 |
* <p> |
3933 |
* |
3943 |
* |
3934 |
* @param lineIndex index of the line, 0 based relative to the first |
3944 |
* @param lineIndex index of the line, 0 based relative to the first |
3935 |
* line in the content. 0 <= lineIndex < getLineCount(), except |
3945 |
* line in the content. 0 <= lineIndex < getLineCount(), except |
3936 |
* lineIndex may always be 0 |
3946 |
* lineIndex may always be 0 |
3937 |
* @return offset offset of the first character of the line, relative to |
3947 |
* @return offset offset of the first character of the line, relative to |
3938 |
* the beginning of the document. The first character of the document is |
3948 |
* the beginning of the document. The first character of the document is |
3939 |
* at offset 0. |
3949 |
* at offset 0. |
3940 |
* When there are not any lines, getOffsetAtLine(0) is a valid call that |
3950 |
* When there are not any lines, getOffsetAtLine(0) is a valid call that |
3941 |
* answers 0. |
3951 |
* answers 0. |
3942 |
* @exception SWTException <ul> |
3952 |
* @exception SWTException <ul> |
3943 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3953 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3944 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3954 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3945 |
* </ul> |
3955 |
* </ul> |
3946 |
* @exception IllegalArgumentException <ul> |
3956 |
* @exception IllegalArgumentException <ul> |
3947 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3957 |
* <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> |
3948 |
* </ul> |
3958 |
* </ul> |
3949 |
* @since 2.0 |
3959 |
* @since 2.0 |
3950 |
*/ |
3960 |
*/ |
3951 |
public int getOffsetAtLine(int lineIndex) { |
3961 |
public int getOffsetAtLine(int lineIndex) { |
3952 |
checkWidget(); |
3962 |
checkWidget(); |
3953 |
|
3963 |
|
3954 |
if (lineIndex < 0 || |
3964 |
if (lineIndex < 0 || |
3955 |
(lineIndex > 0 && lineIndex >= logicalContent.getLineCount())) { |
3965 |
(lineIndex > 0 && lineIndex >= logicalContent.getLineCount())) { |
3956 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3966 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
3957 |
} |
3967 |
} |
3958 |
return logicalContent.getOffsetAtLine(lineIndex); |
3968 |
return logicalContent.getOffsetAtLine(lineIndex); |
3959 |
} |
3969 |
} |
3960 |
/** |
3970 |
/** |
3961 |
* Returns the offset of the character at the given location relative |
3971 |
* Returns the offset of the character at the given location relative |
3962 |
* to the first character in the document. |
3972 |
* to the first character in the document. |
3963 |
* The return value reflects the character offset that the caret will |
3973 |
* The return value reflects the character offset that the caret will |
3964 |
* be placed at if a mouse click occurred at the specified location. |
3974 |
* be placed at if a mouse click occurred at the specified location. |
Lines 3966-3975
Link Here
|
3966 |
* the returned offset will be behind the character. |
3976 |
* the returned offset will be behind the character. |
3967 |
* <p> |
3977 |
* <p> |
3968 |
* |
3978 |
* |
3969 |
* @param point the origin of character bounding box relative to |
3979 |
* @param point the origin of character bounding box relative to |
3970 |
* the origin of the widget client area. |
3980 |
* the origin of the widget client area. |
3971 |
* @return offset of the character at the given location relative |
3981 |
* @return offset of the character at the given location relative |
3972 |
* to the first character in the document. |
3982 |
* to the first character in the document. |
3973 |
* @exception SWTException <ul> |
3983 |
* @exception SWTException <ul> |
3974 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3984 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
3975 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
3985 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
Lines 3980-4127
Link Here
|
3980 |
* </ul> |
3990 |
* </ul> |
3981 |
*/ |
3991 |
*/ |
3982 |
public int getOffsetAtLocation(Point point) { |
3992 |
public int getOffsetAtLocation(Point point) { |
3983 |
checkWidget(); |
3993 |
checkWidget(); |
3984 |
int line; |
3994 |
int line; |
3985 |
int lineOffset; |
3995 |
int lineOffset; |
3986 |
int offsetInLine; |
3996 |
int offsetInLine; |
3987 |
String lineText; |
3997 |
String lineText; |
3988 |
|
3998 |
|
3989 |
if (point == null) { |
3999 |
if (point == null) { |
3990 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
4000 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
3991 |
} |
4001 |
} |
3992 |
// is y above first line or is x before first column? |
4002 |
// is y above first line or is x before first column? |
3993 |
if (point.y + verticalScrollOffset < 0 || point.x + horizontalScrollOffset < 0) { |
4003 |
if (point.y + verticalScrollOffset < 0 || point.x + horizontalScrollOffset < 0) { |
3994 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4004 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
3995 |
} |
4005 |
} |
3996 |
line = (getTopPixel() + point.y) / lineHeight; |
4006 |
line = (getTopPixel() + point.y) / lineHeight; |
3997 |
// does the referenced line exist? |
4007 |
// does the referenced line exist? |
3998 |
if (line >= content.getLineCount()) { |
4008 |
if (line >= content.getLineCount()) { |
3999 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4009 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4000 |
} |
4010 |
} |
4001 |
lineText = content.getLine(line); |
4011 |
lineText = content.getLine(line); |
4002 |
lineOffset = content.getOffsetAtLine(line); |
4012 |
lineOffset = content.getOffsetAtLine(line); |
4003 |
offsetInLine = getOffsetAtX(lineText, lineOffset, point.x); |
4013 |
offsetInLine = getOffsetAtX(lineText, lineOffset, point.x); |
4004 |
// is the x position within the line? |
4014 |
// is the x position within the line? |
4005 |
if (offsetInLine == -1) { |
4015 |
if (offsetInLine == -1) { |
4006 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4016 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4007 |
} |
4017 |
} |
4008 |
return lineOffset + offsetInLine; |
4018 |
return lineOffset + offsetInLine; |
4009 |
} |
4019 |
} |
4010 |
/** |
4020 |
/** |
4011 |
* Returns the offset at the specified x location in the specified line. |
4021 |
* Returns the offset at the specified x location in the specified line. |
4012 |
* <p> |
4022 |
* <p> |
4013 |
* |
4023 |
* |
4014 |
* @param x x location of the mouse location |
4024 |
* @param x x location of the mouse location |
4015 |
* @param line line the mouse location is in |
4025 |
* @param line line the mouse location is in |
4016 |
* @return the offset at the specified x location in the specified line, |
4026 |
* @return the offset at the specified x location in the specified line, |
4017 |
* relative to the beginning of the document |
4027 |
* relative to the beginning of the document |
4018 |
*/ |
4028 |
*/ |
4019 |
int getOffsetAtMouseLocation(int x, int line) { |
4029 |
int getOffsetAtMouseLocation(int x, int line) { |
4020 |
String lineText = content.getLine(line); |
4030 |
String lineText = content.getLine(line); |
4021 |
int lineOffset = content.getOffsetAtLine(line); |
4031 |
int lineOffset = content.getOffsetAtLine(line); |
4022 |
int offsetInLine = getCaretOffsetAtX(lineText, lineOffset, x); |
4032 |
int offsetInLine = getCaretOffsetAtX(lineText, lineOffset, x); |
4023 |
return lineOffset + offsetInLine; |
4033 |
return lineOffset + offsetInLine; |
4024 |
} |
4034 |
} |
4025 |
/** |
4035 |
/** |
4026 |
* Returns the offset of the character at the given x location in the line. |
4036 |
* Returns the offset of the character at the given x location in the line. |
4027 |
* <p> |
4037 |
* <p> |
4028 |
* |
4038 |
* |
4029 |
* @param line text of the line to calculate the offset in |
4039 |
* @param line text of the line to calculate the offset in |
4030 |
* @param lineOffset offset of the first character in the line. |
4040 |
* @param lineOffset offset of the first character in the line. |
4031 |
* 0 based from the beginning of the document. |
4041 |
* 0 based from the beginning of the document. |
4032 |
* @param lineXOffset x location in the line |
4042 |
* @param lineXOffset x location in the line |
4033 |
* @return offset of the character at the x location relative to the start |
4043 |
* @return offset of the character at the x location relative to the start |
4034 |
* of the line. -1 if the x location is past the end if the line. |
4044 |
* of the line. -1 if the x location is past the end if the line. |
4035 |
*/ |
4045 |
*/ |
4036 |
int getOffsetAtX(String line, int lineOffset, int lineXOffset) { |
4046 |
int getOffsetAtX(String line, int lineOffset, int lineXOffset) { |
4037 |
GC gc = getGC(); |
4047 |
GC gc = getGC(); |
4038 |
int offset; |
4048 |
int offset; |
4039 |
|
4049 |
|
4040 |
lineXOffset += (horizontalScrollOffset - leftMargin); |
4050 |
lineXOffset += (horizontalScrollOffset - leftMargin); |
4041 |
if (isBidi()) { |
4051 |
if (isBidi()) { |
4042 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); |
4052 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); |
4043 |
offset = bidi.getOffsetAtX(lineXOffset); |
4053 |
offset = bidi.getOffsetAtX(lineXOffset); |
4044 |
} |
4054 |
} |
4045 |
else { |
4055 |
else { |
4046 |
StyleRange[] styles = null; |
4056 |
StyleRange[] styles = null; |
4047 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
4057 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
4048 |
|
4058 |
|
4049 |
if (event != null) { |
4059 |
if (event != null) { |
4050 |
styles = renderer.filterLineStyles(event.styles); |
4060 |
styles = renderer.filterLineStyles(event.styles); |
4051 |
} |
4061 |
} |
4052 |
int low = -1; |
4062 |
int low = -1; |
4053 |
int high = line.length(); |
4063 |
int high = line.length(); |
4054 |
while (high - low > 1) { |
4064 |
while (high - low > 1) { |
4055 |
offset = (high + low) / 2; |
4065 |
offset = (high + low) / 2; |
4056 |
// Restrict right/high search boundary only if x is within searched text segment. |
4066 |
// Restrict right/high search boundary only if x is within searched text segment. |
4057 |
// Fixes 1GL4ZVE. |
4067 |
// Fixes 1GL4ZVE. |
4058 |
if (lineXOffset < renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc)) { |
4068 |
if (lineXOffset < renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc)) { |
4059 |
high = offset; |
4069 |
high = offset; |
4060 |
} |
4070 |
} |
4061 |
else |
4071 |
else |
4062 |
if (high == line.length() && high - offset == 1) { |
4072 |
if (high == line.length() && high - offset == 1) { |
4063 |
// requested x location is past end of line |
4073 |
// requested x location is past end of line |
4064 |
high = -1; |
4074 |
high = -1; |
4065 |
} |
4075 |
} |
4066 |
else { |
4076 |
else { |
4067 |
low = offset; |
4077 |
low = offset; |
4068 |
} |
4078 |
} |
4069 |
} |
4079 |
} |
4070 |
offset = high; |
4080 |
offset = high; |
4071 |
} |
4081 |
} |
4072 |
gc.dispose(); |
4082 |
gc.dispose(); |
4073 |
return offset; |
4083 |
return offset; |
4074 |
} |
4084 |
} |
4075 |
/** |
4085 |
/** |
4076 |
* Returns the index of the last partially visible line. |
4086 |
* Returns the index of the last partially visible line. |
4077 |
* |
4087 |
* |
4078 |
* @return index of the last partially visible line. |
4088 |
* @return index of the last partially visible line. |
4079 |
*/ |
4089 |
*/ |
4080 |
int getPartialBottomIndex() { |
4090 |
int getPartialBottomIndex() { |
4081 |
int partialLineCount = Compatibility.ceil(getClientArea().height, lineHeight); |
4091 |
int partialLineCount = Compatibility.ceil(getClientArea().height, lineHeight); |
4082 |
return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; |
4092 |
return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; |
4083 |
} |
4093 |
} |
4084 |
/** |
4094 |
/** |
4085 |
* Returns the content in the specified range using the platform line |
4095 |
* Returns the content in the specified range using the platform line |
4086 |
* delimiter to separate lines. |
4096 |
* delimiter to separate lines. |
4087 |
* <p> |
4097 |
* <p> |
4088 |
* |
4098 |
* |
4089 |
* @param writer the TextWriter to write line text into |
4099 |
* @param writer the TextWriter to write line text into |
4090 |
* @return the content in the specified range using the platform line |
4100 |
* @return the content in the specified range using the platform line |
4091 |
* delimiter to separate lines as written by the specified TextWriter. |
4101 |
* delimiter to separate lines as written by the specified TextWriter. |
4092 |
*/ |
4102 |
*/ |
4093 |
String getPlatformDelimitedText(TextWriter writer) { |
4103 |
String getPlatformDelimitedText(TextWriter writer) { |
4094 |
int end = writer.getStart() + writer.getCharCount(); |
4104 |
int end = writer.getStart() + writer.getCharCount(); |
4095 |
int startLine = logicalContent.getLineAtOffset(writer.getStart()); |
4105 |
int startLine = logicalContent.getLineAtOffset(writer.getStart()); |
4096 |
int endLine = logicalContent.getLineAtOffset(end); |
4106 |
int endLine = logicalContent.getLineAtOffset(end); |
4097 |
String endLineText = logicalContent.getLine(endLine); |
4107 |
String endLineText = logicalContent.getLine(endLine); |
4098 |
int endLineOffset = logicalContent.getOffsetAtLine(endLine); |
4108 |
int endLineOffset = logicalContent.getOffsetAtLine(endLine); |
4099 |
|
4109 |
|
4100 |
for (int i = startLine; i <= endLine; i++) { |
4110 |
for (int i = startLine; i <= endLine; i++) { |
4101 |
writer.writeLine(logicalContent.getLine(i), logicalContent.getOffsetAtLine(i)); |
4111 |
writer.writeLine(logicalContent.getLine(i), logicalContent.getOffsetAtLine(i)); |
4102 |
if (i < endLine) { |
4112 |
if (i < endLine) { |
4103 |
writer.writeLineDelimiter(PlatformLineDelimiter); |
4113 |
writer.writeLineDelimiter(PlatformLineDelimiter); |
4104 |
} |
4114 |
} |
4105 |
} |
4115 |
} |
4106 |
if (end > endLineOffset + endLineText.length()) { |
4116 |
if (end > endLineOffset + endLineText.length()) { |
4107 |
writer.writeLineDelimiter(PlatformLineDelimiter); |
4117 |
writer.writeLineDelimiter(PlatformLineDelimiter); |
4108 |
} |
4118 |
} |
4109 |
writer.close(); |
4119 |
writer.close(); |
4110 |
return writer.toString(); |
4120 |
return writer.toString(); |
4111 |
} |
4121 |
} |
4112 |
/** |
4122 |
/** |
4113 |
* Returns the selection. |
4123 |
* Returns the selection. |
4114 |
* <p> |
4124 |
* <p> |
4115 |
* Text selections are specified in terms of caret positions. In a text |
4125 |
* Text selections are specified in terms of caret positions. In a text |
4116 |
* widget that contains N characters, there are N+1 caret positions, |
4126 |
* widget that contains N characters, there are N+1 caret positions, |
4117 |
* ranging from 0..N |
4127 |
* ranging from 0..N |
4118 |
* <p> |
4128 |
* <p> |
4119 |
* |
4129 |
* |
4120 |
* @return start and end of the selection, x is the offset of the first |
4130 |
* @return start and end of the selection, x is the offset of the first |
4121 |
* selected character, y is the offset after the last selected character. |
4131 |
* selected character, y is the offset after the last selected character. |
4122 |
* The selection values returned are visual (i.e., x will always always be |
4132 |
* The selection values returned are visual (i.e., x will always always be |
4123 |
* <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4133 |
* <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4124 |
* (LtoR), compare the caretOffset to the start and end of the selection |
4134 |
* (LtoR), compare the caretOffset to the start and end of the selection |
4125 |
* (e.g., caretOffset == start of selection implies that the selection is RtoL). |
4135 |
* (e.g., caretOffset == start of selection implies that the selection is RtoL). |
4126 |
* @see #getSelectionRange |
4136 |
* @see #getSelectionRange |
4127 |
* @exception SWTException <ul> |
4137 |
* @exception SWTException <ul> |
Lines 4130-4148
Link Here
|
4130 |
* </ul> |
4140 |
* </ul> |
4131 |
*/ |
4141 |
*/ |
4132 |
public Point getSelection() { |
4142 |
public Point getSelection() { |
4133 |
checkWidget(); |
4143 |
checkWidget(); |
4134 |
return new Point(selection.x, selection.y); |
4144 |
return new Point(selection.x, selection.y); |
4135 |
} |
4145 |
} |
4136 |
/** |
4146 |
/** |
4137 |
* Returns the selection. |
4147 |
* Returns the selection. |
4138 |
* <p> |
4148 |
* <p> |
4139 |
* |
4149 |
* |
4140 |
* @return start and length of the selection, x is the offset of the |
4150 |
* @return start and length of the selection, x is the offset of the |
4141 |
* first selected character, relative to the first character of the |
4151 |
* first selected character, relative to the first character of the |
4142 |
* widget content. y is the length of the selection. |
4152 |
* widget content. y is the length of the selection. |
4143 |
* The selection values returned are visual (i.e., length will always always be |
4153 |
* The selection values returned are visual (i.e., length will always always be |
4144 |
* positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4154 |
* positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right |
4145 |
* (LtoR), compare the caretOffset to the start and end of the selection |
4155 |
* (LtoR), compare the caretOffset to the start and end of the selection |
4146 |
* (e.g., caretOffset == start of selection implies that the selection is RtoL). |
4156 |
* (e.g., caretOffset == start of selection implies that the selection is RtoL). |
4147 |
* @exception SWTException <ul> |
4157 |
* @exception SWTException <ul> |
4148 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4158 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 4150-4157
Link Here
|
4150 |
* </ul> |
4160 |
* </ul> |
4151 |
*/ |
4161 |
*/ |
4152 |
public Point getSelectionRange() { |
4162 |
public Point getSelectionRange() { |
4153 |
checkWidget(); |
4163 |
checkWidget(); |
4154 |
return new Point(selection.x, selection.y - selection.x); |
4164 |
return new Point(selection.x, selection.y - selection.x); |
4155 |
} |
4165 |
} |
4156 |
/** |
4166 |
/** |
4157 |
* Returns the receiver's selection background color. |
4167 |
* Returns the receiver's selection background color. |
Lines 4165-4175
Link Here
|
4165 |
* @since 2.1 |
4175 |
* @since 2.1 |
4166 |
*/ |
4176 |
*/ |
4167 |
public Color getSelectionBackground() { |
4177 |
public Color getSelectionBackground() { |
4168 |
checkWidget(); |
4178 |
checkWidget(); |
4169 |
if (selectionBackground == null) { |
4179 |
if (selectionBackground == null) { |
4170 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); |
4180 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); |
4171 |
} |
4181 |
} |
4172 |
return selectionBackground; |
4182 |
return selectionBackground; |
4173 |
} |
4183 |
} |
4174 |
/** |
4184 |
/** |
4175 |
* Gets the number of selected characters. |
4185 |
* Gets the number of selected characters. |
Lines 4182-4189
Link Here
|
4182 |
* </ul> |
4192 |
* </ul> |
4183 |
*/ |
4193 |
*/ |
4184 |
public int getSelectionCount() { |
4194 |
public int getSelectionCount() { |
4185 |
checkWidget(); |
4195 |
checkWidget(); |
4186 |
return getSelectionRange().y; |
4196 |
return getSelectionRange().y; |
4187 |
} |
4197 |
} |
4188 |
/** |
4198 |
/** |
4189 |
* Returns the receiver's selection foreground color. |
4199 |
* Returns the receiver's selection foreground color. |
Lines 4197-4207
Link Here
|
4197 |
* @since 2.1 |
4207 |
* @since 2.1 |
4198 |
*/ |
4208 |
*/ |
4199 |
public Color getSelectionForeground() { |
4209 |
public Color getSelectionForeground() { |
4200 |
checkWidget(); |
4210 |
checkWidget(); |
4201 |
if (selectionForeground == null) { |
4211 |
if (selectionForeground == null) { |
4202 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); |
4212 |
return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); |
4203 |
} |
4213 |
} |
4204 |
return selectionForeground; |
4214 |
return selectionForeground; |
4205 |
} |
4215 |
} |
4206 |
/** |
4216 |
/** |
4207 |
* Returns the selected text. |
4217 |
* Returns the selected text. |
Lines 4214-4342
Link Here
|
4214 |
* </ul> |
4224 |
* </ul> |
4215 |
*/ |
4225 |
*/ |
4216 |
public String getSelectionText() { |
4226 |
public String getSelectionText() { |
4217 |
checkWidget(); |
4227 |
checkWidget(); |
4218 |
return content.getTextRange(selection.x, selection.y - selection.x); |
4228 |
return content.getTextRange(selection.x, selection.y - selection.x); |
4219 |
} |
4229 |
} |
4220 |
/** |
4230 |
/** |
4221 |
* Returns the text segments that should be treated as if they |
4231 |
* Returns the text segments that should be treated as if they |
4222 |
* had a different direction than the surrounding text. |
4232 |
* had a different direction than the surrounding text. |
4223 |
* <p> |
4233 |
* <p> |
4224 |
* |
4234 |
* |
4225 |
* @param lineOffset offset of the first character in the line. |
4235 |
* @param lineOffset offset of the first character in the line. |
4226 |
* 0 based from the beginning of the document. |
4236 |
* 0 based from the beginning of the document. |
4227 |
* @param line text of the line to specify bidi segments for |
4237 |
* @param line text of the line to specify bidi segments for |
4228 |
* @return text segments that should be treated as if they had a |
4238 |
* @return text segments that should be treated as if they had a |
4229 |
* different direction than the surrounding text. Only the start |
4239 |
* different direction than the surrounding text. Only the start |
4230 |
* index of a segment is specified, relative to the start of the |
4240 |
* index of a segment is specified, relative to the start of the |
4231 |
* line. Always starts with 0 and ends with the line length. |
4241 |
* line. Always starts with 0 and ends with the line length. |
4232 |
* @exception IllegalArgumentException <ul> |
4242 |
* @exception IllegalArgumentException <ul> |
4233 |
* <li>ERROR_INVALID_ARGUMENT - if the segment indices returned |
4243 |
* <li>ERROR_INVALID_ARGUMENT - if the segment indices returned |
4234 |
* by the listener do not start with 0, are not in ascending order, |
4244 |
* by the listener do not start with 0, are not in ascending order, |
4235 |
* exceed the line length or have duplicates</li> |
4245 |
* exceed the line length or have duplicates</li> |
4236 |
* </ul> |
4246 |
* </ul> |
4237 |
*/ |
4247 |
*/ |
4238 |
int [] getBidiSegments(int lineOffset, String line) { |
4248 |
int [] getBidiSegments(int lineOffset, String line) { |
4239 |
if (isListening(LineGetSegments) == false) { |
4249 |
if (isListening(LineGetSegments) == false) { |
4240 |
return getBidiSegmentsCompatibility(line, lineOffset); |
4250 |
return getBidiSegmentsCompatibility(line, lineOffset); |
4241 |
} |
4251 |
} |
4242 |
StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); |
4252 |
StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); |
4243 |
int lineLength = line.length(); |
4253 |
int lineLength = line.length(); |
4244 |
int[] segments; |
4254 |
int[] segments; |
4245 |
if (event == null || event.segments == null || event.segments.length == 0) { |
4255 |
if (event == null || event.segments == null || event.segments.length == 0) { |
4246 |
segments = new int[] {0, lineLength}; |
4256 |
segments = new int[] {0, lineLength}; |
4247 |
} |
4257 |
} |
4248 |
else { |
4258 |
else { |
4249 |
int segmentCount = event.segments.length; |
4259 |
int segmentCount = event.segments.length; |
4250 |
|
4260 |
|
4251 |
// test segment index consistency |
4261 |
// test segment index consistency |
4252 |
if (event.segments[0] != 0) { |
4262 |
if (event.segments[0] != 0) { |
4253 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4263 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4254 |
} |
4264 |
} |
4255 |
for (int i = 1; i < segmentCount; i++) { |
4265 |
for (int i = 1; i < segmentCount; i++) { |
4256 |
if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { |
4266 |
if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { |
4257 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4267 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4258 |
} |
4268 |
} |
4259 |
} |
4269 |
} |
4260 |
// ensure that last segment index is line end offset |
4270 |
// ensure that last segment index is line end offset |
4261 |
if (event.segments[segmentCount - 1] != lineLength) { |
4271 |
if (event.segments[segmentCount - 1] != lineLength) { |
4262 |
segments = new int[segmentCount + 1]; |
4272 |
segments = new int[segmentCount + 1]; |
4263 |
System.arraycopy(event.segments, 0, segments, 0, segmentCount); |
4273 |
System.arraycopy(event.segments, 0, segments, 0, segmentCount); |
4264 |
segments[segmentCount] = lineLength; |
4274 |
segments[segmentCount] = lineLength; |
4265 |
} |
4275 |
} |
4266 |
else { |
4276 |
else { |
4267 |
segments = event.segments; |
4277 |
segments = event.segments; |
4268 |
} |
4278 |
} |
4269 |
} |
4279 |
} |
4270 |
return segments; |
4280 |
return segments; |
4271 |
} |
4281 |
} |
4272 |
/** |
4282 |
/** |
4273 |
* @see getBidiSegments |
4283 |
* @see getBidiSegments |
4274 |
* Supports deprecated setBidiColoring API. Remove when API is removed. |
4284 |
* Supports deprecated setBidiColoring API. Remove when API is removed. |
4275 |
*/ |
4285 |
*/ |
4276 |
int [] getBidiSegmentsCompatibility(String line, int lineOffset) { |
4286 |
int [] getBidiSegmentsCompatibility(String line, int lineOffset) { |
4277 |
StyledTextEvent event; |
4287 |
StyledTextEvent event; |
4278 |
StyleRange [] styles = new StyleRange [0]; |
4288 |
StyleRange [] styles = new StyleRange [0]; |
4279 |
int lineLength = line.length(); |
4289 |
int lineLength = line.length(); |
4280 |
if (bidiColoring == false) { |
4290 |
if (bidiColoring == false) { |
4281 |
return new int[] {0, lineLength}; |
4291 |
return new int[] {0, lineLength}; |
4282 |
} |
4292 |
} |
4283 |
event = renderer.getLineStyleData(lineOffset, line); |
4293 |
event = renderer.getLineStyleData(lineOffset, line); |
4284 |
if (event != null) { |
4294 |
if (event != null) { |
4285 |
styles = event.styles; |
4295 |
styles = event.styles; |
4286 |
} |
4296 |
} |
4287 |
if (styles.length == 0) { |
4297 |
if (styles.length == 0) { |
4288 |
return new int[] {0, lineLength}; |
4298 |
return new int[] {0, lineLength}; |
4289 |
} |
4299 |
} |
4290 |
int k=0, count = 1; |
4300 |
int k=0, count = 1; |
4291 |
while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) { |
4301 |
while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) { |
4292 |
k++; |
4302 |
k++; |
4293 |
} |
4303 |
} |
4294 |
int[] offsets = new int[(styles.length - k) * 2 + 2]; |
4304 |
int[] offsets = new int[(styles.length - k) * 2 + 2]; |
4295 |
for (int i = k; i < styles.length; i++) { |
4305 |
for (int i = k; i < styles.length; i++) { |
4296 |
StyleRange style = styles[i]; |
4306 |
StyleRange style = styles[i]; |
4297 |
int styleLineStart = Math.max(style.start - lineOffset, 0); |
4307 |
int styleLineStart = Math.max(style.start - lineOffset, 0); |
4298 |
int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); |
4308 |
int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); |
4299 |
styleLineEnd = Math.min (styleLineEnd, line.length ()); |
4309 |
styleLineEnd = Math.min (styleLineEnd, line.length ()); |
4300 |
if (i > 0 && count > 1 && |
4310 |
if (i > 0 && count > 1 && |
4301 |
((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || |
4311 |
((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || |
4302 |
(styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && |
4312 |
(styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && |
4303 |
style.similarTo(styles[i-1])) { |
4313 |
style.similarTo(styles[i-1])) { |
4304 |
offsets[count-2] = Math.min(offsets[count-2], styleLineStart); |
4314 |
offsets[count-2] = Math.min(offsets[count-2], styleLineStart); |
4305 |
offsets[count-1] = Math.max(offsets[count-1], styleLineEnd); |
4315 |
offsets[count-1] = Math.max(offsets[count-1], styleLineEnd); |
4306 |
} else { |
4316 |
} else { |
4307 |
if (styleLineStart > offsets[count - 1]) { |
4317 |
if (styleLineStart > offsets[count - 1]) { |
4308 |
offsets[count] = styleLineStart; |
4318 |
offsets[count] = styleLineStart; |
4309 |
count++; |
4319 |
count++; |
4310 |
} |
4320 |
} |
4311 |
offsets[count] = styleLineEnd; |
4321 |
offsets[count] = styleLineEnd; |
4312 |
count++; |
4322 |
count++; |
4313 |
} |
4323 |
} |
4314 |
} |
4324 |
} |
4315 |
// add offset for last non-colored segment in line, if any |
4325 |
// add offset for last non-colored segment in line, if any |
4316 |
if (lineLength > offsets[count-1]) { |
4326 |
if (lineLength > offsets[count-1]) { |
4317 |
offsets [count] = lineLength; |
4327 |
offsets [count] = lineLength; |
4318 |
count++; |
4328 |
count++; |
4319 |
} |
4329 |
} |
4320 |
if (count == offsets.length) { |
4330 |
if (count == offsets.length) { |
4321 |
return offsets; |
4331 |
return offsets; |
4322 |
} |
4332 |
} |
4323 |
int [] result = new int [count]; |
4333 |
int [] result = new int [count]; |
4324 |
System.arraycopy (offsets, 0, result, 0, count); |
4334 |
System.arraycopy (offsets, 0, result, 0, count); |
4325 |
return result; |
4335 |
return result; |
4326 |
} |
4336 |
} |
4327 |
/** |
4337 |
/** |
4328 |
* Returns the style range at the given offset. |
4338 |
* Returns the style range at the given offset. |
4329 |
* Returns null if a LineStyleListener has been set or if a style is not set |
4339 |
* Returns null if a LineStyleListener has been set or if a style is not set |
4330 |
* for the offset. |
4340 |
* for the offset. |
4331 |
* Should not be called if a LineStyleListener has been set since the |
4341 |
* Should not be called if a LineStyleListener has been set since the |
4332 |
* listener maintains the styles. |
4342 |
* listener maintains the styles. |
4333 |
* <p> |
4343 |
* <p> |
4334 |
* |
4344 |
* |
4335 |
* @param offset the offset to return the style for. |
4345 |
* @param offset the offset to return the style for. |
4336 |
* 0 <= offset < getCharCount() must be true. |
4346 |
* 0 <= offset < getCharCount() must be true. |
4337 |
* @return a StyleRange with start == offset and length == 1, indicating |
4347 |
* @return a StyleRange with start == offset and length == 1, indicating |
4338 |
* the style at the given offset. null if a LineStyleListener has been set |
4348 |
* the style at the given offset. null if a LineStyleListener has been set |
4339 |
* or if a style is not set for the given offset. |
4349 |
* or if a style is not set for the given offset. |
4340 |
* @exception SWTException <ul> |
4350 |
* @exception SWTException <ul> |
4341 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4351 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4342 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4352 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
Lines 4346-4364
Link Here
|
4346 |
* </ul> |
4356 |
* </ul> |
4347 |
*/ |
4357 |
*/ |
4348 |
public StyleRange getStyleRangeAtOffset(int offset) { |
4358 |
public StyleRange getStyleRangeAtOffset(int offset) { |
4349 |
checkWidget(); |
4359 |
checkWidget(); |
4350 |
if (offset < 0 || offset >= getCharCount()) { |
4360 |
if (offset < 0 || offset >= getCharCount()) { |
4351 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4361 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
4352 |
} |
4362 |
} |
4353 |
if (userLineStyle == false) { |
4363 |
if (userLineStyle == false) { |
4354 |
return defaultLineStyler.getStyleRangeAtOffset(offset); |
4364 |
return defaultLineStyler.getStyleRangeAtOffset(offset); |
4355 |
} |
4365 |
} |
4356 |
return null; |
4366 |
return null; |
4357 |
} |
4367 |
} |
4358 |
/** |
4368 |
/** |
4359 |
* Returns the styles. |
4369 |
* Returns the styles. |
4360 |
* Returns an empty array if a LineStyleListener has been set. |
4370 |
* Returns an empty array if a LineStyleListener has been set. |
4361 |
* Should not be called if a LineStyleListener has been set since the |
4371 |
* Should not be called if a LineStyleListener has been set since the |
4362 |
* listener maintains the styles. |
4372 |
* listener maintains the styles. |
4363 |
* <p> |
4373 |
* <p> |
4364 |
* |
4374 |
* |
Lines 4369-4415
Link Here
|
4369 |
* </ul> |
4379 |
* </ul> |
4370 |
*/ |
4380 |
*/ |
4371 |
public StyleRange [] getStyleRanges() { |
4381 |
public StyleRange [] getStyleRanges() { |
4372 |
checkWidget(); |
4382 |
checkWidget(); |
4373 |
StyleRange styles[]; |
4383 |
StyleRange styles[]; |
4374 |
|
4384 |
|
4375 |
if (userLineStyle == false) { |
4385 |
if (userLineStyle == false) { |
4376 |
styles = defaultLineStyler.getStyleRanges(); |
4386 |
styles = defaultLineStyler.getStyleRanges(); |
4377 |
} |
4387 |
} |
4378 |
else { |
4388 |
else { |
4379 |
styles = new StyleRange[0]; |
4389 |
styles = new StyleRange[0]; |
4380 |
} |
4390 |
} |
4381 |
return styles; |
4391 |
return styles; |
4382 |
} |
4392 |
} |
4383 |
/** |
4393 |
/** |
4384 |
* Returns a StyledTextBidi object for the specified line. |
4394 |
* Returns a StyledTextBidi object for the specified line. |
4385 |
* <p> |
4395 |
* <p> |
4386 |
* |
4396 |
* |
4387 |
* @param lineText the line that the StyledTextBidi object should |
4397 |
* @param lineText the line that the StyledTextBidi object should |
4388 |
* work on. |
4398 |
* work on. |
4389 |
* @param lineOffset offset of the beginning of the line, relative |
4399 |
* @param lineOffset offset of the beginning of the line, relative |
4390 |
* to the beginning of the document |
4400 |
* to the beginning of the document |
4391 |
* @param gc GC to use when creating a new StyledTextBidi object. |
4401 |
* @param gc GC to use when creating a new StyledTextBidi object. |
4392 |
* @return a StyledTextBidi object for the specified line. |
4402 |
* @return a StyledTextBidi object for the specified line. |
4393 |
*/ |
4403 |
*/ |
4394 |
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc) { |
4404 |
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc) { |
4395 |
return getStyledTextBidi(lineText, lineOffset, gc, null); |
4405 |
return getStyledTextBidi(lineText, lineOffset, gc, null); |
4396 |
} |
4406 |
} |
4397 |
/** |
4407 |
/** |
4398 |
* Returns a StyledTextBidi object for the specified line. |
4408 |
* Returns a StyledTextBidi object for the specified line. |
4399 |
* <p> |
4409 |
* <p> |
4400 |
* |
4410 |
* |
4401 |
* @param lineText the line that the StyledTextBidi object should |
4411 |
* @param lineText the line that the StyledTextBidi object should |
4402 |
* work on. |
4412 |
* work on. |
4403 |
* @param lineOffset offset of the beginning of the line, relative |
4413 |
* @param lineOffset offset of the beginning of the line, relative |
4404 |
* to the beginning of the document |
4414 |
* to the beginning of the document |
4405 |
* @param gc GC to use when creating a new StyledTextBidi object. |
4415 |
* @param gc GC to use when creating a new StyledTextBidi object. |
4406 |
* @param styles StyleRanges to use when creating a new StyledTextBidi |
4416 |
* @param styles StyleRanges to use when creating a new StyledTextBidi |
4407 |
* object. |
4417 |
* object. |
4408 |
* @return a StyledTextBidi object for the specified line. |
4418 |
* @return a StyledTextBidi object for the specified line. |
4409 |
*/ |
4419 |
*/ |
4410 |
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc, StyleRange[] styles) { |
4420 |
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc, StyleRange[] styles) { |
4411 |
return renderer.getStyledTextBidi(lineText, lineOffset, gc, styles); |
4421 |
return renderer.getStyledTextBidi(lineText, lineOffset, gc, styles); |
4412 |
} |
4422 |
} |
4413 |
/** |
4423 |
/** |
4414 |
* Returns the tab width measured in characters. |
4424 |
* Returns the tab width measured in characters. |
4415 |
* |
4425 |
* |
Lines 4420-4427
Link Here
|
4420 |
* </ul> |
4430 |
* </ul> |
4421 |
*/ |
4431 |
*/ |
4422 |
public int getTabs() { |
4432 |
public int getTabs() { |
4423 |
checkWidget(); |
4433 |
checkWidget(); |
4424 |
return tabLength; |
4434 |
return tabLength; |
4425 |
} |
4435 |
} |
4426 |
/** |
4436 |
/** |
4427 |
* Returns a copy of the widget content. |
4437 |
* Returns a copy of the widget content. |
Lines 4434-4448
Link Here
|
4434 |
* </ul> |
4444 |
* </ul> |
4435 |
*/ |
4445 |
*/ |
4436 |
public String getText() { |
4446 |
public String getText() { |
4437 |
checkWidget(); |
4447 |
checkWidget(); |
4438 |
return content.getTextRange(0, getCharCount()); |
4448 |
return content.getTextRange(0, getCharCount()); |
4439 |
} |
4449 |
} |
4440 |
/** |
4450 |
/** |
4441 |
* Returns the widget content between the two offsets. |
4451 |
* Returns the widget content between the two offsets. |
4442 |
* <p> |
4452 |
* <p> |
4443 |
* |
4453 |
* |
4444 |
* @param start offset of the first character in the returned String |
4454 |
* @param start offset of the first character in the returned String |
4445 |
* @param end offset of the last character in the returned String |
4455 |
* @param end offset of the last character in the returned String |
4446 |
* @return widget content starting at start and ending at end |
4456 |
* @return widget content starting at start and ending at end |
4447 |
* @see #getTextRange(int,int) |
4457 |
* @see #getTextRange(int,int) |
4448 |
* @exception SWTException <ul> |
4458 |
* @exception SWTException <ul> |
Lines 4450-4494
Link Here
|
4450 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4460 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4451 |
* </ul> |
4461 |
* </ul> |
4452 |
* @exception IllegalArgumentException <ul> |
4462 |
* @exception IllegalArgumentException <ul> |
4453 |
* <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4463 |
* <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
4454 |
* </ul> |
4464 |
* </ul> |
4455 |
*/ |
4465 |
*/ |
4456 |
public String getText(int start, int end) { |
4466 |
public String getText(int start, int end) { |
4457 |
checkWidget(); |
4467 |
checkWidget(); |
4458 |
int contentLength = getCharCount(); |
4468 |
int contentLength = getCharCount(); |
4459 |
|
4469 |
|
4460 |
if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { |
4470 |
if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { |
4461 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
4471 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
4462 |
} |
4472 |
} |
4463 |
return content.getTextRange(start, end - start + 1); |
4473 |
return content.getTextRange(start, end - start + 1); |
4464 |
} |
4474 |
} |
4465 |
/** |
4475 |
/** |
4466 |
* Returns the widget content starting at start for length characters. |
4476 |
* Returns the widget content starting at start for length characters. |
4467 |
* <p> |
4477 |
* <p> |
4468 |
* |
4478 |
* |
4469 |
* @param start offset of the first character in the returned String |
4479 |
* @param start offset of the first character in the returned String |
4470 |
* @param length number of characters to return |
4480 |
* @param length number of characters to return |
4471 |
* @return widget content starting at start and extending length characters. |
4481 |
* @return widget content starting at start and extending length characters. |
4472 |
* @exception SWTException <ul> |
4482 |
* @exception SWTException <ul> |
4473 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4483 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
4474 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4484 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
4475 |
* </ul> |
4485 |
* </ul> |
4476 |
* @exception IllegalArgumentException <ul> |
4486 |
* @exception IllegalArgumentException <ul> |
4477 |
* <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> |
4487 |
* <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> |
4478 |
* </ul> |
4488 |
* </ul> |
4479 |
*/ |
4489 |
*/ |
4480 |
public String getTextRange(int start, int length) { |
4490 |
public String getTextRange(int start, int length) { |
4481 |
checkWidget(); |
4491 |
checkWidget(); |
4482 |
int contentLength = getCharCount(); |
4492 |
int contentLength = getCharCount(); |
4483 |
int end = start + length; |
4493 |
int end = start + length; |
4484 |
|
4494 |
|
4485 |
if (start > end || start < 0 || end > contentLength) { |
4495 |
if (start > end || start < 0 || end > contentLength) { |
4486 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
4496 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
4487 |
} |
4497 |
} |
4488 |
return content.getTextRange(start, length); |
4498 |
return content.getTextRange(start, length); |
4489 |
} |
4499 |
} |
4490 |
/** |
4500 |
/** |
4491 |
* Gets the text limit. The text limit specifies the amount of text that the user |
4501 |
* Gets the text limit. The text limit specifies the amount of text that the user |
4492 |
* can type into the widget. |
4502 |
* can type into the widget. |
4493 |
* <p> |
4503 |
* <p> |
4494 |
* |
4504 |
* |
Lines 4498-4548
Link Here
|
4498 |
* </ul> |
4508 |
* </ul> |
4499 |
*/ |
4509 |
*/ |
4500 |
public int getTextLimit() { |
4510 |
public int getTextLimit() { |
4501 |
checkWidget(); |
4511 |
checkWidget(); |
4502 |
|
4512 |
|
4503 |
return textLimit; |
4513 |
return textLimit; |
4504 |
} |
4514 |
} |
4505 |
/** |
4515 |
/** |
4506 |
* Returns the x position of the character at the specified offset |
4516 |
* Returns the x position of the character at the specified offset |
4507 |
* relative to the first character in the line. |
4517 |
* relative to the first character in the line. |
4508 |
* Expands tabs to tab stops using the widget tab width. |
4518 |
* Expands tabs to tab stops using the widget tab width. |
4509 |
* <p> |
4519 |
* <p> |
4510 |
* |
4520 |
* |
4511 |
* @param line line to be measured. |
4521 |
* @param line line to be measured. |
4512 |
* @param lineIndex index of the line relative to the first kine of the |
4522 |
* @param lineIndex index of the line relative to the first kine of the |
4513 |
* document |
4523 |
* document |
4514 |
* @param length number of characters to measure. Tabs are counted |
4524 |
* @param length number of characters to measure. Tabs are counted |
4515 |
* as one character in this parameter. |
4525 |
* as one character in this parameter. |
4516 |
* @param gc GC to use for measuring text |
4526 |
* @param gc GC to use for measuring text |
4517 |
* @return x position of the character at the specified offset |
4527 |
* @return x position of the character at the specified offset |
4518 |
* with tabs expanded to tab stops. 0 if the length is outside the |
4528 |
* with tabs expanded to tab stops. 0 if the length is outside the |
4519 |
* specified text. |
4529 |
* specified text. |
4520 |
*/ |
4530 |
*/ |
4521 |
int getTextPosition(String line, int lineIndex, int length, GC gc) { |
4531 |
int getTextPosition(String line, int lineIndex, int length, GC gc) { |
4522 |
int lineOffset = content.getOffsetAtLine(lineIndex); |
4532 |
int lineOffset = content.getOffsetAtLine(lineIndex); |
4523 |
int lineLength = line.length(); |
4533 |
int lineLength = line.length(); |
4524 |
int width; |
4534 |
int width; |
4525 |
if (lineLength == 0 || length > lineLength) { |
4535 |
if (lineLength == 0 || length > lineLength) { |
4526 |
return 0; |
4536 |
return 0; |
4527 |
} |
4537 |
} |
4528 |
if (isBidi()) { |
4538 |
if (isBidi()) { |
4529 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc, null); |
4539 |
StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc, null); |
4530 |
width = getBidiTextPosition(line, length, bidi); |
4540 |
width = getBidiTextPosition(line, length, bidi); |
4531 |
} |
4541 |
} |
4532 |
else { |
4542 |
else { |
4533 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
4543 |
StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); |
4534 |
StyleRange[] styles = null; |
4544 |
StyleRange[] styles = null; |
4535 |
if (event != null) { |
4545 |
if (event != null) { |
4536 |
styles = renderer.filterLineStyles(event.styles); |
4546 |
styles = renderer.filterLineStyles(event.styles); |
4537 |
} |
4547 |
} |
4538 |
width = renderer.getTextPosition(line, lineOffset, length, styles, gc); |
4548 |
width = renderer.getTextPosition(line, lineOffset, length, styles, gc); |
4539 |
} |
4549 |
} |
4540 |
return width; |
4550 |
return width; |
4541 |
} |
4551 |
} |
4542 |
/** |
4552 |
/** |
4543 |
* Gets the top index. The top index is the index of the fully visible line that |
4553 |
* Gets the top index. The top index is the index of the fully visible line that |
4544 |
* is currently at the top of the widget or the topmost partially visible line if |
4554 |
* is currently at the top of the widget or the topmost partially visible line if |
4545 |
* no line is fully visible. |
4555 |
* no line is fully visible. |
4546 |
* The top index changes when the widget is scrolled. Indexing is zero based. |
4556 |
* The top index changes when the widget is scrolled. Indexing is zero based. |
4547 |
* <p> |
4557 |
* <p> |
4548 |
* |
4558 |
* |
Lines 4553-4572
Link Here
|
4553 |
* </ul> |
4563 |
* </ul> |
4554 |
*/ |
4564 |
*/ |
4555 |
public int getTopIndex() { |
4565 |
public int getTopIndex() { |
4556 |
checkWidget(); |
4566 |
checkWidget(); |
4557 |
int logicalTopIndex = topIndex; |
4567 |
int logicalTopIndex = topIndex; |
4558 |
|
4568 |
|
4559 |
if (wordWrap) { |
4569 |
if (wordWrap) { |
4560 |
int visualLineOffset = content.getOffsetAtLine(topIndex); |
4570 |
int visualLineOffset = content.getOffsetAtLine(topIndex); |
4561 |
logicalTopIndex = logicalContent.getLineAtOffset(visualLineOffset); |
4571 |
logicalTopIndex = logicalContent.getLineAtOffset(visualLineOffset); |
4562 |
} |
4572 |
} |
4563 |
return logicalTopIndex; |
4573 |
return logicalTopIndex; |
4564 |
} |
4574 |
} |
4565 |
/** |
4575 |
/** |
4566 |
* Gets the top pixel. The top pixel is the pixel position of the line that is |
4576 |
* Gets the top pixel. The top pixel is the pixel position of the line that is |
4567 |
* currently at the top of the widget.The text widget can be scrolled by pixels |
4577 |
* currently at the top of the widget.The text widget can be scrolled by pixels |
4568 |
* by dragging the scroll thumb so that a partial line may be displayed at the top |
4578 |
* by dragging the scroll thumb so that a partial line may be displayed at the top |
4569 |
* the widget. The top pixel changes when the widget is scrolled. The top pixel |
4579 |
* the widget. The top pixel changes when the widget is scrolled. The top pixel |
4570 |
* does not include the widget trimming. |
4580 |
* does not include the widget trimming. |
4571 |
* <p> |
4581 |
* <p> |
4572 |
* |
4582 |
* |
Lines 4577-4615
Link Here
|
4577 |
* </ul> |
4587 |
* </ul> |
4578 |
*/ |
4588 |
*/ |
4579 |
public int getTopPixel() { |
4589 |
public int getTopPixel() { |
4580 |
checkWidget(); |
4590 |
checkWidget(); |
4581 |
return verticalScrollOffset; |
4591 |
return verticalScrollOffset; |
4582 |
} |
4592 |
} |
4583 |
/** |
4593 |
/** |
4584 |
* Returns the vertical scroll increment. |
4594 |
* Returns the vertical scroll increment. |
4585 |
* <p> |
4595 |
* <p> |
4586 |
* |
4596 |
* |
4587 |
* @return vertical scroll increment. |
4597 |
* @return vertical scroll increment. |
4588 |
*/ |
4598 |
*/ |
4589 |
int getVerticalIncrement() { |
4599 |
int getVerticalIncrement() { |
4590 |
return lineHeight; |
4600 |
return lineHeight; |
4591 |
} |
4601 |
} |
4592 |
/** |
4602 |
/** |
4593 |
* Returns the index of the line the caret is on. |
4603 |
* Returns the index of the line the caret is on. |
4594 |
* When in word wrap mode and at the end of one wrapped line/ |
4604 |
* When in word wrap mode and at the end of one wrapped line/ |
4595 |
* beginning of the continuing wrapped line the caret offset |
4605 |
* beginning of the continuing wrapped line the caret offset |
4596 |
* is not sufficient to determine the caret line. |
4606 |
* is not sufficient to determine the caret line. |
4597 |
* |
4607 |
* |
4598 |
* @return the index of the line the caret is on. |
4608 |
* @return the index of the line the caret is on. |
4599 |
*/ |
4609 |
*/ |
4600 |
int getCaretLine() { |
4610 |
int getCaretLine() { |
4601 |
int caretLine = content.getLineAtOffset(caretOffset); |
4611 |
int caretLine = content.getLineAtOffset(caretOffset); |
4602 |
int leftColumnX = 0; |
4612 |
int leftColumnX = 0; |
4603 |
|
4613 |
|
4604 |
if (isBidi()) { |
4614 |
if (isBidi()) { |
4605 |
leftColumnX = XINSET; |
4615 |
leftColumnX = XINSET; |
4606 |
} |
4616 |
} |
4607 |
if (wordWrap && columnX <= leftColumnX && |
4617 |
if (wordWrap && columnX <= leftColumnX && |
4608 |
caretLine < content.getLineCount() - 1 && |
4618 |
caretLine < content.getLineCount() - 1 && |
4609 |
caretOffset == content.getOffsetAtLine(caretLine + 1)) { |
4619 |
caretOffset == content.getOffsetAtLine(caretLine + 1)) { |
4610 |
caretLine++; |
4620 |
caretLine++; |
4611 |
} |
4621 |
} |
4612 |
return caretLine; |
4622 |
return caretLine; |
4613 |
} |
4623 |
} |
4614 |
/** |
4624 |
/** |
4615 |
* Returns the offset of the character after the word at the specified |
4625 |
* Returns the offset of the character after the word at the specified |
Lines 4623-4664
Link Here
|
4623 |
* </p> |
4633 |
* </p> |
4624 |
* <p> |
4634 |
* <p> |
4625 |
* Space characters ' ' (ASCII 20) are special as they are treated as |
4635 |
* Space characters ' ' (ASCII 20) are special as they are treated as |
4626 |
* part of the word leading up to the space character. Line breaks are |
4636 |
* part of the word leading up to the space character. Line breaks are |
4627 |
* treated as one word. |
4637 |
* treated as one word. |
4628 |
* </p> |
4638 |
* </p> |
4629 |
*/ |
4639 |
*/ |
4630 |
int getWordEnd(int offset) { |
4640 |
int getWordEnd(int offset) { |
4631 |
int line = logicalContent.getLineAtOffset(offset); |
4641 |
int line = logicalContent.getLineAtOffset(offset); |
4632 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4642 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4633 |
String lineText = logicalContent.getLine(line); |
4643 |
String lineText = logicalContent.getLine(line); |
4634 |
int lineLength = lineText.length(); |
4644 |
int lineLength = lineText.length(); |
4635 |
|
4645 |
|
4636 |
if (offset >= getCharCount()) { |
4646 |
if (offset >= getCharCount()) { |
4637 |
return offset; |
4647 |
return offset; |
4638 |
} |
4648 |
} |
4639 |
if (offset == lineOffset + lineLength) { |
4649 |
if (offset == lineOffset + lineLength) { |
4640 |
line++; |
4650 |
line++; |
4641 |
offset = logicalContent.getOffsetAtLine(line); |
4651 |
offset = logicalContent.getOffsetAtLine(line); |
4642 |
} |
4652 |
} |
4643 |
else { |
4653 |
else { |
4644 |
offset -= lineOffset; |
4654 |
offset -= lineOffset; |
4645 |
char ch = lineText.charAt(offset); |
4655 |
char ch = lineText.charAt(offset); |
4646 |
boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4656 |
boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4647 |
while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit) { |
4657 |
while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit) { |
4648 |
offset++; |
4658 |
offset++; |
4649 |
ch = lineText.charAt(offset); |
4659 |
ch = lineText.charAt(offset); |
4650 |
} |
4660 |
} |
4651 |
// skip over trailing whitespace |
4661 |
// skip over trailing whitespace |
4652 |
while (offset < lineLength - 1 && Compatibility.isSpaceChar(ch)) { |
4662 |
while (offset < lineLength - 1 && Compatibility.isSpaceChar(ch)) { |
4653 |
offset++; |
4663 |
offset++; |
4654 |
ch = lineText.charAt(offset); |
4664 |
ch = lineText.charAt(offset); |
4655 |
} |
4665 |
} |
4656 |
if (offset == lineLength - 1 && (Compatibility.isLetterOrDigit(ch) == letterOrDigit || Compatibility.isSpaceChar(ch))) { |
4666 |
if (offset == lineLength - 1 && (Compatibility.isLetterOrDigit(ch) == letterOrDigit || Compatibility.isSpaceChar(ch))) { |
4657 |
offset++; |
4667 |
offset++; |
4658 |
} |
4668 |
} |
4659 |
offset += lineOffset; |
4669 |
offset += lineOffset; |
4660 |
} |
4670 |
} |
4661 |
return offset; |
4671 |
return offset; |
4662 |
} |
4672 |
} |
4663 |
/** |
4673 |
/** |
4664 |
* Returns the offset of the character after the word at the specified |
4674 |
* Returns the offset of the character after the word at the specified |
Lines 4671-4708
Link Here
|
4671 |
* </ul> |
4681 |
* </ul> |
4672 |
* </p> |
4682 |
* </p> |
4673 |
* <p> |
4683 |
* <p> |
4674 |
* Spaces are ignored and do not represent a word. Line breaks are treated |
4684 |
* Spaces are ignored and do not represent a word. Line breaks are treated |
4675 |
* as one word. |
4685 |
* as one word. |
4676 |
* </p> |
4686 |
* </p> |
4677 |
*/ |
4687 |
*/ |
4678 |
int getWordEndNoSpaces(int offset) { |
4688 |
int getWordEndNoSpaces(int offset) { |
4679 |
int line = logicalContent.getLineAtOffset(offset); |
4689 |
int line = logicalContent.getLineAtOffset(offset); |
4680 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4690 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4681 |
String lineText = logicalContent.getLine(line); |
4691 |
String lineText = logicalContent.getLine(line); |
4682 |
int lineLength = lineText.length(); |
4692 |
int lineLength = lineText.length(); |
4683 |
|
4693 |
|
4684 |
if (offset >= getCharCount()) { |
4694 |
if (offset >= getCharCount()) { |
4685 |
return offset; |
4695 |
return offset; |
4686 |
} |
4696 |
} |
4687 |
if (offset == lineOffset + lineLength) { |
4697 |
if (offset == lineOffset + lineLength) { |
4688 |
line++; |
4698 |
line++; |
4689 |
offset = logicalContent.getOffsetAtLine(line); |
4699 |
offset = logicalContent.getOffsetAtLine(line); |
4690 |
} |
4700 |
} |
4691 |
else { |
4701 |
else { |
4692 |
offset -= lineOffset; |
4702 |
offset -= lineOffset; |
4693 |
char ch = lineText.charAt(offset); |
4703 |
char ch = lineText.charAt(offset); |
4694 |
boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4704 |
boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4695 |
|
4705 |
|
4696 |
while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4706 |
while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4697 |
offset++; |
4707 |
offset++; |
4698 |
ch = lineText.charAt(offset); |
4708 |
ch = lineText.charAt(offset); |
4699 |
} |
4709 |
} |
4700 |
if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4710 |
if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4701 |
offset++; |
4711 |
offset++; |
4702 |
} |
4712 |
} |
4703 |
offset += lineOffset; |
4713 |
offset += lineOffset; |
4704 |
} |
4714 |
} |
4705 |
return offset; |
4715 |
return offset; |
4706 |
} |
4716 |
} |
4707 |
/** |
4717 |
/** |
4708 |
* Returns the start offset of the word at the specified offset. |
4718 |
* Returns the start offset of the word at the specified offset. |
Lines 4715-4758
Link Here
|
4715 |
* </p> |
4725 |
* </p> |
4716 |
* <p> |
4726 |
* <p> |
4717 |
* Space characters ' ' (ASCII 20) are special as they are treated as |
4727 |
* Space characters ' ' (ASCII 20) are special as they are treated as |
4718 |
* part of the word leading up to the space character. Line breaks are treated |
4728 |
* part of the word leading up to the space character. Line breaks are treated |
4719 |
* as one word. |
4729 |
* as one word. |
4720 |
* </p> |
4730 |
* </p> |
4721 |
*/ |
4731 |
*/ |
4722 |
int getWordStart(int offset) { |
4732 |
int getWordStart(int offset) { |
4723 |
int line = logicalContent.getLineAtOffset(offset); |
4733 |
int line = logicalContent.getLineAtOffset(offset); |
4724 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4734 |
int lineOffset = logicalContent.getOffsetAtLine(line); |
4725 |
String lineText = logicalContent.getLine(line); |
4735 |
String lineText = logicalContent.getLine(line); |
4726 |
|
4736 |
|
4727 |
if (offset <= 0) { |
4737 |
if (offset <= 0) { |
4728 |
return offset; |
4738 |
return offset; |
4729 |
} |
4739 |
} |
4730 |
if (offset == lineOffset) { |
4740 |
if (offset == lineOffset) { |
4731 |
line--; |
4741 |
line--; |
4732 |
lineText = logicalContent.getLine(line); |
4742 |
lineText = logicalContent.getLine(line); |
4733 |
offset = logicalContent.getOffsetAtLine(line) + lineText.length(); |
4743 |
offset = logicalContent.getOffsetAtLine(line) + lineText.length(); |
4734 |
} |
4744 |
} |
4735 |
else { |
4745 |
else { |
4736 |
char ch; |
4746 |
char ch; |
4737 |
boolean letterOrDigit; |
4747 |
boolean letterOrDigit; |
4738 |
|
4748 |
|
4739 |
offset -= lineOffset; |
4749 |
offset -= lineOffset; |
4740 |
// skip over trailing whitespace |
4750 |
// skip over trailing whitespace |
4741 |
do { |
4751 |
do { |
4742 |
offset--; |
4752 |
offset--; |
4743 |
ch = lineText.charAt(offset); |
4753 |
ch = lineText.charAt(offset); |
4744 |
} while (offset > 0 && Compatibility.isSpaceChar(ch)); |
4754 |
} while (offset > 0 && Compatibility.isSpaceChar(ch)); |
4745 |
letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4755 |
letterOrDigit = Compatibility.isLetterOrDigit(ch); |
4746 |
while (offset > 0 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4756 |
while (offset > 0 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { |
4747 |
offset--; |
4757 |
offset--; |
4748 |
ch = lineText.charAt(offset); |
4758 |
ch = lineText.charAt(offset); |
4749 |
} |
4759 |
} |
4750 |
if (offset > 0 || Compatibility.isLetterOrDigit(ch) != letterOrDigit) { |
4760 |
if (offset > 0 || Compatibility.isLetterOrDigit(ch) != letterOrDigit) { |
4751 |
offset++; |
4761 |
offset++; |
4752 |
} |
4762 |
} |
4753 |
offset += lineOffset; |
4763 |
offset += lineOffset; |
4754 |
} |
4764 |
} |
4755 |
return offset; |
4765 |
return offset; |
4756 |
} |
4766 |
} |
4757 |
/** |
4767 |
/** |
4758 |
* Returns whether the widget wraps lines. |
4768 |
* Returns whether the widget wraps lines. |
Lines 4762-4771
Link Here
|
4762 |
* @since 2.0 |
4772 |
* @since 2.0 |
4763 |
*/ |
4773 |
*/ |
4764 |
public boolean getWordWrap() { |
4774 |
public boolean getWordWrap() { |
4765 |
checkWidget(); |
4775 |
checkWidget(); |
4766 |
return wordWrap; |
4776 |
return wordWrap; |
4767 |
} |
4777 |
} |
4768 |
/** |
4778 |
/** |
4769 |
* Returns the x location of the character at the give offset in the line. |
4779 |
* Returns the x location of the character at the give offset in the line. |
4770 |
* <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts). |
4780 |
* <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts). |
4771 |
* <p> |
4781 |
* <p> |
Lines 4773-4796
Link Here
|
4773 |
* @return x location of the character at the given offset in the line. |
4783 |
* @return x location of the character at the given offset in the line. |
4774 |
*/ |
4784 |
*/ |
4775 |
int getXAtOffset(String line, int lineIndex, int lineOffset) { |
4785 |
int getXAtOffset(String line, int lineIndex, int lineOffset) { |
4776 |
int x; |
4786 |
int x; |
4777 |
if (lineOffset == 0 && isBidi() == false) { |
4787 |
if (lineOffset == 0 && isBidi() == false) { |
4778 |
x = leftMargin; |
4788 |
x = leftMargin; |
4779 |
} |
4789 |
} |
4780 |
else { |
4790 |
else { |
4781 |
GC gc = getGC(); |
4791 |
GC gc = getGC(); |
4782 |
x = getTextPosition(line, lineIndex, Math.min(line.length(), lineOffset), gc) + leftMargin; |
4792 |
x = getTextPosition(line, lineIndex, Math.min(line.length(), lineOffset), gc) + leftMargin; |
4783 |
gc.dispose(); |
4793 |
gc.dispose(); |
4784 |
if (lineOffset > line.length()) { |
4794 |
if (lineOffset > line.length()) { |
4785 |
// offset is not on the line. return an x location one character |
4795 |
// offset is not on the line. return an x location one character |
4786 |
// after the line to indicate the line delimiter. |
4796 |
// after the line to indicate the line delimiter. |
4787 |
x += lineEndSpaceWidth; |
4797 |
x += lineEndSpaceWidth; |
4788 |
} |
4798 |
} |
4789 |
} |
4799 |
} |
4790 |
return x - horizontalScrollOffset; |
4800 |
return x - horizontalScrollOffset; |
4791 |
} |
4801 |
} |
4792 |
/** |
4802 |
/** |
4793 |
* Inserts a string. The old selection is replaced with the new text. |
4803 |
* Inserts a string. The old selection is replaced with the new text. |
4794 |
* <p> |
4804 |
* <p> |
4795 |
* |
4805 |
* |
4796 |
* @param string the string |
4806 |
* @param string the string |
Lines 4804-4833
Link Here
|
4804 |
* </ul> |
4814 |
* </ul> |
4805 |
*/ |
4815 |
*/ |
4806 |
public void insert(String string) { |
4816 |
public void insert(String string) { |
4807 |
checkWidget(); |
4817 |
checkWidget(); |
4808 |
if (string == null) { |
4818 |
if (string == null) { |
4809 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
4819 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
4810 |
} |
4820 |
} |
4811 |
Point sel = getSelectionRange(); |
4821 |
Point sel = getSelectionRange(); |
4812 |
replaceTextRange(sel.x, sel.y, string); |
4822 |
replaceTextRange(sel.x, sel.y, string); |
4813 |
} |
4823 |
} |
4814 |
/** |
4824 |
/** |
4815 |
* Creates content change listeners and set the default content model. |
4825 |
* Creates content change listeners and set the default content model. |
4816 |
*/ |
4826 |
*/ |
4817 |
void installDefaultContent() { |
4827 |
void installDefaultContent() { |
4818 |
textChangeListener = new TextChangeListener() { |
4828 |
textChangeListener = new TextChangeListener() { |
4819 |
public void textChanging(TextChangingEvent event) { |
4829 |
public void textChanging(TextChangingEvent event) { |
4820 |
handleTextChanging(event); |
4830 |
handleTextChanging(event); |
4821 |
} |
4831 |
} |
4822 |
public void textChanged(TextChangedEvent event) { |
4832 |
public void textChanged(TextChangedEvent event) { |
4823 |
handleTextChanged(event); |
4833 |
handleTextChanged(event); |
4824 |
} |
4834 |
} |
4825 |
public void textSet(TextChangedEvent event) { |
4835 |
public void textSet(TextChangedEvent event) { |
4826 |
handleTextSet(event); |
4836 |
handleTextSet(event); |
4827 |
} |
4837 |
} |
4828 |
}; |
4838 |
}; |
4829 |
logicalContent = content = new DefaultContent(); |
4839 |
logicalContent = content = new DefaultContent(); |
4830 |
content.addTextChangeListener(textChangeListener); |
4840 |
content.addTextChangeListener(textChangeListener); |
4831 |
} |
4841 |
} |
4832 |
/** |
4842 |
/** |
4833 |
* Creates a default line style listener. |
4843 |
* Creates a default line style listener. |
Lines 4838-4996
Link Here
|
4838 |
* @see #addLineStyleListener |
4848 |
* @see #addLineStyleListener |
4839 |
*/ |
4849 |
*/ |
4840 |
void installDefaultLineStyler() { |
4850 |
void installDefaultLineStyler() { |
4841 |
defaultLineStyler = new DefaultLineStyler(logicalContent); |
4851 |
defaultLineStyler = new DefaultLineStyler(logicalContent); |
4842 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
4852 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
4843 |
if (userLineStyle == false) { |
4853 |
if (userLineStyle == false) { |
4844 |
addListener(LineGetStyle, typedListener); |
4854 |
addListener(LineGetStyle, typedListener); |
4845 |
} |
4855 |
} |
4846 |
if (userLineBackground == false) { |
4856 |
if (userLineBackground == false) { |
4847 |
addListener(LineGetBackground, typedListener); |
4857 |
addListener(LineGetBackground, typedListener); |
4848 |
} |
4858 |
} |
4849 |
} |
4859 |
} |
4850 |
/** |
4860 |
/** |
4851 |
* Adds event listeners |
4861 |
* Adds event listeners |
4852 |
*/ |
4862 |
*/ |
4853 |
void installListeners() { |
4863 |
void installListeners() { |
4854 |
ScrollBar verticalBar = getVerticalBar(); |
4864 |
ScrollBar verticalBar = getVerticalBar(); |
4855 |
ScrollBar horizontalBar = getHorizontalBar(); |
4865 |
ScrollBar horizontalBar = getHorizontalBar(); |
4856 |
|
4866 |
|
4857 |
addListener(SWT.Dispose, new Listener() { |
4867 |
addListener(SWT.Dispose, new Listener() { |
4858 |
public void handleEvent(Event event) { |
4868 |
public void handleEvent(Event event) { |
4859 |
handleDispose(); |
4869 |
handleDispose(); |
4860 |
} |
4870 |
} |
4861 |
}); |
4871 |
}); |
4862 |
addListener(SWT.KeyDown, new Listener() { |
4872 |
addListener(SWT.KeyDown, new Listener() { |
4863 |
public void handleEvent(Event event) { |
4873 |
public void handleEvent(Event event) { |
4864 |
handleKeyDown(event); |
4874 |
handleKeyDown(event); |
4865 |
} |
4875 |
} |
4866 |
}); |
4876 |
}); |
4867 |
addListener(SWT.MouseDown, new Listener() { |
4877 |
addListener(SWT.MouseDown, new Listener() { |
4868 |
public void handleEvent(Event event) { |
4878 |
public void handleEvent(Event event) { |
4869 |
handleMouseDown(event); |
4879 |
handleMouseDown(event); |
4870 |
} |
4880 |
} |
4871 |
}); |
4881 |
}); |
4872 |
addListener(SWT.MouseUp, new Listener() { |
4882 |
addListener(SWT.MouseUp, new Listener() { |
4873 |
public void handleEvent(Event event) { |
4883 |
public void handleEvent(Event event) { |
4874 |
handleMouseUp(event); |
4884 |
handleMouseUp(event); |
4875 |
} |
4885 |
} |
4876 |
}); |
4886 |
}); |
4877 |
addListener(SWT.MouseDoubleClick, new Listener() { |
4887 |
addListener(SWT.MouseDoubleClick, new Listener() { |
4878 |
public void handleEvent(Event event) { |
4888 |
public void handleEvent(Event event) { |
4879 |
handleMouseDoubleClick(event); |
4889 |
handleMouseDoubleClick(event); |
4880 |
} |
4890 |
} |
4881 |
}); |
4891 |
}); |
4882 |
addListener(SWT.MouseMove, new Listener() { |
4892 |
addListener(SWT.MouseMove, new Listener() { |
4883 |
public void handleEvent(Event event) { |
4893 |
public void handleEvent(Event event) { |
4884 |
handleMouseMove(event); |
4894 |
handleMouseMove(event); |
4885 |
} |
4895 |
} |
4886 |
}); |
4896 |
}); |
4887 |
addListener(SWT.Paint, new Listener() { |
4897 |
addListener(SWT.Paint, new Listener() { |
4888 |
public void handleEvent(Event event) { |
4898 |
public void handleEvent(Event event) { |
4889 |
handlePaint(event); |
4899 |
handlePaint(event); |
4890 |
} |
4900 |
} |
4891 |
}); |
4901 |
}); |
4892 |
addListener(SWT.Resize, new Listener() { |
4902 |
addListener(SWT.Resize, new Listener() { |
4893 |
public void handleEvent(Event event) { |
4903 |
public void handleEvent(Event event) { |
4894 |
handleResize(event); |
4904 |
handleResize(event); |
4895 |
} |
4905 |
} |
4896 |
}); |
4906 |
}); |
4897 |
addListener(SWT.Traverse, new Listener() { |
4907 |
addListener(SWT.Traverse, new Listener() { |
4898 |
public void handleEvent(Event event) { |
4908 |
public void handleEvent(Event event) { |
4899 |
handleTraverse(event); |
4909 |
handleTraverse(event); |
4900 |
} |
4910 |
} |
4901 |
}); |
4911 |
}); |
4902 |
if (verticalBar != null) { |
4912 |
if (verticalBar != null) { |
4903 |
verticalBar.addListener(SWT.Selection, new Listener() { |
4913 |
verticalBar.addListener(SWT.Selection, new Listener() { |
4904 |
public void handleEvent(Event event) { |
4914 |
public void handleEvent(Event event) { |
4905 |
handleVerticalScroll(event); |
4915 |
handleVerticalScroll(event); |
4906 |
} |
4916 |
} |
4907 |
}); |
4917 |
}); |
4908 |
} |
4918 |
} |
4909 |
if (horizontalBar != null) { |
4919 |
if (horizontalBar != null) { |
4910 |
horizontalBar.addListener(SWT.Selection, new Listener() { |
4920 |
horizontalBar.addListener(SWT.Selection, new Listener() { |
4911 |
public void handleEvent(Event event) { |
4921 |
public void handleEvent(Event event) { |
4912 |
handleHorizontalScroll(event); |
4922 |
handleHorizontalScroll(event); |
4913 |
} |
4923 |
} |
4914 |
}); |
4924 |
}); |
4915 |
} |
4925 |
} |
4916 |
} |
4926 |
} |
4917 |
StyledTextContent internalGetContent() { |
4927 |
StyledTextContent internalGetContent() { |
4918 |
return content; |
4928 |
return content; |
4919 |
} |
4929 |
} |
4920 |
int internalGetHorizontalPixel() { |
4930 |
int internalGetHorizontalPixel() { |
4921 |
return horizontalScrollOffset; |
4931 |
return horizontalScrollOffset; |
4922 |
} |
4932 |
} |
4923 |
LineCache internalGetLineCache() { |
4933 |
LineCache internalGetLineCache() { |
4924 |
return lineCache; |
4934 |
return lineCache; |
4925 |
} |
4935 |
} |
4926 |
Point internalGetSelection() { |
4936 |
Point internalGetSelection() { |
4927 |
return selection; |
4937 |
return selection; |
4928 |
} |
4938 |
} |
4929 |
boolean internalGetWordWrap() { |
4939 |
boolean internalGetWordWrap() { |
4930 |
return wordWrap; |
4940 |
return wordWrap; |
4931 |
} |
4941 |
} |
4932 |
/** |
4942 |
/** |
4933 |
* Used by WordWrapCache to bypass StyledText.redraw which does |
4943 |
* Used by WordWrapCache to bypass StyledText.redraw which does |
4934 |
* an unwanted cache reset. |
4944 |
* an unwanted cache reset. |
4935 |
*/ |
4945 |
*/ |
4936 |
void internalRedraw() { |
4946 |
void internalRedraw() { |
4937 |
super.redraw(); |
4947 |
super.redraw(); |
4938 |
} |
4948 |
} |
4939 |
/** |
4949 |
/** |
4940 |
* Redraws the specified text range. |
4950 |
* Redraws the specified text range. |
4941 |
* <p> |
4951 |
* <p> |
4942 |
* |
4952 |
* |
4943 |
* @param start offset of the first character to redraw |
4953 |
* @param start offset of the first character to redraw |
4944 |
* @param length number of characters to redraw |
4954 |
* @param length number of characters to redraw |
4945 |
* @param clearBackground true if the background should be cleared as |
4955 |
* @param clearBackground true if the background should be cleared as |
4946 |
* part of the redraw operation. If true, the entire redraw range will |
4956 |
* part of the redraw operation. If true, the entire redraw range will |
4947 |
* be cleared before anything is redrawn. If the redraw range includes |
4957 |
* be cleared before anything is redrawn. If the redraw range includes |
4948 |
* the last character of a line (i.e., the entire line is redrawn) the |
4958 |
* the last character of a line (i.e., the entire line is redrawn) the |
4949 |
* line is cleared all the way to the right border of the widget. |
4959 |
* line is cleared all the way to the right border of the widget. |
4950 |
* The redraw operation will be faster and smoother if clearBackground is |
4960 |
* The redraw operation will be faster and smoother if clearBackground is |
4951 |
* set to false. Whether or not the flag can be set to false depends on |
4961 |
* set to false. Whether or not the flag can be set to false depends on |
4952 |
* the type of change that has taken place. If font styles or background |
4962 |
* the type of change that has taken place. If font styles or background |
4953 |
* colors for the redraw range have changed, clearBackground should be |
4963 |
* colors for the redraw range have changed, clearBackground should be |
4954 |
* set to true. If only foreground colors have changed for the redraw |
4964 |
* set to true. If only foreground colors have changed for the redraw |
4955 |
* range, clearBackground can be set to false. |
4965 |
* range, clearBackground can be set to false. |
4956 |
*/ |
4966 |
*/ |
4957 |
void internalRedrawRange(int start, int length, boolean clearBackground) { |
4967 |
void internalRedrawRange(int start, int length, boolean clearBackground) { |
4958 |
int end = start + length; |
4968 |
int end = start + length; |
4959 |
int firstLine = content.getLineAtOffset(start); |
4969 |
int firstLine = content.getLineAtOffset(start); |
4960 |
int lastLine = content.getLineAtOffset(end); |
4970 |
int lastLine = content.getLineAtOffset(end); |
4961 |
int offsetInFirstLine; |
4971 |
int offsetInFirstLine; |
4962 |
int partialBottomIndex = getPartialBottomIndex(); |
4972 |
int partialBottomIndex = getPartialBottomIndex(); |
4963 |
int partialTopIndex = verticalScrollOffset / lineHeight; |
4973 |
int partialTopIndex = verticalScrollOffset / lineHeight; |
4964 |
// do nothing if redraw range is completely invisible |
4974 |
// do nothing if redraw range is completely invisible |
4965 |
if (firstLine > partialBottomIndex || lastLine < partialTopIndex) { |
4975 |
if (firstLine > partialBottomIndex || lastLine < partialTopIndex) { |
4966 |
return; |
4976 |
return; |
4967 |
} |
4977 |
} |
4968 |
// only redraw visible lines |
4978 |
// only redraw visible lines |
4969 |
if (partialTopIndex > firstLine) { |
4979 |
if (partialTopIndex > firstLine) { |
4970 |
firstLine = partialTopIndex; |
4980 |
firstLine = partialTopIndex; |
4971 |
offsetInFirstLine = 0; |
4981 |
offsetInFirstLine = 0; |
4972 |
} |
4982 |
} |
4973 |
else { |
4983 |
else { |
4974 |
offsetInFirstLine = start - content.getOffsetAtLine(firstLine); |
4984 |
offsetInFirstLine = start - content.getOffsetAtLine(firstLine); |
4975 |
} |
4985 |
} |
4976 |
if (partialBottomIndex + 1 < lastLine) { |
4986 |
if (partialBottomIndex + 1 < lastLine) { |
4977 |
lastLine = partialBottomIndex + 1; // + 1 to redraw whole bottom line, including line break |
4987 |
lastLine = partialBottomIndex + 1; // + 1 to redraw whole bottom line, including line break |
4978 |
end = content.getOffsetAtLine(lastLine); |
4988 |
end = content.getOffsetAtLine(lastLine); |
4979 |
} |
4989 |
} |
4980 |
// redraw first and last lines |
4990 |
// redraw first and last lines |
4981 |
if (isBidi()) { |
4991 |
if (isBidi()) { |
4982 |
redrawBidiLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); |
4992 |
redrawBidiLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); |
4983 |
} |
4993 |
} |
4984 |
else { |
4994 |
else { |
4985 |
redrawLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); |
4995 |
redrawLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); |
4986 |
} |
4996 |
} |
4987 |
// redraw entire center lines if redraw range includes more than two lines |
4997 |
// redraw entire center lines if redraw range includes more than two lines |
4988 |
if (lastLine - firstLine > 1) { |
4998 |
if (lastLine - firstLine > 1) { |
4989 |
Rectangle clientArea = getClientArea(); |
4999 |
Rectangle clientArea = getClientArea(); |
4990 |
int redrawStopY = lastLine * lineHeight - verticalScrollOffset; |
5000 |
int redrawStopY = lastLine * lineHeight - verticalScrollOffset; |
4991 |
int redrawY = (firstLine + 1) * lineHeight - verticalScrollOffset; |
5001 |
int redrawY = (firstLine + 1) * lineHeight - verticalScrollOffset; |
4992 |
draw(0, redrawY, clientArea.width, redrawStopY - redrawY, clearBackground); |
5002 |
draw(0, redrawY, clientArea.width, redrawStopY - redrawY, clearBackground); |
4993 |
} |
5003 |
} |
4994 |
} |
5004 |
} |
4995 |
/** |
5005 |
/** |
4996 |
* Returns the widget text with style information encoded using RTF format |
5006 |
* Returns the widget text with style information encoded using RTF format |
Lines 5003-5043
Link Here
|
5003 |
* </ul> |
5013 |
* </ul> |
5004 |
*/ |
5014 |
*/ |
5005 |
String getRtf(){ |
5015 |
String getRtf(){ |
5006 |
checkWidget(); |
5016 |
checkWidget(); |
5007 |
RTFWriter rtfWriter = new RTFWriter(0, getCharCount()); |
5017 |
RTFWriter rtfWriter = new RTFWriter(0, getCharCount()); |
5008 |
return getPlatformDelimitedText(rtfWriter); |
5018 |
return getPlatformDelimitedText(rtfWriter); |
5009 |
} |
5019 |
} |
5010 |
/** |
5020 |
/** |
5011 |
* Frees resources. |
5021 |
* Frees resources. |
5012 |
*/ |
5022 |
*/ |
5013 |
void handleDispose() { |
5023 |
void handleDispose() { |
5014 |
clipboard.dispose(); |
5024 |
clipboard.dispose(); |
5015 |
ibeamCursor.dispose(); |
5025 |
ibeamCursor.dispose(); |
5016 |
if (renderer != null) { |
5026 |
if (renderer != null) { |
5017 |
renderer.dispose(); |
5027 |
renderer.dispose(); |
5018 |
renderer = null; |
5028 |
renderer = null; |
5019 |
} |
5029 |
} |
5020 |
if (content != null) { |
5030 |
if (content != null) { |
5021 |
content.removeTextChangeListener(textChangeListener); |
5031 |
content.removeTextChangeListener(textChangeListener); |
5022 |
} |
5032 |
} |
5023 |
if (leftCaretBitmap != null) { |
5033 |
if (leftCaretBitmap != null) { |
5024 |
leftCaretBitmap.dispose(); |
5034 |
leftCaretBitmap.dispose(); |
5025 |
leftCaretBitmap = null; |
5035 |
leftCaretBitmap = null; |
5026 |
} |
5036 |
} |
5027 |
if (rightCaretBitmap != null) { |
5037 |
if (rightCaretBitmap != null) { |
5028 |
rightCaretBitmap.dispose(); |
5038 |
rightCaretBitmap.dispose(); |
5029 |
rightCaretBitmap = null; |
5039 |
rightCaretBitmap = null; |
5030 |
} |
5040 |
} |
5031 |
if (isBidi()) { |
5041 |
if (isBidi()) { |
5032 |
StyledTextBidi.removeLanguageListener(this); |
5042 |
StyledTextBidi.removeLanguageListener(this); |
5033 |
} |
5043 |
} |
5034 |
} |
5044 |
} |
5035 |
/** |
5045 |
/** |
5036 |
* Scrolls the widget horizontally. |
5046 |
* Scrolls the widget horizontally. |
5037 |
*/ |
5047 |
*/ |
5038 |
void handleHorizontalScroll(Event event) { |
5048 |
void handleHorizontalScroll(Event event) { |
5039 |
int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; |
5049 |
int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; |
5040 |
scrollHorizontal(scrollPixel); |
5050 |
scrollHorizontal(scrollPixel); |
5041 |
} |
5051 |
} |
5042 |
/** |
5052 |
/** |
5043 |
* If an action has been registered for the key stroke execute the action. |
5053 |
* If an action has been registered for the key stroke execute the action. |
Lines 5047-5102
Link Here
|
5047 |
* @param event keyboard event |
5057 |
* @param event keyboard event |
5048 |
*/ |
5058 |
*/ |
5049 |
void handleKey(Event event) { |
5059 |
void handleKey(Event event) { |
5050 |
int action; |
5060 |
int action; |
5051 |
|
5061 |
|
5052 |
if (event.keyCode != 0) { |
5062 |
if (event.keyCode != 0) { |
5053 |
// special key pressed (e.g., F1) |
5063 |
// special key pressed (e.g., F1) |
5054 |
action = getKeyBinding(event.keyCode | event.stateMask); |
5064 |
action = getKeyBinding(event.keyCode | event.stateMask); |
5055 |
} |
5065 |
} |
5056 |
else { |
5066 |
else { |
5057 |
// character key pressed |
5067 |
// character key pressed |
5058 |
action = getKeyBinding(event.character | event.stateMask); |
5068 |
action = getKeyBinding(event.character | event.stateMask); |
5059 |
if (action == SWT.NULL) { |
5069 |
if (action == SWT.NULL) { |
5060 |
// see if we have a control character |
5070 |
// see if we have a control character |
5061 |
if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) { |
5071 |
if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) { |
5062 |
// get the character from the CTRL+char sequence, the control |
5072 |
// get the character from the CTRL+char sequence, the control |
5063 |
// key subtracts 64 from the value of the key that it modifies |
5073 |
// key subtracts 64 from the value of the key that it modifies |
5064 |
int c = event.character + 64; |
5074 |
int c = event.character + 64; |
5065 |
action = getKeyBinding(c | event.stateMask); |
5075 |
action = getKeyBinding(c | event.stateMask); |
5066 |
} |
5076 |
} |
5067 |
} |
5077 |
} |
5068 |
} |
5078 |
} |
5069 |
if (action == SWT.NULL) { |
5079 |
if (action == SWT.NULL) { |
5070 |
boolean ignore = false; |
5080 |
boolean ignore = false; |
5071 |
|
5081 |
|
5072 |
if (isCarbon) { |
5082 |
if (isCarbon) { |
5073 |
// Ignore acclerator key combinations (we do not want to |
5083 |
// Ignore acclerator key combinations (we do not want to |
5074 |
// insert a character in the text in this instance). Do not |
5084 |
// insert a character in the text in this instance). Do not |
5075 |
// ignore COMMAND+ALT combinations since that key sequence |
5085 |
// ignore COMMAND+ALT combinations since that key sequence |
5076 |
// produces characters on the mac. |
5086 |
// produces characters on the mac. |
5077 |
ignore = (event.stateMask ^ SWT.COMMAND) == 0 || |
5087 |
ignore = (event.stateMask ^ SWT.COMMAND) == 0 || |
5078 |
(event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0; |
5088 |
(event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0; |
5079 |
} else { |
5089 |
} else { |
5080 |
// Ignore acclerator key combinations (we do not want to |
5090 |
// Ignore acclerator key combinations (we do not want to |
5081 |
// insert a character in the text in this instance). Don't |
5091 |
// insert a character in the text in this instance). Don't |
5082 |
// ignore CTRL+ALT combinations since that is the Alt Gr |
5092 |
// ignore CTRL+ALT combinations since that is the Alt Gr |
5083 |
// key on some keyboards. See bug 20953. |
5093 |
// key on some keyboards. See bug 20953. |
5084 |
ignore = (event.stateMask ^ SWT.ALT) == 0 || |
5094 |
ignore = (event.stateMask ^ SWT.ALT) == 0 || |
5085 |
(event.stateMask ^ SWT.CTRL) == 0 || |
5095 |
(event.stateMask ^ SWT.CTRL) == 0 || |
5086 |
(event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 || |
5096 |
(event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 || |
5087 |
(event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; |
5097 |
(event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; |
5088 |
} |
5098 |
} |
5089 |
// -ignore anything below SPACE except for line delimiter keys and tab. |
5099 |
// -ignore anything below SPACE except for line delimiter keys and tab. |
5090 |
// -ignore DEL |
5100 |
// -ignore DEL |
5091 |
if (!ignore && event.character > 31 && event.character != SWT.DEL || |
5101 |
if (!ignore && event.character > 31 && event.character != SWT.DEL || |
5092 |
event.character == SWT.CR || event.character == SWT.LF || |
5102 |
event.character == SWT.CR || event.character == SWT.LF || |
5093 |
event.character == TAB) { |
5103 |
event.character == TAB) { |
5094 |
doContent(event.character); |
5104 |
doContent(event.character); |
5095 |
} |
5105 |
} |
5096 |
} |
5106 |
} |
5097 |
else { |
5107 |
else { |
5098 |
invokeAction(action); |
5108 |
invokeAction(action); |
5099 |
} |
5109 |
} |
5100 |
} |
5110 |
} |
5101 |
/** |
5111 |
/** |
5102 |
* If a VerifyKey listener exists, verify that the key that was entered |
5112 |
* If a VerifyKey listener exists, verify that the key that was entered |
Lines 5106-5171
Link Here
|
5106 |
* @param event keyboard event |
5116 |
* @param event keyboard event |
5107 |
*/ |
5117 |
*/ |
5108 |
void handleKeyDown(Event event) { |
5118 |
void handleKeyDown(Event event) { |
5109 |
Event verifyEvent = new Event(); |
5119 |
Event verifyEvent = new Event(); |
5110 |
|
5120 |
|
5111 |
verifyEvent.character = event.character; |
5121 |
verifyEvent.character = event.character; |
5112 |
verifyEvent.keyCode = event.keyCode; |
5122 |
verifyEvent.keyCode = event.keyCode; |
5113 |
verifyEvent.stateMask = event.stateMask; |
5123 |
verifyEvent.stateMask = event.stateMask; |
5114 |
verifyEvent.doit = true; |
5124 |
verifyEvent.doit = true; |
5115 |
notifyListeners(VerifyKey, verifyEvent); |
5125 |
notifyListeners(VerifyKey, verifyEvent); |
5116 |
if (verifyEvent.doit == true) { |
5126 |
if (verifyEvent.doit == true) { |
5117 |
handleKey(event); |
5127 |
handleKey(event); |
5118 |
} |
5128 |
} |
5119 |
} |
5129 |
} |
5120 |
/** |
5130 |
/** |
5121 |
* Updates the caret location and selection if mouse button 1 has been |
5131 |
* Updates the caret location and selection if mouse button 1 has been |
5122 |
* pressed. |
5132 |
* pressed. |
5123 |
*/ |
5133 |
*/ |
5124 |
void handleMouseDoubleClick(Event event) { |
5134 |
void handleMouseDoubleClick(Event event) { |
5125 |
if (event.button != 1 || doubleClickEnabled == false) { |
5135 |
if (event.button != 1 || doubleClickEnabled == false) { |
5126 |
return; |
5136 |
return; |
5127 |
} |
5137 |
} |
5128 |
event.y -= topMargin; |
5138 |
event.y -= topMargin; |
5129 |
mouseDoubleClick = true; |
5139 |
mouseDoubleClick = true; |
5130 |
caretOffset = getWordStart(caretOffset); |
5140 |
caretOffset = getWordStart(caretOffset); |
5131 |
resetSelection(); |
5141 |
resetSelection(); |
5132 |
caretOffset = getWordEndNoSpaces(caretOffset); |
5142 |
caretOffset = getWordEndNoSpaces(caretOffset); |
5133 |
showCaret(); |
5143 |
showCaret(); |
5134 |
doMouseSelection(); |
5144 |
doMouseSelection(); |
5135 |
doubleClickSelection = new Point(selection.x, selection.y); |
5145 |
doubleClickSelection = new Point(selection.x, selection.y); |
5136 |
} |
5146 |
} |
5137 |
/** |
5147 |
/** |
5138 |
* Updates the caret location and selection if mouse button 1 has been |
5148 |
* Updates the caret location and selection if mouse button 1 has been |
5139 |
* pressed. |
5149 |
* pressed. |
5140 |
*/ |
5150 |
*/ |
5141 |
void handleMouseDown(Event event) { |
5151 |
void handleMouseDown(Event event) { |
5142 |
boolean select = (event.stateMask & SWT.MOD2) != 0; |
5152 |
boolean select = (event.stateMask & SWT.MOD2) != 0; |
5143 |
|
5153 |
|
5144 |
if (event.button != 1) { |
5154 |
if ((event.button == 1) || (event.button == 3)) { |
5145 |
return; |
5155 |
if ((event.button == 3) && (isMouseOverSelection(event.x, event.y))) { |
5146 |
} |
5156 |
// we have a right click over a selection, so don't alter the selection |
5147 |
mouseDoubleClick = false; |
5157 |
return; |
5148 |
event.y -= topMargin; |
5158 |
} |
5149 |
doMouseLocationChange(event.x, event.y, select); |
5159 |
mouseDoubleClick = false; |
|
|
5160 |
event.y -= topMargin; |
5161 |
doMouseLocationChange(event.x, event.y, select); |
5162 |
} |
5150 |
} |
5163 |
} |
5151 |
/** |
5164 |
/** |
5152 |
* Updates the caret location and selection if mouse button 1 is pressed |
5165 |
* Updates the caret location and selection if mouse button 1 is pressed |
5153 |
* during the mouse move. |
5166 |
* during the mouse move. |
5154 |
*/ |
5167 |
*/ |
5155 |
void handleMouseMove(Event event) { |
5168 |
void handleMouseMove(Event event) { |
5156 |
if ((event.stateMask & SWT.BUTTON1) == 0) { |
5169 |
if ((event.stateMask & SWT.BUTTON1) != 0) { |
5157 |
return; |
5170 |
event.y -= topMargin; |
5158 |
} |
5171 |
doMouseLocationChange(event.x, event.y, true); |
5159 |
event.y -= topMargin; |
5172 |
doAutoScroll(event); |
5160 |
doMouseLocationChange(event.x, event.y, true); |
5173 |
} else if (event.stateMask == 0) { |
5161 |
doAutoScroll(event); |
5174 |
// changes the mouse pointer based on whether or not it is over a selection |
|
|
5175 |
internalSetCursor(event.x, event.y); |
5176 |
} |
5162 |
} |
5177 |
} |
5163 |
/** |
5178 |
/** |
5164 |
* Autoscrolling ends when the mouse button is released. |
5179 |
* Autoscrolling ends when the mouse button is released. |
5165 |
*/ |
5180 |
*/ |
5166 |
void handleMouseUp(Event event) { |
5181 |
void handleMouseUp(Event event) { |
5167 |
event.y -= topMargin; |
5182 |
event.y -= topMargin; |
5168 |
endAutoScroll(); |
5183 |
endAutoScroll(); |
5169 |
} |
5184 |
} |
5170 |
/** |
5185 |
/** |
5171 |
* Renders the invalidated area specified in the paint event. |
5186 |
* Renders the invalidated area specified in the paint event. |
Lines 5174-5377
Link Here
|
5174 |
* @param event paint event |
5189 |
* @param event paint event |
5175 |
*/ |
5190 |
*/ |
5176 |
void handlePaint(Event event) { |
5191 |
void handlePaint(Event event) { |
5177 |
int startLine = Math.max(0, (event.y - topMargin + verticalScrollOffset) / lineHeight); |
5192 |
int startLine = Math.max(0, (event.y - topMargin + verticalScrollOffset) / lineHeight); |
5178 |
int paintYFromTopLine = (startLine - topIndex) * lineHeight; |
5193 |
int paintYFromTopLine = (startLine - topIndex) * lineHeight; |
5179 |
int topLineOffset = topIndex * lineHeight - verticalScrollOffset; |
5194 |
int topLineOffset = topIndex * lineHeight - verticalScrollOffset; |
5180 |
int startY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling and top margin |
5195 |
int startY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling and top margin |
5181 |
int renderHeight = event.y + event.height - startY; |
5196 |
int renderHeight = event.y + event.height - startY; |
5182 |
Rectangle clientArea = getClientArea(); |
5197 |
Rectangle clientArea = getClientArea(); |
5183 |
|
5198 |
|
5184 |
// Check if there is work to do. clientArea.width should never be 0 |
5199 |
// Check if there is work to do. clientArea.width should never be 0 |
5185 |
// if we receive a paint event but we never want to try and create |
5200 |
// if we receive a paint event but we never want to try and create |
5186 |
// an Image with 0 width. |
5201 |
// an Image with 0 width. |
5187 |
if (clientArea.width == 0 || event.height == 0) { |
5202 |
if (clientArea.width == 0 || event.height == 0) { |
5188 |
return; |
5203 |
return; |
5189 |
} |
5204 |
} |
5190 |
performPaint(event.gc, startLine, startY, renderHeight); |
5205 |
performPaint(event.gc, startLine, startY, renderHeight); |
5191 |
} |
5206 |
} |
5192 |
/** |
5207 |
/** |
5193 |
* Recalculates the scroll bars. Rewraps all lines when in word |
5208 |
* Recalculates the scroll bars. Rewraps all lines when in word |
5194 |
* wrap mode. |
5209 |
* wrap mode. |
5195 |
* <p> |
5210 |
* <p> |
5196 |
* |
5211 |
* |
5197 |
* @param event resize event |
5212 |
* @param event resize event |
5198 |
*/ |
5213 |
*/ |
5199 |
void handleResize(Event event) { |
5214 |
void handleResize(Event event) { |
5200 |
int oldHeight = clientAreaHeight; |
5215 |
int oldHeight = clientAreaHeight; |
5201 |
int oldWidth = clientAreaWidth; |
5216 |
int oldWidth = clientAreaWidth; |
5202 |
|
5217 |
|
5203 |
clientAreaHeight = getClientArea().height; |
5218 |
clientAreaHeight = getClientArea().height; |
5204 |
clientAreaWidth = getClientArea().width; |
5219 |
clientAreaWidth = getClientArea().width; |
5205 |
if (wordWrap) { |
5220 |
if (wordWrap) { |
5206 |
if (oldWidth != clientAreaWidth) { |
5221 |
if (oldWidth != clientAreaWidth) { |
5207 |
wordWrapResize(oldWidth); |
5222 |
wordWrapResize(oldWidth); |
5208 |
} |
5223 |
} |
5209 |
} |
5224 |
} |
5210 |
else |
5225 |
else |
5211 |
if (clientAreaHeight > oldHeight) { |
5226 |
if (clientAreaHeight > oldHeight) { |
5212 |
int lineCount = content.getLineCount(); |
5227 |
int lineCount = content.getLineCount(); |
5213 |
int oldBottomIndex = topIndex + oldHeight / lineHeight; |
5228 |
int oldBottomIndex = topIndex + oldHeight / lineHeight; |
5214 |
int newItemCount = Compatibility.ceil(clientAreaHeight - oldHeight, lineHeight); |
5229 |
int newItemCount = Compatibility.ceil(clientAreaHeight - oldHeight, lineHeight); |
5215 |
|
5230 |
|
5216 |
oldBottomIndex = Math.min(oldBottomIndex, lineCount); |
5231 |
oldBottomIndex = Math.min(oldBottomIndex, lineCount); |
5217 |
newItemCount = Math.min(newItemCount, lineCount - oldBottomIndex); |
5232 |
newItemCount = Math.min(newItemCount, lineCount - oldBottomIndex); |
5218 |
lineCache.calculate(oldBottomIndex, newItemCount); |
5233 |
lineCache.calculate(oldBottomIndex, newItemCount); |
5219 |
} |
5234 |
} |
5220 |
setScrollBars(); |
5235 |
setScrollBars(); |
5221 |
claimBottomFreeSpace(); |
5236 |
claimBottomFreeSpace(); |
5222 |
claimRightFreeSpace(); |
5237 |
claimRightFreeSpace(); |
5223 |
if (oldHeight != clientAreaHeight) { |
5238 |
if (oldHeight != clientAreaHeight) { |
5224 |
calculateTopIndex(); |
5239 |
calculateTopIndex(); |
5225 |
} |
5240 |
} |
5226 |
} |
5241 |
} |
5227 |
/** |
5242 |
/** |
5228 |
* Updates the caret position and selection and the scroll bars to reflect |
5243 |
* Updates the caret position and selection and the scroll bars to reflect |
5229 |
* the content change. |
5244 |
* the content change. |
5230 |
* <p> |
5245 |
* <p> |
5231 |
*/ |
5246 |
*/ |
5232 |
void handleTextChanged(TextChangedEvent event) { |
5247 |
void handleTextChanged(TextChangedEvent event) { |
5233 |
lineCache.textChanged(lastTextChangeStart, |
5248 |
lineCache.textChanged(lastTextChangeStart, |
5234 |
lastTextChangeNewLineCount, |
5249 |
lastTextChangeNewLineCount, |
5235 |
lastTextChangeReplaceLineCount, |
5250 |
lastTextChangeReplaceLineCount, |
5236 |
lastTextChangeNewCharCount, |
5251 |
lastTextChangeNewCharCount, |
5237 |
lastTextChangeReplaceCharCount); |
5252 |
lastTextChangeReplaceCharCount); |
5238 |
setScrollBars(); |
5253 |
setScrollBars(); |
5239 |
// update selection/caret location after styles have been changed. |
5254 |
// update selection/caret location after styles have been changed. |
5240 |
// otherwise any text measuring could be incorrect |
5255 |
// otherwise any text measuring could be incorrect |
5241 |
// |
5256 |
// |
5242 |
// also, this needs to be done after all scrolling. Otherwise, |
5257 |
// also, this needs to be done after all scrolling. Otherwise, |
5243 |
// selection redraw would be flushed during scroll which is wrong. |
5258 |
// selection redraw would be flushed during scroll which is wrong. |
5244 |
// in some cases new text would be drawn in scroll source area even |
5259 |
// in some cases new text would be drawn in scroll source area even |
5245 |
// though the intent is to scroll it. |
5260 |
// though the intent is to scroll it. |
5246 |
// fixes 1GB93QT |
5261 |
// fixes 1GB93QT |
5247 |
updateSelection( |
5262 |
updateSelection( |
5248 |
lastTextChangeStart, |
5263 |
lastTextChangeStart, |
5249 |
lastTextChangeReplaceCharCount, |
5264 |
lastTextChangeReplaceCharCount, |
5250 |
lastTextChangeNewCharCount); |
5265 |
lastTextChangeNewCharCount); |
5251 |
|
5266 |
|
5252 |
if (lastTextChangeReplaceLineCount > 0) { |
5267 |
if (lastTextChangeReplaceLineCount > 0) { |
5253 |
// Only check for unused space when lines are deleted. |
5268 |
// Only check for unused space when lines are deleted. |
5254 |
// Fixes 1GFL4LY |
5269 |
// Fixes 1GFL4LY |
5255 |
// Scroll up so that empty lines below last text line are used. |
5270 |
// Scroll up so that empty lines below last text line are used. |
5256 |
// Fixes 1GEYJM0 |
5271 |
// Fixes 1GEYJM0 |
5257 |
claimBottomFreeSpace(); |
5272 |
claimBottomFreeSpace(); |
5258 |
} |
5273 |
} |
5259 |
if (lastTextChangeReplaceCharCount > 0) { |
5274 |
if (lastTextChangeReplaceCharCount > 0) { |
5260 |
// fixes bug 8273 |
5275 |
// fixes bug 8273 |
5261 |
claimRightFreeSpace(); |
5276 |
claimRightFreeSpace(); |
5262 |
} |
5277 |
} |
5263 |
// do direct drawing if the text change is confined to a single line. |
5278 |
// do direct drawing if the text change is confined to a single line. |
5264 |
// optimization and fixes bug 13999. see also handleTextChanging. |
5279 |
// optimization and fixes bug 13999. see also handleTextChanging. |
5265 |
if (lastTextChangeNewLineCount == 0 && lastTextChangeReplaceLineCount == 0) { |
5280 |
if (lastTextChangeNewLineCount == 0 && lastTextChangeReplaceLineCount == 0) { |
5266 |
int startLine = content.getLineAtOffset(lastTextChangeStart); |
5281 |
int startLine = content.getLineAtOffset(lastTextChangeStart); |
5267 |
int startY = startLine * lineHeight - verticalScrollOffset + topMargin; |
5282 |
int startY = startLine * lineHeight - verticalScrollOffset + topMargin; |
5268 |
|
5283 |
|
5269 |
GC gc = getGC(); |
5284 |
GC gc = getGC(); |
5270 |
Caret caret = getCaret(); |
5285 |
Caret caret = getCaret(); |
5271 |
boolean caretVisible = false; |
5286 |
boolean caretVisible = false; |
5272 |
|
5287 |
|
5273 |
if (caret != null) { |
5288 |
if (caret != null) { |
5274 |
caretVisible = caret.getVisible(); |
5289 |
caretVisible = caret.getVisible(); |
5275 |
caret.setVisible(false); |
5290 |
caret.setVisible(false); |
5276 |
} |
5291 |
} |
5277 |
performPaint(gc, startLine, startY, lineHeight); |
5292 |
performPaint(gc, startLine, startY, lineHeight); |
5278 |
if (caret != null) { |
5293 |
if (caret != null) { |
5279 |
caret.setVisible(caretVisible); |
5294 |
caret.setVisible(caretVisible); |
5280 |
} |
5295 |
} |
5281 |
gc.dispose(); |
5296 |
gc.dispose(); |
5282 |
} |
5297 |
} |
5283 |
} |
5298 |
} |
5284 |
/** |
5299 |
/** |
5285 |
* Updates the screen to reflect a pending content change. |
5300 |
* Updates the screen to reflect a pending content change. |
5286 |
* <p> |
5301 |
* <p> |
5287 |
* |
5302 |
* |
5288 |
* @param event.start the start offset of the change |
5303 |
* @param event.start the start offset of the change |
5289 |
* @param event.newText text that is going to be inserted or empty String |
5304 |
* @param event.newText text that is going to be inserted or empty String |
5290 |
* if no text will be inserted |
5305 |
* if no text will be inserted |
5291 |
* @param event.replaceCharCount length of text that is going to be replaced |
5306 |
* @param event.replaceCharCount length of text that is going to be replaced |
5292 |
* @param event.newCharCount length of text that is going to be inserted |
5307 |
* @param event.newCharCount length of text that is going to be inserted |
5293 |
* @param event.replaceLineCount number of lines that are going to be replaced |
5308 |
* @param event.replaceLineCount number of lines that are going to be replaced |
5294 |
* @param event.newLineCount number of new lines that are going to be inserted |
5309 |
* @param event.newLineCount number of new lines that are going to be inserted |
5295 |
*/ |
5310 |
*/ |
5296 |
void handleTextChanging(TextChangingEvent event) { |
5311 |
void handleTextChanging(TextChangingEvent event) { |
5297 |
int firstLine; |
5312 |
int firstLine; |
5298 |
int textChangeY; |
5313 |
int textChangeY; |
5299 |
boolean isMultiLineChange = event.replaceLineCount > 0 || event.newLineCount > 0; |
5314 |
boolean isMultiLineChange = event.replaceLineCount > 0 || event.newLineCount > 0; |
5300 |
|
5315 |
|
5301 |
if (event.replaceCharCount < 0) { |
5316 |
if (event.replaceCharCount < 0) { |
5302 |
event.start += event.replaceCharCount; |
5317 |
event.start += event.replaceCharCount; |
5303 |
event.replaceCharCount *= -1; |
5318 |
event.replaceCharCount *= -1; |
5304 |
} |
5319 |
} |
5305 |
lastTextChangeStart = event.start; |
5320 |
lastTextChangeStart = event.start; |
5306 |
lastTextChangeNewLineCount = event.newLineCount; |
5321 |
lastTextChangeNewLineCount = event.newLineCount; |
5307 |
lastTextChangeNewCharCount = event.newCharCount; |
5322 |
lastTextChangeNewCharCount = event.newCharCount; |
5308 |
lastTextChangeReplaceLineCount = event.replaceLineCount; |
5323 |
lastTextChangeReplaceLineCount = event.replaceLineCount; |
5309 |
lastTextChangeReplaceCharCount = event.replaceCharCount; |
5324 |
lastTextChangeReplaceCharCount = event.replaceCharCount; |
5310 |
firstLine = content.getLineAtOffset(event.start); |
5325 |
firstLine = content.getLineAtOffset(event.start); |
5311 |
textChangeY = firstLine * lineHeight - verticalScrollOffset + topMargin; |
5326 |
textChangeY = firstLine * lineHeight - verticalScrollOffset + topMargin; |
5312 |
if (isMultiLineChange) { |
5327 |
if (isMultiLineChange) { |
5313 |
redrawMultiLineChange(textChangeY, event.newLineCount, event.replaceLineCount); |
5328 |
redrawMultiLineChange(textChangeY, event.newLineCount, event.replaceLineCount); |
5314 |
} |
5329 |
} |
5315 |
// notify default line styler about text change |
5330 |
// notify default line styler about text change |
5316 |
if (defaultLineStyler != null) { |
5331 |
if (defaultLineStyler != null) { |
5317 |
defaultLineStyler.textChanging(event); |
5332 |
defaultLineStyler.textChanging(event); |
5318 |
} |
5333 |
} |
5319 |
|
5334 |
|
5320 |
// Update the caret offset if it is greater than the length of the content. |
5335 |
// Update the caret offset if it is greater than the length of the content. |
5321 |
// This is necessary since style range API may be called between the |
5336 |
// This is necessary since style range API may be called between the |
5322 |
// handleTextChanging and handleTextChanged events and this API sets the |
5337 |
// handleTextChanging and handleTextChanged events and this API sets the |
5323 |
// caretOffset. |
5338 |
// caretOffset. |
5324 |
int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; |
5339 |
int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; |
5325 |
if (caretOffset > newEndOfText) caretOffset = newEndOfText; |
5340 |
if (caretOffset > newEndOfText) caretOffset = newEndOfText; |
5326 |
} |
5341 |
} |
5327 |
/** |
5342 |
/** |
5328 |
* Called when the widget content is set programatically, overwriting |
5343 |
* Called when the widget content is set programatically, overwriting |
5329 |
* the old content. Resets the caret position, selection and scroll offsets. |
5344 |
* the old content. Resets the caret position, selection and scroll offsets. |
5330 |
* Recalculates the content width and scroll bars. Redraws the widget. |
5345 |
* Recalculates the content width and scroll bars. Redraws the widget. |
5331 |
* <p> |
5346 |
* <p> |
5332 |
* |
5347 |
* |
5333 |
* @param event text change event. |
5348 |
* @param event text change event. |
5334 |
*/ |
5349 |
*/ |
5335 |
void handleTextSet(TextChangedEvent event) { |
5350 |
void handleTextSet(TextChangedEvent event) { |
5336 |
reset(); |
5351 |
reset(); |
5337 |
} |
5352 |
} |
5338 |
/** |
5353 |
/** |
5339 |
* Called when a traversal key is pressed. |
5354 |
* Called when a traversal key is pressed. |
5340 |
* Allow tab next traversal to occur when the widget is in single |
5355 |
* Allow tab next traversal to occur when the widget is in single |
5341 |
* line mode or in multi line and non-editable mode . |
5356 |
* line mode or in multi line and non-editable mode . |
5342 |
* When in editable multi line mode we want to prevent the tab |
5357 |
* When in editable multi line mode we want to prevent the tab |
5343 |
* traversal and receive the tab key event instead. |
5358 |
* traversal and receive the tab key event instead. |
5344 |
* <p> |
5359 |
* <p> |
5345 |
* |
5360 |
* |
5346 |
* @param event the event |
5361 |
* @param event the event |
5347 |
*/ |
5362 |
*/ |
5348 |
void handleTraverse(Event event) { |
5363 |
void handleTraverse(Event event) { |
5349 |
int style = getStyle(); |
5364 |
int style = getStyle(); |
5350 |
boolean ignoreTab = (style & SWT.MULTI) != 0 && !editable || isSingleLine(); |
5365 |
boolean ignoreTab = (style & SWT.MULTI) != 0 && !editable || isSingleLine(); |
5351 |
|
5366 |
|
5352 |
if ((event.detail == SWT.TRAVERSE_TAB_NEXT || |
5367 |
if ((event.detail == SWT.TRAVERSE_TAB_NEXT || |
5353 |
event.detail == SWT.TRAVERSE_RETURN) && ignoreTab) { |
5368 |
event.detail == SWT.TRAVERSE_RETURN) && ignoreTab) { |
5354 |
event.doit = true; |
5369 |
event.doit = true; |
5355 |
} |
5370 |
} |
5356 |
} |
5371 |
} |
5357 |
/** |
5372 |
/** |
5358 |
* Scrolls the widget vertically. |
5373 |
* Scrolls the widget vertically. |
5359 |
*/ |
5374 |
*/ |
5360 |
void handleVerticalScroll(Event event) { |
5375 |
void handleVerticalScroll(Event event) { |
5361 |
setVerticalScrollOffset(getVerticalBar().getSelection(), false); |
5376 |
setVerticalScrollOffset(getVerticalBar().getSelection(), false); |
5362 |
} |
5377 |
} |
5363 |
/** |
5378 |
/** |
5364 |
* Initializes the fonts used to render font styles. |
5379 |
* Initializes the fonts used to render font styles. |
5365 |
* Presently only regular and bold fonts are supported. |
5380 |
* Presently only regular and bold fonts are supported. |
5366 |
*/ |
5381 |
*/ |
5367 |
void initializeRenderer() { |
5382 |
void initializeRenderer() { |
5368 |
if (renderer != null) { |
5383 |
if (renderer != null) { |
5369 |
renderer.dispose(); |
5384 |
renderer.dispose(); |
5370 |
} |
5385 |
} |
5371 |
renderer = new DisplayRenderer( |
5386 |
renderer = new DisplayRenderer( |
5372 |
getDisplay(), getFont(), isBidi(), leftMargin, this, tabLength); |
5387 |
getDisplay(), getFont(), isBidi(), leftMargin, this, tabLength); |
5373 |
lineHeight = renderer.getLineHeight(); |
5388 |
lineHeight = renderer.getLineHeight(); |
5374 |
lineEndSpaceWidth = renderer.getLineEndSpaceWidth(); |
5389 |
lineEndSpaceWidth = renderer.getLineEndSpaceWidth(); |
5375 |
} |
5390 |
} |
5376 |
/** |
5391 |
/** |
5377 |
* Executes the action. |
5392 |
* Executes the action. |
Lines 5380-5557
Link Here
|
5380 |
* @param action one of the actions defined in ST.java |
5395 |
* @param action one of the actions defined in ST.java |
5381 |
*/ |
5396 |
*/ |
5382 |
public void invokeAction(int action) { |
5397 |
public void invokeAction(int action) { |
5383 |
int oldColumnX; |
5398 |
int oldColumnX; |
5384 |
int caretLine; |
5399 |
int caretLine; |
5385 |
|
5400 |
|
5386 |
checkWidget(); |
5401 |
checkWidget(); |
5387 |
switch (action) { |
5402 |
switch (action) { |
5388 |
// Navigation |
5403 |
// Navigation |
5389 |
case ST.LINE_UP: |
5404 |
case ST.LINE_UP: |
5390 |
caretLine = doLineUp(); |
5405 |
caretLine = doLineUp(); |
5391 |
oldColumnX = columnX; |
5406 |
oldColumnX = columnX; |
5392 |
// explicitly go to the calculated caret line. may be different |
5407 |
// explicitly go to the calculated caret line. may be different |
5393 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
5408 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
5394 |
showCaret(caretLine); |
5409 |
showCaret(caretLine); |
5395 |
// save the original horizontal caret position |
5410 |
// save the original horizontal caret position |
5396 |
columnX = oldColumnX; |
5411 |
columnX = oldColumnX; |
5397 |
clearSelection(true); |
5412 |
clearSelection(true); |
5398 |
break; |
5413 |
break; |
5399 |
case ST.LINE_DOWN: |
5414 |
case ST.LINE_DOWN: |
5400 |
caretLine = doLineDown(); |
5415 |
caretLine = doLineDown(); |
5401 |
oldColumnX = columnX; |
5416 |
oldColumnX = columnX; |
5402 |
// explicitly go to the calculated caret line. may be different |
5417 |
// explicitly go to the calculated caret line. may be different |
5403 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
5418 |
// from content.getLineAtOffset(caretOffset) when in word wrap mode |
5404 |
showCaret(caretLine); |
5419 |
showCaret(caretLine); |
5405 |
// save the original horizontal caret position |
5420 |
// save the original horizontal caret position |
5406 |
columnX = oldColumnX; |
5421 |
columnX = oldColumnX; |
5407 |
clearSelection(true); |
5422 |
clearSelection(true); |
5408 |
break; |
5423 |
break; |
5409 |
case ST.LINE_START: |
5424 |
case ST.LINE_START: |
5410 |
doLineStart(); |
5425 |
doLineStart(); |
5411 |
clearSelection(true); |
5426 |
clearSelection(true); |
5412 |
break; |
5427 |
break; |
5413 |
case ST.LINE_END: |
5428 |
case ST.LINE_END: |
5414 |
doLineEnd(); |
5429 |
doLineEnd(); |
5415 |
clearSelection(true); |
5430 |
clearSelection(true); |
5416 |
break; |
5431 |
break; |
5417 |
case ST.COLUMN_PREVIOUS: |
5432 |
case ST.COLUMN_PREVIOUS: |
5418 |
doCursorPrevious(); |
5433 |
doCursorPrevious(); |
5419 |
clearSelection(true); |
5434 |
clearSelection(true); |
5420 |
break; |
5435 |
break; |
5421 |
case ST.COLUMN_NEXT: |
5436 |
case ST.COLUMN_NEXT: |
5422 |
doCursorNext(); |
5437 |
doCursorNext(); |
5423 |
clearSelection(true); |
5438 |
clearSelection(true); |
5424 |
break; |
5439 |
break; |
5425 |
case ST.PAGE_UP: |
5440 |
case ST.PAGE_UP: |
5426 |
doPageUp(); |
5441 |
doPageUp(); |
5427 |
clearSelection(true); |
5442 |
clearSelection(true); |
5428 |
break; |
5443 |
break; |
5429 |
case ST.PAGE_DOWN: |
5444 |
case ST.PAGE_DOWN: |
5430 |
doPageDown(false); |
5445 |
doPageDown(false); |
5431 |
clearSelection(true); |
5446 |
clearSelection(true); |
5432 |
break; |
5447 |
break; |
5433 |
case ST.WORD_PREVIOUS: |
5448 |
case ST.WORD_PREVIOUS: |
5434 |
doWordPrevious(); |
5449 |
doWordPrevious(); |
5435 |
clearSelection(true); |
5450 |
clearSelection(true); |
5436 |
break; |
5451 |
break; |
5437 |
case ST.WORD_NEXT: |
5452 |
case ST.WORD_NEXT: |
5438 |
doWordNext(); |
5453 |
doWordNext(); |
5439 |
clearSelection(true); |
5454 |
clearSelection(true); |
5440 |
break; |
5455 |
break; |
5441 |
case ST.TEXT_START: |
5456 |
case ST.TEXT_START: |
5442 |
doContentStart(); |
5457 |
doContentStart(); |
5443 |
clearSelection(true); |
5458 |
clearSelection(true); |
5444 |
break; |
5459 |
break; |
5445 |
case ST.TEXT_END: |
5460 |
case ST.TEXT_END: |
5446 |
doContentEnd(); |
5461 |
doContentEnd(); |
5447 |
clearSelection(true); |
5462 |
clearSelection(true); |
5448 |
break; |
5463 |
break; |
5449 |
case ST.WINDOW_START: |
5464 |
case ST.WINDOW_START: |
5450 |
doPageStart(); |
5465 |
doPageStart(); |
5451 |
clearSelection(true); |
5466 |
clearSelection(true); |
5452 |
break; |
5467 |
break; |
5453 |
case ST.WINDOW_END: |
5468 |
case ST.WINDOW_END: |
5454 |
doPageEnd(); |
5469 |
doPageEnd(); |
5455 |
clearSelection(true); |
5470 |
clearSelection(true); |
5456 |
break; |
5471 |
break; |
5457 |
// Selection |
5472 |
// Selection |
5458 |
case ST.SELECT_LINE_UP: |
5473 |
case ST.SELECT_LINE_UP: |
5459 |
doSelectionLineUp(); |
5474 |
doSelectionLineUp(); |
5460 |
break; |
5475 |
break; |
5461 |
case ST.SELECT_LINE_DOWN: |
5476 |
case ST.SELECT_LINE_DOWN: |
5462 |
doSelectionLineDown(); |
5477 |
doSelectionLineDown(); |
5463 |
break; |
5478 |
break; |
5464 |
case ST.SELECT_LINE_START: |
5479 |
case ST.SELECT_LINE_START: |
5465 |
doLineStart(); |
5480 |
doLineStart(); |
5466 |
doSelection(SWT.LEFT); |
5481 |
doSelection(SWT.LEFT); |
5467 |
break; |
5482 |
break; |
5468 |
case ST.SELECT_LINE_END: |
5483 |
case ST.SELECT_LINE_END: |
5469 |
doLineEnd(); |
5484 |
doLineEnd(); |
5470 |
doSelection(SWT.RIGHT); |
5485 |
doSelection(SWT.RIGHT); |
5471 |
break; |
5486 |
break; |
5472 |
case ST.SELECT_COLUMN_PREVIOUS: |
5487 |
case ST.SELECT_COLUMN_PREVIOUS: |
5473 |
doSelectionCursorPrevious(); |
5488 |
doSelectionCursorPrevious(); |
5474 |
doSelection(SWT.LEFT); |
5489 |
doSelection(SWT.LEFT); |
5475 |
break; |
5490 |
break; |
5476 |
case ST.SELECT_COLUMN_NEXT: |
5491 |
case ST.SELECT_COLUMN_NEXT: |
5477 |
doSelectionCursorNext(); |
5492 |
doSelectionCursorNext(); |
5478 |
doSelection(SWT.RIGHT); |
5493 |
doSelection(SWT.RIGHT); |
5479 |
break; |
5494 |
break; |
5480 |
case ST.SELECT_PAGE_UP: |
5495 |
case ST.SELECT_PAGE_UP: |
5481 |
doPageUp(); |
5496 |
doPageUp(); |
5482 |
doSelection(SWT.LEFT); |
5497 |
doSelection(SWT.LEFT); |
5483 |
break; |
5498 |
break; |
5484 |
case ST.SELECT_PAGE_DOWN: |
5499 |
case ST.SELECT_PAGE_DOWN: |
5485 |
doPageDown(true); |
5500 |
doPageDown(true); |
5486 |
break; |
5501 |
break; |
5487 |
case ST.SELECT_WORD_PREVIOUS: |
5502 |
case ST.SELECT_WORD_PREVIOUS: |
5488 |
doSelectionWordPrevious(); |
5503 |
doSelectionWordPrevious(); |
5489 |
doSelection(SWT.LEFT); |
5504 |
doSelection(SWT.LEFT); |
5490 |
break; |
5505 |
break; |
5491 |
case ST.SELECT_WORD_NEXT: |
5506 |
case ST.SELECT_WORD_NEXT: |
5492 |
doSelectionWordNext(); |
5507 |
doSelectionWordNext(); |
5493 |
doSelection(SWT.RIGHT); |
5508 |
doSelection(SWT.RIGHT); |
5494 |
break; |
5509 |
break; |
5495 |
case ST.SELECT_TEXT_START: |
5510 |
case ST.SELECT_TEXT_START: |
5496 |
doContentStart(); |
5511 |
doContentStart(); |
5497 |
doSelection(SWT.LEFT); |
5512 |
doSelection(SWT.LEFT); |
5498 |
break; |
5513 |
break; |
5499 |
case ST.SELECT_TEXT_END: |
5514 |
case ST.SELECT_TEXT_END: |
5500 |
doContentEnd(); |
5515 |
doContentEnd(); |
5501 |
doSelection(SWT.RIGHT); |
5516 |
doSelection(SWT.RIGHT); |
5502 |
break; |
5517 |
break; |
5503 |
case ST.SELECT_WINDOW_START: |
5518 |
case ST.SELECT_WINDOW_START: |
5504 |
doPageStart(); |
5519 |
doPageStart(); |
5505 |
doSelection(SWT.LEFT); |
5520 |
doSelection(SWT.LEFT); |
5506 |
break; |
5521 |
break; |
5507 |
case ST.SELECT_WINDOW_END: |
5522 |
case ST.SELECT_WINDOW_END: |
5508 |
doPageEnd(); |
5523 |
doPageEnd(); |
5509 |
doSelection(SWT.RIGHT); |
5524 |
doSelection(SWT.RIGHT); |
5510 |
break; |
5525 |
break; |
5511 |
// Modification |
5526 |
// Modification |
5512 |
case ST.CUT: |
5527 |
case ST.CUT: |
5513 |
cut(); |
5528 |
cut(); |
5514 |
break; |
5529 |
break; |
5515 |
case ST.COPY: |
5530 |
case ST.COPY: |
5516 |
copy(); |
5531 |
copy(); |
5517 |
break; |
5532 |
break; |
5518 |
case ST.PASTE: |
5533 |
case ST.PASTE: |
5519 |
paste(); |
5534 |
paste(); |
5520 |
break; |
5535 |
break; |
5521 |
case ST.DELETE_PREVIOUS: |
5536 |
case ST.DELETE_PREVIOUS: |
5522 |
doBackspace(); |
5537 |
doBackspace(); |
5523 |
break; |
5538 |
break; |
5524 |
case ST.DELETE_NEXT: |
5539 |
case ST.DELETE_NEXT: |
5525 |
doDelete(); |
5540 |
doDelete(); |
5526 |
break; |
5541 |
break; |
5527 |
// Miscellaneous |
5542 |
// Miscellaneous |
5528 |
case ST.TOGGLE_OVERWRITE: |
5543 |
case ST.TOGGLE_OVERWRITE: |
5529 |
overwrite = !overwrite; // toggle insert/overwrite mode |
5544 |
overwrite = !overwrite; // toggle insert/overwrite mode |
5530 |
break; |
5545 |
break; |
5531 |
} |
5546 |
} |
5532 |
} |
5547 |
} |
5533 |
/** |
5548 |
/** |
5534 |
* Temporary until SWT provides this |
5549 |
* Temporary until SWT provides this |
5535 |
*/ |
5550 |
*/ |
5536 |
boolean isBidi() { |
5551 |
boolean isBidi() { |
5537 |
return isBidi; |
5552 |
return isBidi; |
5538 |
} |
5553 |
} |
5539 |
/** |
5554 |
/** |
5540 |
* Returns whether the given offset is inside a multi byte line delimiter. |
5555 |
* Returns whether the given offset is inside a multi byte line delimiter. |
5541 |
* Example: |
5556 |
* Example: |
5542 |
* "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true |
5557 |
* "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true |
5543 |
* |
5558 |
* |
5544 |
* @return true if the given offset is inside a multi byte line delimiter. |
5559 |
* @return true if the given offset is inside a multi byte line delimiter. |
5545 |
* false if the given offset is before or after a line delimiter. |
5560 |
* false if the given offset is before or after a line delimiter. |
5546 |
*/ |
5561 |
*/ |
5547 |
boolean isLineDelimiter(int offset) { |
5562 |
boolean isLineDelimiter(int offset) { |
5548 |
int line = content.getLineAtOffset(offset); |
5563 |
int line = content.getLineAtOffset(offset); |
5549 |
int lineOffset = content.getOffsetAtLine(line); |
5564 |
int lineOffset = content.getOffsetAtLine(line); |
5550 |
int offsetInLine = offset - lineOffset; |
5565 |
int offsetInLine = offset - lineOffset; |
5551 |
// offsetInLine will be greater than line length if the line |
5566 |
// offsetInLine will be greater than line length if the line |
5552 |
// delimiter is longer than one character and the offset is set |
5567 |
// delimiter is longer than one character and the offset is set |
5553 |
// in between parts of the line delimiter. |
5568 |
// in between parts of the line delimiter. |
5554 |
return offsetInLine > content.getLine(line).length(); |
5569 |
return offsetInLine > content.getLine(line).length(); |
5555 |
} |
5570 |
} |
5556 |
/** |
5571 |
/** |
5557 |
* Returns whether or not the given lines are visible. |
5572 |
* Returns whether or not the given lines are visible. |
Lines 5561-5750
Link Here
|
5561 |
* false if none of the lines is visible |
5576 |
* false if none of the lines is visible |
5562 |
*/ |
5577 |
*/ |
5563 |
boolean isAreaVisible(int firstLine, int lastLine) { |
5578 |
boolean isAreaVisible(int firstLine, int lastLine) { |
5564 |
int partialBottomIndex = getPartialBottomIndex(); |
5579 |
int partialBottomIndex = getPartialBottomIndex(); |
5565 |
int partialTopIndex = verticalScrollOffset / lineHeight; |
5580 |
int partialTopIndex = verticalScrollOffset / lineHeight; |
5566 |
boolean notVisible = firstLine > partialBottomIndex || lastLine < partialTopIndex; |
5581 |
boolean notVisible = firstLine > partialBottomIndex || lastLine < partialTopIndex; |
5567 |
return !notVisible; |
5582 |
return !notVisible; |
|
|
5583 |
} |
5584 |
/** |
5585 |
* Tests whether the mouse pointer is over a selection. |
5586 |
* |
5587 |
* @param x mouse x position in client coordinates |
5588 |
* @param y mouse y position in client coordinates |
5589 |
*/ |
5590 |
private boolean isMouseOverSelection(int x, int y) { |
5591 |
if (selectionAnchor == -1) { |
5592 |
// no selection |
5593 |
return false; |
5594 |
} else { |
5595 |
// there is a selection |
5596 |
int mouseLineIndex = (y + verticalScrollOffset) / lineHeight; |
5597 |
int mouseCharOffset; |
5598 |
int selLineIndexX; |
5599 |
int selLineIndexY; |
5600 |
int selLineOffset; |
5601 |
String lineContent = null; |
5602 |
|
5603 |
selLineIndexX = content.getLineAtOffset(selection.x); |
5604 |
selLineIndexY = content.getLineAtOffset(selection.y); |
5605 |
|
5606 |
if ((mouseLineIndex < selLineIndexX) || (mouseLineIndex > selLineIndexY)) { |
5607 |
// mouse is before the first or after the last line of the selection |
5608 |
return false; |
5609 |
} |
5610 |
|
5611 |
if (mouseLineIndex == selLineIndexX) { |
5612 |
// the mouse is on the first line of the selection |
5613 |
selLineOffset = content.getOffsetAtLine(selLineIndexX); |
5614 |
lineContent = content.getLine(selLineIndexX); |
5615 |
if (x < getXAtOffset(lineContent, selLineIndexX, selection.x - selLineOffset)) { |
5616 |
// mouse is before the start of the selection |
5617 |
return false; |
5618 |
} |
5619 |
} |
5620 |
|
5621 |
if (mouseLineIndex == selLineIndexY) { |
5622 |
// the mouse is on the last line of the selection |
5623 |
selLineOffset = content.getOffsetAtLine(selLineIndexY); |
5624 |
if (selLineIndexY != selLineIndexX) { |
5625 |
lineContent = content.getLine(selLineIndexY); |
5626 |
} |
5627 |
if (x > getXAtOffset(lineContent, selLineIndexY, selection.y - selLineOffset)) { |
5628 |
// mouse is after the end of the selection |
5629 |
return false; |
5630 |
} |
5631 |
} |
5632 |
|
5633 |
// mouse is over the selection |
5634 |
return true; |
5635 |
} |
5568 |
} |
5636 |
} |
5569 |
/** |
5637 |
/** |
5570 |
* Returns whether or not the given styles will necessitate a redraw for the given start line. |
5638 |
* Returns whether or not the given styles will necessitate a redraw for the given start line. |
5571 |
* A redraw is necessary when font style changes after the start of a style will take place. |
5639 |
* A redraw is necessary when font style changes after the start of a style will take place. |
5572 |
* This method assumes ranges is in order and non-overlapping. |
5640 |
* This method assumes ranges is in order and non-overlapping. |
5573 |
* <p> |
5641 |
* <p> |
5574 |
* |
5642 |
* |
5575 |
* @return true if a redraw of the given line is necessary, false otherwise |
5643 |
* @return true if a redraw of the given line is necessary, false otherwise |
5576 |
*/ |
5644 |
*/ |
5577 |
boolean isRedrawFirstLine(StyleRange[] ranges, int firstLine, int firstLineOffset) { |
5645 |
boolean isRedrawFirstLine(StyleRange[] ranges, int firstLine, int firstLineOffset) { |
5578 |
int lineEnd = firstLineOffset + content.getLine(firstLine).length(); |
5646 |
int lineEnd = firstLineOffset + content.getLine(firstLine).length(); |
5579 |
for (int i=0; i<ranges.length; i++) { |
5647 |
for (int i=0; i<ranges.length; i++) { |
5580 |
StyleRange range = ranges[i]; |
5648 |
StyleRange range = ranges[i]; |
5581 |
// does the style start on the first line? |
5649 |
// does the style start on the first line? |
5582 |
if (range.start < lineEnd) { |
5650 |
if (range.start < lineEnd) { |
5583 |
int rangeEnd = range.start + range.length; |
5651 |
int rangeEnd = range.start + range.length; |
5584 |
if (isStyleChanging(range, range.start, Math.min(rangeEnd, lineEnd))) return true; |
5652 |
if (isStyleChanging(range, range.start, Math.min(rangeEnd, lineEnd))) return true; |
5585 |
} else { |
5653 |
} else { |
5586 |
return false; |
5654 |
return false; |
5587 |
} |
5655 |
} |
5588 |
} |
5656 |
} |
5589 |
return false; |
5657 |
return false; |
5590 |
} |
5658 |
} |
5591 |
/** |
5659 |
/** |
5592 |
* Returns whether or not the given styles will necessitate a redraw for the given end line. |
5660 |
* Returns whether or not the given styles will necessitate a redraw for the given end line. |
5593 |
* A redraw is necessary when font style changes after the start of a style will take place. |
5661 |
* A redraw is necessary when font style changes after the start of a style will take place. |
5594 |
* This method assumes ranges is in order and non-overlapping. |
5662 |
* This method assumes ranges is in order and non-overlapping. |
5595 |
* <p> |
5663 |
* <p> |
5596 |
* |
5664 |
* |
5597 |
* @return true if a redraw of the last line is necessary, false otherwise |
5665 |
* @return true if a redraw of the last line is necessary, false otherwise |
5598 |
*/ |
5666 |
*/ |
5599 |
boolean isRedrawLastLine(StyleRange[] ranges, int lastLine, int lastLineOffset) { |
5667 |
boolean isRedrawLastLine(StyleRange[] ranges, int lastLine, int lastLineOffset) { |
5600 |
for (int i = ranges.length - 1; i >= 0; i--) { |
5668 |
for (int i = ranges.length - 1; i >= 0; i--) { |
5601 |
StyleRange range = ranges[i]; |
5669 |
StyleRange range = ranges[i]; |
5602 |
int rangeEnd = range.start + range.length; |
5670 |
int rangeEnd = range.start + range.length; |
5603 |
// does style range end on the last line? |
5671 |
// does style range end on the last line? |
5604 |
if (rangeEnd >= lastLineOffset) { |
5672 |
if (rangeEnd >= lastLineOffset) { |
5605 |
if (isStyleChanging(range, Math.max(range.start, lastLineOffset), rangeEnd)) return true; |
5673 |
if (isStyleChanging(range, Math.max(range.start, lastLineOffset), rangeEnd)) return true; |
5606 |
} else { |
5674 |
} else { |
5607 |
break; |
5675 |
break; |
5608 |
} |
5676 |
} |
5609 |
} |
5677 |
} |
5610 |
return false; |
5678 |
return false; |
5611 |
} |
5679 |
} |
5612 |
/** |
5680 |
/** |
5613 |
* Returns whether the widget can have only one line. |
5681 |
* Returns whether the widget can have only one line. |
5614 |
* <p> |
5682 |
* <p> |
5615 |
* |
5683 |
* |
5616 |
* @return true if widget can have only one line, false if widget can have |
5684 |
* @return true if widget can have only one line, false if widget can have |
5617 |
* multiple lines |
5685 |
* multiple lines |
5618 |
*/ |
5686 |
*/ |
5619 |
boolean isSingleLine() { |
5687 |
boolean isSingleLine() { |
5620 |
return (getStyle() & SWT.SINGLE) != 0; |
5688 |
return (getStyle() & SWT.SINGLE) != 0; |
5621 |
} |
5689 |
} |
5622 |
/** |
5690 |
/** |
5623 |
* Returns whether the font style in the given style range is changing |
5691 |
* Returns whether the font style in the given style range is changing |
5624 |
* from SWT.NORMAL to SWT.BOLD or vice versa. |
5692 |
* from SWT.NORMAL to SWT.BOLD or vice versa. |
5625 |
* <p> |
5693 |
* <p> |
5626 |
* |
5694 |
* |
5627 |
* @param range StyleRange to compare current font style with. |
5695 |
* @param range StyleRange to compare current font style with. |
5628 |
* @param start offset of the first font style to compare |
5696 |
* @param start offset of the first font style to compare |
5629 |
* @param end offset behind the last font style to compare |
5697 |
* @param end offset behind the last font style to compare |
5630 |
* @return true if the font style is changing in the given style range, |
5698 |
* @return true if the font style is changing in the given style range, |
5631 |
* false if the font style is not changing in the given style range. |
5699 |
* false if the font style is not changing in the given style range. |
5632 |
* @exception SWTException <ul> |
5700 |
* @exception SWTException <ul> |
5633 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5701 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5634 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5702 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
5635 |
* </ul> |
5703 |
* </ul> |
5636 |
*/ |
5704 |
*/ |
5637 |
boolean isStyleChanging(StyleRange range, int start, int end) { |
5705 |
boolean isStyleChanging(StyleRange range, int start, int end) { |
5638 |
checkWidget(); |
5706 |
checkWidget(); |
5639 |
StyleRange[] styles = defaultLineStyler.getStyleRangesFor(start, end - start); |
5707 |
StyleRange[] styles = defaultLineStyler.getStyleRangesFor(start, end - start); |
5640 |
|
5708 |
|
5641 |
if (styles == null) { |
5709 |
if (styles == null) { |
5642 |
return (range.fontStyle != SWT.NORMAL); |
5710 |
return (range.fontStyle != SWT.NORMAL); |
5643 |
} |
5711 |
} |
5644 |
for (int i = 0; i < styles.length; i++) { |
5712 |
for (int i = 0; i < styles.length; i++) { |
5645 |
StyleRange newStyle = styles[i]; |
5713 |
StyleRange newStyle = styles[i]; |
5646 |
if (newStyle.fontStyle != range.fontStyle) { |
5714 |
if (newStyle.fontStyle != range.fontStyle) { |
5647 |
return true; |
5715 |
return true; |
5648 |
} |
5716 |
} |
5649 |
} |
5717 |
} |
5650 |
return false; |
5718 |
return false; |
5651 |
} |
5719 |
} |
5652 |
/** |
5720 |
/** |
5653 |
* Sends the specified verify event, replace/insert text as defined by |
5721 |
* Sends the specified verify event, replace/insert text as defined by |
5654 |
* the event and send a modify event. |
5722 |
* the event and send a modify event. |
5655 |
* <p> |
5723 |
* <p> |
5656 |
* |
5724 |
* |
5657 |
* @param event the text change event. |
5725 |
* @param event the text change event. |
5658 |
* <ul> |
5726 |
* <ul> |
5659 |
* <li>event.start - the replace start offset</li> |
5727 |
* <li>event.start - the replace start offset</li> |
5660 |
* <li>event.end - the replace end offset</li> |
5728 |
* <li>event.end - the replace end offset</li> |
5661 |
* <li>event.text - the new text</li> |
5729 |
* <li>event.text - the new text</li> |
5662 |
* </ul> |
5730 |
* </ul> |
5663 |
* @param updateCaret whether or not he caret should be set behind |
5731 |
* @param updateCaret whether or not he caret should be set behind |
5664 |
* the new text |
5732 |
* the new text |
5665 |
*/ |
5733 |
*/ |
5666 |
void modifyContent(Event event, boolean updateCaret) { |
5734 |
void modifyContent(Event event, boolean updateCaret) { |
5667 |
event.doit = true; |
5735 |
event.doit = true; |
5668 |
notifyListeners(SWT.Verify, event); |
5736 |
notifyListeners(SWT.Verify, event); |
5669 |
if (event.doit) { |
5737 |
if (event.doit) { |
5670 |
StyledTextEvent styledTextEvent = null; |
5738 |
StyledTextEvent styledTextEvent = null; |
5671 |
int replacedLength = event.end - event.start; |
5739 |
int replacedLength = event.end - event.start; |
5672 |
boolean isCharacterRemove = replacedLength == 1 && event.text.length() == 0; |
5740 |
boolean isCharacterRemove = replacedLength == 1 && event.text.length() == 0; |
5673 |
boolean isBackspace = event.start < caretOffset; |
5741 |
boolean isBackspace = event.start < caretOffset; |
5674 |
boolean isDirectionBoundary = false; |
5742 |
boolean isDirectionBoundary = false; |
5675 |
|
5743 |
|
5676 |
if (updateCaret && isBidi() && isCharacterRemove) { |
5744 |
if (updateCaret && isBidi() && isCharacterRemove) { |
5677 |
// set the keyboard language to the language of the deleted character. |
5745 |
// set the keyboard language to the language of the deleted character. |
5678 |
// determine direction boundary so that caret location can be updated |
5746 |
// determine direction boundary so that caret location can be updated |
5679 |
// properly. |
5747 |
// properly. |
5680 |
int line = content.getLineAtOffset(caretOffset); |
5748 |
int line = content.getLineAtOffset(caretOffset); |
5681 |
int lineStartOffset = content.getOffsetAtLine(line); |
5749 |
int lineStartOffset = content.getOffsetAtLine(line); |
5682 |
int offsetInLine = caretOffset - lineStartOffset; |
5750 |
int offsetInLine = caretOffset - lineStartOffset; |
5683 |
String lineText = content.getLine(line); |
5751 |
String lineText = content.getLine(line); |
5684 |
GC gc = getGC(); |
5752 |
GC gc = getGC(); |
5685 |
StyledTextBidi bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); |
5753 |
StyledTextBidi bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); |
5686 |
if (isBackspace) { |
5754 |
if (isBackspace) { |
5687 |
if (offsetInLine > 0) { |
5755 |
if (offsetInLine > 0) { |
5688 |
// the line start/end does not represent a direction boundary |
5756 |
// the line start/end does not represent a direction boundary |
5689 |
// even if the previous/next line has a different direction. |
5757 |
// even if the previous/next line has a different direction. |
5690 |
isDirectionBoundary = |
5758 |
isDirectionBoundary = |
5691 |
offsetInLine < lineText.length() && |
5759 |
offsetInLine < lineText.length() && |
5692 |
(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || |
5760 |
(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || |
5693 |
bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); |
5761 |
bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); |
5694 |
bidi.setKeyboardLanguage(offsetInLine - 1); |
5762 |
bidi.setKeyboardLanguage(offsetInLine - 1); |
5695 |
} |
5763 |
} |
5696 |
} |
5764 |
} |
5697 |
else { |
5765 |
else { |
5698 |
if (offsetInLine < lineText.length()) { |
5766 |
if (offsetInLine < lineText.length()) { |
5699 |
// the line start/end does not represent a direction boundary |
5767 |
// the line start/end does not represent a direction boundary |
5700 |
// even if the previous/next line has a different direction. |
5768 |
// even if the previous/next line has a different direction. |
5701 |
isDirectionBoundary = |
5769 |
isDirectionBoundary = |
5702 |
offsetInLine > 0 && |
5770 |
offsetInLine > 0 && |
5703 |
(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || |
5771 |
(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || |
5704 |
bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); |
5772 |
bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); |
5705 |
bidi.setKeyboardLanguage(offsetInLine); |
5773 |
bidi.setKeyboardLanguage(offsetInLine); |
5706 |
} |
5774 |
} |
5707 |
} |
5775 |
} |
5708 |
gc.dispose(); |
5776 |
gc.dispose(); |
5709 |
} |
5777 |
} |
5710 |
if (isListening(ExtendedModify)) { |
5778 |
if (isListening(ExtendedModify)) { |
5711 |
styledTextEvent = new StyledTextEvent(logicalContent); |
5779 |
styledTextEvent = new StyledTextEvent(logicalContent); |
5712 |
styledTextEvent.start = event.start; |
5780 |
styledTextEvent.start = event.start; |
5713 |
styledTextEvent.end = event.start + event.text.length(); |
5781 |
styledTextEvent.end = event.start + event.text.length(); |
5714 |
styledTextEvent.text = content.getTextRange(event.start, replacedLength); |
5782 |
styledTextEvent.text = content.getTextRange(event.start, replacedLength); |
5715 |
} |
5783 |
} |
5716 |
content.replaceTextRange(event.start, replacedLength, event.text); |
5784 |
content.replaceTextRange(event.start, replacedLength, event.text); |
5717 |
// set the caret position prior to sending the modify event. |
5785 |
// set the caret position prior to sending the modify event. |
5718 |
// fixes 1GBB8NJ |
5786 |
// fixes 1GBB8NJ |
5719 |
if (updateCaret) { |
5787 |
if (updateCaret) { |
5720 |
// always update the caret location. fixes 1G8FODP |
5788 |
// always update the caret location. fixes 1G8FODP |
5721 |
internalSetSelection(event.start + event.text.length(), 0, true); |
5789 |
internalSetSelection(event.start + event.text.length(), 0, true); |
5722 |
if (isBidi()) { |
5790 |
if (isBidi()) { |
5723 |
// Update the caret direction so that the caret moves to the |
5791 |
// Update the caret direction so that the caret moves to the |
5724 |
// typed/deleted character. Fixes 1GJLQ16. |
5792 |
// typed/deleted character. Fixes 1GJLQ16. |
5725 |
if (isCharacterRemove) { |
5793 |
if (isCharacterRemove) { |
5726 |
updateBidiDirection(isBackspace, isDirectionBoundary); |
5794 |
updateBidiDirection(isBackspace, isDirectionBoundary); |
5727 |
} |
5795 |
} |
5728 |
else { |
5796 |
else { |
5729 |
lastCaretDirection = ST.COLUMN_NEXT; |
5797 |
lastCaretDirection = ST.COLUMN_NEXT; |
5730 |
} |
5798 |
} |
5731 |
showBidiCaret(); |
5799 |
showBidiCaret(); |
5732 |
} |
5800 |
} |
5733 |
else { |
5801 |
else { |
5734 |
showCaret(); |
5802 |
showCaret(); |
5735 |
} |
5803 |
} |
5736 |
} |
5804 |
} |
5737 |
notifyListeners(SWT.Modify, event); |
5805 |
notifyListeners(SWT.Modify, event); |
5738 |
if (isListening(ExtendedModify)) { |
5806 |
if (isListening(ExtendedModify)) { |
5739 |
notifyListeners(ExtendedModify, styledTextEvent); |
5807 |
notifyListeners(ExtendedModify, styledTextEvent); |
5740 |
} |
5808 |
} |
5741 |
} |
5809 |
} |
5742 |
} |
5810 |
} |
5743 |
/** |
5811 |
/** |
5744 |
* Replaces the selection with the clipboard text or insert the text at |
5812 |
* Replaces the selection with the clipboard text or insert the text at |
5745 |
* the current caret offset if there is no selection. |
5813 |
* the current caret offset if there is no selection. |
5746 |
* If the widget has the SWT.SINGLE style and the clipboard text contains |
5814 |
* If the widget has the SWT.SINGLE style and the clipboard text contains |
5747 |
* more than one line, only the first line without line delimiters is |
5815 |
* more than one line, only the first line without line delimiters is |
5748 |
* inserted in the widget. |
5816 |
* inserted in the widget. |
5749 |
* <p> |
5817 |
* <p> |
5750 |
* |
5818 |
* |
Lines 5754-5826
Link Here
|
5754 |
* </ul> |
5822 |
* </ul> |
5755 |
*/ |
5823 |
*/ |
5756 |
public void paste(){ |
5824 |
public void paste(){ |
5757 |
checkWidget(); |
5825 |
checkWidget(); |
5758 |
TextTransfer transfer = TextTransfer.getInstance(); |
5826 |
TextTransfer transfer = TextTransfer.getInstance(); |
5759 |
String text; |
5827 |
String text; |
5760 |
text = (String) clipboard.getContents(transfer); |
5828 |
text = (String) clipboard.getContents(transfer); |
5761 |
if (text != null && text.length() > 0) { |
5829 |
if (text != null && text.length() > 0) { |
5762 |
Event event = new Event(); |
5830 |
Event event = new Event(); |
5763 |
event.start = selection.x; |
5831 |
event.start = selection.x; |
5764 |
event.end = selection.y; |
5832 |
event.end = selection.y; |
5765 |
event.text = getModelDelimitedText(text); |
5833 |
event.text = getModelDelimitedText(text); |
5766 |
sendKeyEvent(event); |
5834 |
sendKeyEvent(event); |
5767 |
} |
5835 |
} |
5768 |
} |
5836 |
} |
5769 |
/** |
5837 |
/** |
5770 |
* Render the specified area. Broken out as its own method to support |
5838 |
* Render the specified area. Broken out as its own method to support |
5771 |
* direct drawing. |
5839 |
* direct drawing. |
5772 |
* <p> |
5840 |
* <p> |
5773 |
* |
5841 |
* |
5774 |
* @param gc GC to render on |
5842 |
* @param gc GC to render on |
5775 |
* @param startLine first line to render |
5843 |
* @param startLine first line to render |
5776 |
* @param startY y pixel location to start rendering at |
5844 |
* @param startY y pixel location to start rendering at |
5777 |
* @param renderHeight renderHeight widget area that needs to be filled with lines |
5845 |
* @param renderHeight renderHeight widget area that needs to be filled with lines |
5778 |
*/ |
5846 |
*/ |
5779 |
void performPaint(GC gc,int startLine,int startY, int renderHeight) { |
5847 |
void performPaint(GC gc,int startLine,int startY, int renderHeight) { |
5780 |
Rectangle clientArea = getClientArea(); |
5848 |
Rectangle clientArea = getClientArea(); |
5781 |
Color background = getBackground(); |
5849 |
Color background = getBackground(); |
5782 |
|
5850 |
|
5783 |
// Check if there is work to do. We never want to try and create |
5851 |
// Check if there is work to do. We never want to try and create |
5784 |
// an Image with 0 width or 0 height. |
5852 |
// an Image with 0 width or 0 height. |
5785 |
if (clientArea.width == 0) { |
5853 |
if (clientArea.width == 0) { |
5786 |
return; |
5854 |
return; |
5787 |
} |
5855 |
} |
5788 |
if (renderHeight > 0) { |
5856 |
if (renderHeight > 0) { |
5789 |
// renderHeight will be negative when only top margin needs redrawing |
5857 |
// renderHeight will be negative when only top margin needs redrawing |
5790 |
Color foreground = getForeground(); |
5858 |
Color foreground = getForeground(); |
5791 |
int lineCount = content.getLineCount(); |
5859 |
int lineCount = content.getLineCount(); |
5792 |
int paintY = 0; |
5860 |
int paintY = 0; |
5793 |
|
5861 |
|
5794 |
if (isSingleLine()) { |
5862 |
if (isSingleLine()) { |
5795 |
lineCount = 1; |
5863 |
lineCount = 1; |
5796 |
if (startLine > 1) { |
5864 |
if (startLine > 1) { |
5797 |
startLine = 1; |
5865 |
startLine = 1; |
5798 |
} |
5866 |
} |
5799 |
} |
5867 |
} |
5800 |
Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight); |
5868 |
Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight); |
5801 |
GC lineGC = new GC(lineBuffer); |
5869 |
GC lineGC = new GC(lineBuffer); |
5802 |
|
5870 |
|
5803 |
lineGC.setFont(getFont()); |
5871 |
lineGC.setFont(getFont()); |
5804 |
renderer.setCurrentFontStyle(SWT.NORMAL); |
5872 |
renderer.setCurrentFontStyle(SWT.NORMAL); |
5805 |
lineGC.setForeground(foreground); |
5873 |
lineGC.setForeground(foreground); |
5806 |
lineGC.setBackground(background); |
5874 |
lineGC.setBackground(background); |
5807 |
|
5875 |
|
5808 |
for (int i = startLine; paintY < renderHeight && i < lineCount; i++, paintY += lineHeight) { |
5876 |
for (int i = startLine; paintY < renderHeight && i < lineCount; i++, paintY += lineHeight) { |
5809 |
String line = content.getLine(i); |
5877 |
String line = content.getLine(i); |
5810 |
renderer.drawLine(line, i, paintY, lineGC, background, foreground, true); |
5878 |
renderer.drawLine(line, i, paintY, lineGC, background, foreground, true); |
5811 |
} |
5879 |
} |
5812 |
if (paintY < renderHeight) { |
5880 |
if (paintY < renderHeight) { |
5813 |
lineGC.setBackground(background); |
5881 |
lineGC.setBackground(background); |
5814 |
lineGC.setForeground(background); |
5882 |
lineGC.setForeground(background); |
5815 |
lineGC.fillRectangle(0, paintY, clientArea.width, renderHeight - paintY); |
5883 |
lineGC.fillRectangle(0, paintY, clientArea.width, renderHeight - paintY); |
5816 |
} |
5884 |
} |
5817 |
gc.drawImage(lineBuffer, 0, startY); |
5885 |
gc.drawImage(lineBuffer, 0, startY); |
5818 |
lineGC.dispose(); |
5886 |
lineGC.dispose(); |
5819 |
lineBuffer.dispose(); |
5887 |
lineBuffer.dispose(); |
5820 |
} |
5888 |
} |
5821 |
clearMargin(gc, background, clientArea, renderHeight); |
5889 |
clearMargin(gc, background, clientArea, renderHeight); |
5822 |
} |
5890 |
} |
5823 |
/** |
5891 |
/** |
5824 |
* Prints the widget's text to the default printer. |
5892 |
* Prints the widget's text to the default printer. |
5825 |
* |
5893 |
* |
5826 |
* @exception SWTException <ul> |
5894 |
* @exception SWTException <ul> |
Lines 5829-5852
Link Here
|
5829 |
* </ul> |
5897 |
* </ul> |
5830 |
*/ |
5898 |
*/ |
5831 |
public void print() { |
5899 |
public void print() { |
5832 |
checkWidget(); |
5900 |
checkWidget(); |
5833 |
Printer printer = new Printer(); |
5901 |
Printer printer = new Printer(); |
5834 |
StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5902 |
StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5835 |
|
5903 |
|
5836 |
options.printTextForeground = true; |
5904 |
options.printTextForeground = true; |
5837 |
options.printTextBackground = true; |
5905 |
options.printTextBackground = true; |
5838 |
options.printTextFontStyle = true; |
5906 |
options.printTextFontStyle = true; |
5839 |
options.printLineBackground = true; |
5907 |
options.printLineBackground = true; |
5840 |
new Printing(this, printer, options).run(); |
5908 |
new Printing(this, printer, options).run(); |
5841 |
printer.dispose(); |
5909 |
printer.dispose(); |
5842 |
} |
5910 |
} |
5843 |
/** |
5911 |
/** |
5844 |
* Returns a runnable that will print the widget's text |
5912 |
* Returns a runnable that will print the widget's text |
5845 |
* to the specified printer. |
5913 |
* to the specified printer. |
5846 |
* <p> |
5914 |
* <p> |
5847 |
* The runnable may be run in a non-UI thread. |
5915 |
* The runnable may be run in a non-UI thread. |
5848 |
* </p> |
5916 |
* </p> |
5849 |
* |
5917 |
* |
5850 |
* @param printer the printer to print to |
5918 |
* @param printer the printer to print to |
5851 |
* @exception SWTException <ul> |
5919 |
* @exception SWTException <ul> |
5852 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
5920 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 5857-5881
Link Here
|
5857 |
* </ul> |
5925 |
* </ul> |
5858 |
*/ |
5926 |
*/ |
5859 |
public Runnable print(Printer printer) { |
5927 |
public Runnable print(Printer printer) { |
5860 |
StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5928 |
StyledTextPrintOptions options = new StyledTextPrintOptions(); |
5861 |
|
5929 |
|
5862 |
checkWidget(); |
5930 |
checkWidget(); |
5863 |
options.printTextForeground = true; |
5931 |
options.printTextForeground = true; |
5864 |
options.printTextBackground = true; |
5932 |
options.printTextBackground = true; |
5865 |
options.printTextFontStyle = true; |
5933 |
options.printTextFontStyle = true; |
5866 |
options.printLineBackground = true; |
5934 |
options.printLineBackground = true; |
5867 |
if (printer == null) { |
5935 |
if (printer == null) { |
5868 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
5936 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
5869 |
} |
5937 |
} |
5870 |
return print(printer, options); |
5938 |
return print(printer, options); |
5871 |
} |
5939 |
} |
5872 |
/** |
5940 |
/** |
5873 |
* Returns a runnable that will print the widget's text |
5941 |
* Returns a runnable that will print the widget's text |
5874 |
* to the specified printer. |
5942 |
* to the specified printer. |
5875 |
* <p> |
5943 |
* <p> |
5876 |
* The runnable may be run in a non-UI thread. |
5944 |
* The runnable may be run in a non-UI thread. |
5877 |
* </p> |
5945 |
* </p> |
5878 |
* |
5946 |
* |
5879 |
* @param printer the printer to print to |
5947 |
* @param printer the printer to print to |
5880 |
* @param options print options to use during printing |
5948 |
* @param options print options to use during printing |
5881 |
* @exception SWTException <ul> |
5949 |
* @exception SWTException <ul> |
Lines 5888-5898
Link Here
|
5888 |
* @since 2.1 |
5956 |
* @since 2.1 |
5889 |
*/ |
5957 |
*/ |
5890 |
public Runnable print(Printer printer, StyledTextPrintOptions options) { |
5958 |
public Runnable print(Printer printer, StyledTextPrintOptions options) { |
5891 |
checkWidget(); |
5959 |
checkWidget(); |
5892 |
if (printer == null || options == null) { |
5960 |
if (printer == null || options == null) { |
5893 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
5961 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
5894 |
} |
5962 |
} |
5895 |
return new Printing(this, printer, options); |
5963 |
return new Printing(this, printer, options); |
5896 |
} |
5964 |
} |
5897 |
/** |
5965 |
/** |
5898 |
* Causes the entire bounds of the receiver to be marked |
5966 |
* Causes the entire bounds of the receiver to be marked |
Lines 5900-5907
Link Here
|
5900 |
* is processed, the control will be completely painted. |
5968 |
* is processed, the control will be completely painted. |
5901 |
* <p> |
5969 |
* <p> |
5902 |
* Recalculates the content width for all lines in the bounds. |
5970 |
* Recalculates the content width for all lines in the bounds. |
5903 |
* When a <code>LineStyleListener</code> is used a redraw call |
5971 |
* When a <code>LineStyleListener</code> is used a redraw call |
5904 |
* is the only notification to the widget that styles have changed |
5972 |
* is the only notification to the widget that styles have changed |
5905 |
* and that the content width may have changed. |
5973 |
* and that the content width may have changed. |
5906 |
* </p> |
5974 |
* </p> |
5907 |
* |
5975 |
* |
Lines 5913-5940
Link Here
|
5913 |
* @see Control#update |
5981 |
* @see Control#update |
5914 |
*/ |
5982 |
*/ |
5915 |
public void redraw() { |
5983 |
public void redraw() { |
5916 |
int itemCount; |
5984 |
int itemCount; |
5917 |
|
5985 |
|
5918 |
super.redraw(); |
5986 |
super.redraw(); |
5919 |
itemCount = getPartialBottomIndex() - topIndex + 1; |
5987 |
itemCount = getPartialBottomIndex() - topIndex + 1; |
5920 |
lineCache.redrawReset(topIndex, itemCount, true); |
5988 |
lineCache.redrawReset(topIndex, itemCount, true); |
5921 |
lineCache.calculate(topIndex, itemCount); |
5989 |
lineCache.calculate(topIndex, itemCount); |
5922 |
setHorizontalScrollBar(); |
5990 |
setHorizontalScrollBar(); |
5923 |
} |
5991 |
} |
5924 |
/** |
5992 |
/** |
5925 |
* Causes the rectangular area of the receiver specified by |
5993 |
* Causes the rectangular area of the receiver specified by |
5926 |
* the arguments to be marked as needing to be redrawn. |
5994 |
* the arguments to be marked as needing to be redrawn. |
5927 |
* The next time a paint request is processed, that area of |
5995 |
* The next time a paint request is processed, that area of |
5928 |
* the receiver will be painted. If the <code>all</code> flag |
5996 |
* the receiver will be painted. If the <code>all</code> flag |
5929 |
* is <code>true</code>, any children of the receiver which |
5997 |
* is <code>true</code>, any children of the receiver which |
5930 |
* intersect with the specified area will also paint their |
5998 |
* intersect with the specified area will also paint their |
5931 |
* intersecting areas. If the <code>all</code> flag is |
5999 |
* intersecting areas. If the <code>all</code> flag is |
5932 |
* <code>false</code>, the children will not be painted. |
6000 |
* <code>false</code>, the children will not be painted. |
5933 |
* <p> |
6001 |
* <p> |
5934 |
* Marks the content width of all lines in the specified rectangle |
6002 |
* Marks the content width of all lines in the specified rectangle |
5935 |
* as unknown. Recalculates the content width of all visible lines. |
6003 |
* as unknown. Recalculates the content width of all visible lines. |
5936 |
* When a <code>LineStyleListener</code> is used a redraw call |
6004 |
* When a <code>LineStyleListener</code> is used a redraw call |
5937 |
* is the only notification to the widget that styles have changed |
6005 |
* is the only notification to the widget that styles have changed |
5938 |
* and that the content width may have changed. |
6006 |
* and that the content width may have changed. |
5939 |
* </p> |
6007 |
* </p> |
5940 |
* |
6008 |
* |
Lines 5952-5975
Link Here
|
5952 |
* @see Control#update |
6020 |
* @see Control#update |
5953 |
*/ |
6021 |
*/ |
5954 |
public void redraw(int x, int y, int width, int height, boolean all) { |
6022 |
public void redraw(int x, int y, int width, int height, boolean all) { |
5955 |
super.redraw(x, y, width, height, all); |
6023 |
super.redraw(x, y, width, height, all); |
5956 |
if (height > 0) { |
6024 |
if (height > 0) { |
5957 |
int lineCount = content.getLineCount(); |
6025 |
int lineCount = content.getLineCount(); |
5958 |
int startLine = (getTopPixel() + y) / lineHeight; |
6026 |
int startLine = (getTopPixel() + y) / lineHeight; |
5959 |
int endLine = startLine + Compatibility.ceil(height, lineHeight); |
6027 |
int endLine = startLine + Compatibility.ceil(height, lineHeight); |
5960 |
int itemCount; |
6028 |
int itemCount; |
5961 |
|
6029 |
|
5962 |
// reset all lines in the redraw rectangle |
6030 |
// reset all lines in the redraw rectangle |
5963 |
startLine = Math.min(startLine, lineCount); |
6031 |
startLine = Math.min(startLine, lineCount); |
5964 |
itemCount = Math.min(endLine, lineCount) - startLine; |
6032 |
itemCount = Math.min(endLine, lineCount) - startLine; |
5965 |
lineCache.reset(startLine, itemCount, true); |
6033 |
lineCache.reset(startLine, itemCount, true); |
5966 |
// only calculate the visible lines |
6034 |
// only calculate the visible lines |
5967 |
itemCount = getPartialBottomIndex() - topIndex + 1; |
6035 |
itemCount = getPartialBottomIndex() - topIndex + 1; |
5968 |
lineCache.calculate(topIndex, itemCount); |
6036 |
lineCache.calculate(topIndex, itemCount); |
5969 |
setHorizontalScrollBar(); |
6037 |
setHorizontalScrollBar(); |
5970 |
} |
6038 |
} |
5971 |
} |
6039 |
} |
5972 |
/** |
6040 |
/** |
5973 |
* Redraws a text range in the specified lines |
6041 |
* Redraws a text range in the specified lines |
5974 |
* <p> |
6042 |
* <p> |
5975 |
* |
6043 |
* |
Lines 5982-6034
Link Here
|
5982 |
* without invalidating the redraw range. |
6050 |
* without invalidating the redraw range. |
5983 |
*/ |
6051 |
*/ |
5984 |
void redrawBidiLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) { |
6052 |
void redrawBidiLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) { |
5985 |
int lineCount = lastLine - firstLine + 1; |
6053 |
int lineCount = lastLine - firstLine + 1; |
5986 |
int redrawY = firstLine * lineHeight - verticalScrollOffset; |
6054 |
int redrawY = firstLine * lineHeight - verticalScrollOffset; |
5987 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
6055 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
5988 |
String line = content.getLine(firstLine); |
6056 |
String line = content.getLine(firstLine); |
5989 |
GC gc = getGC(); |
6057 |
GC gc = getGC(); |
5990 |
StyledTextBidi bidi = getStyledTextBidi(line, firstLineOffset, gc); |
6058 |
StyledTextBidi bidi = getStyledTextBidi(line, firstLineOffset, gc); |
5991 |
|
6059 |
|
5992 |
bidi.redrawRange( |
6060 |
bidi.redrawRange( |
5993 |
this, offsetInFirstLine, |
6061 |
this, offsetInFirstLine, |
5994 |
Math.min(line.length(), endOffset) - offsetInFirstLine, |
6062 |
Math.min(line.length(), endOffset) - offsetInFirstLine, |
5995 |
leftMargin - horizontalScrollOffset, redrawY + topMargin, lineHeight); |
6063 |
leftMargin - horizontalScrollOffset, redrawY + topMargin, lineHeight); |
5996 |
// redraw line break marker (either space or full client area width) |
6064 |
// redraw line break marker (either space or full client area width) |
5997 |
// if redraw range extends over more than one line and background should be redrawn |
6065 |
// if redraw range extends over more than one line and background should be redrawn |
5998 |
if (lastLine > firstLine && clearBackground) { |
6066 |
if (lastLine > firstLine && clearBackground) { |
5999 |
int lineBreakWidth; |
6067 |
int lineBreakWidth; |
6000 |
int lineBreakStartX = bidi.getTextWidth(); |
6068 |
int lineBreakStartX = bidi.getTextWidth(); |
6001 |
// handle empty line case |
6069 |
// handle empty line case |
6002 |
if (lineBreakStartX == leftMargin) { |
6070 |
if (lineBreakStartX == leftMargin) { |
6003 |
lineBreakStartX += XINSET; |
6071 |
lineBreakStartX += XINSET; |
6004 |
} |
6072 |
} |
6005 |
lineBreakStartX = lineBreakStartX - horizontalScrollOffset; |
6073 |
lineBreakStartX = lineBreakStartX - horizontalScrollOffset; |
6006 |
if ((getStyle() & SWT.FULL_SELECTION) != 0) { |
6074 |
if ((getStyle() & SWT.FULL_SELECTION) != 0) { |
6007 |
lineBreakWidth = getClientArea().width - lineBreakStartX; |
6075 |
lineBreakWidth = getClientArea().width - lineBreakStartX; |
6008 |
} |
6076 |
} |
6009 |
else { |
6077 |
else { |
6010 |
lineBreakWidth = lineEndSpaceWidth; |
6078 |
lineBreakWidth = lineEndSpaceWidth; |
6011 |
} |
6079 |
} |
6012 |
draw(lineBreakStartX, redrawY, lineBreakWidth, lineHeight, clearBackground); |
6080 |
draw(lineBreakStartX, redrawY, lineBreakWidth, lineHeight, clearBackground); |
6013 |
} |
6081 |
} |
6014 |
// redraw last line if more than one line needs redrawing |
6082 |
// redraw last line if more than one line needs redrawing |
6015 |
if (lineCount > 1) { |
6083 |
if (lineCount > 1) { |
6016 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
6084 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
6017 |
int offsetInLastLine = endOffset - lastLineOffset; |
6085 |
int offsetInLastLine = endOffset - lastLineOffset; |
6018 |
// no redraw necessary if redraw offset is 0 |
6086 |
// no redraw necessary if redraw offset is 0 |
6019 |
if (offsetInLastLine > 0) { |
6087 |
if (offsetInLastLine > 0) { |
6020 |
line = content.getLine(lastLine); |
6088 |
line = content.getLine(lastLine); |
6021 |
redrawY = lastLine * lineHeight - verticalScrollOffset; |
6089 |
redrawY = lastLine * lineHeight - verticalScrollOffset; |
6022 |
bidi = getStyledTextBidi(line, lastLineOffset, gc); |
6090 |
bidi = getStyledTextBidi(line, lastLineOffset, gc); |
6023 |
bidi.redrawRange( |
6091 |
bidi.redrawRange( |
6024 |
this, 0, offsetInLastLine, |
6092 |
this, 0, offsetInLastLine, |
6025 |
leftMargin - horizontalScrollOffset, |
6093 |
leftMargin - horizontalScrollOffset, |
6026 |
redrawY + topMargin, lineHeight); |
6094 |
redrawY + topMargin, lineHeight); |
6027 |
} |
6095 |
} |
6028 |
} |
6096 |
} |
6029 |
gc.dispose(); |
6097 |
gc.dispose(); |
6030 |
} |
6098 |
} |
6031 |
/** |
6099 |
/** |
6032 |
* Redraw the given line. |
6100 |
* Redraw the given line. |
6033 |
* <p> |
6101 |
* <p> |
6034 |
* |
6102 |
* |
Lines 6036-6052
Link Here
|
6036 |
* @param offset offset in line to start redrawing |
6104 |
* @param offset offset in line to start redrawing |
6037 |
*/ |
6105 |
*/ |
6038 |
void redrawLine(int line, int offset) { |
6106 |
void redrawLine(int line, int offset) { |
6039 |
int redrawX = 0; |
6107 |
int redrawX = 0; |
6040 |
if (offset > 0) { |
6108 |
if (offset > 0) { |
6041 |
String lineText = content.getLine(line); |
6109 |
String lineText = content.getLine(line); |
6042 |
redrawX = getXAtOffset(lineText, line, offset); |
6110 |
redrawX = getXAtOffset(lineText, line, offset); |
6043 |
} |
6111 |
} |
6044 |
int redrawY = line * lineHeight - verticalScrollOffset; |
6112 |
int redrawY = line * lineHeight - verticalScrollOffset; |
6045 |
super.redraw( |
6113 |
super.redraw( |
6046 |
redrawX + leftMargin, redrawY + topMargin, |
6114 |
redrawX + leftMargin, redrawY + topMargin, |
6047 |
getClientArea().width, lineHeight, true); |
6115 |
getClientArea().width, lineHeight, true); |
6048 |
} |
6116 |
} |
6049 |
/** |
6117 |
/** |
6050 |
* Redraws a text range in the specified lines |
6118 |
* Redraws a text range in the specified lines |
6051 |
* <p> |
6119 |
* <p> |
6052 |
* |
6120 |
* |
Lines 6055-6109
Link Here
|
6055 |
* @param lastLine last line to redraw |
6123 |
* @param lastLine last line to redraw |
6056 |
* @param endOffset offset in the last where redrawing should stop |
6124 |
* @param endOffset offset in the last where redrawing should stop |
6057 |
* @param clearBackground true=clear the background by invalidating |
6125 |
* @param clearBackground true=clear the background by invalidating |
6058 |
* the requested redraw range. If the redraw range includes the |
6126 |
* the requested redraw range. If the redraw range includes the |
6059 |
* last character of a line (i.e., the entire line is redrawn) the |
6127 |
* last character of a line (i.e., the entire line is redrawn) the |
6060 |
* line is cleared all the way to the right border of the widget. |
6128 |
* line is cleared all the way to the right border of the widget. |
6061 |
* false=draw the foreground directly without invalidating the |
6129 |
* false=draw the foreground directly without invalidating the |
6062 |
* redraw range. |
6130 |
* redraw range. |
6063 |
*/ |
6131 |
*/ |
6064 |
void redrawLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) { |
6132 |
void redrawLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) { |
6065 |
String line = content.getLine(firstLine); |
6133 |
String line = content.getLine(firstLine); |
6066 |
int lineCount = lastLine - firstLine + 1; |
6134 |
int lineCount = lastLine - firstLine + 1; |
6067 |
int redrawX = getXAtOffset(line, firstLine, offsetInFirstLine) - leftMargin; |
6135 |
int redrawX = getXAtOffset(line, firstLine, offsetInFirstLine) - leftMargin; |
6068 |
int redrawStopX; |
6136 |
int redrawStopX; |
6069 |
int redrawY = firstLine * lineHeight - verticalScrollOffset; |
6137 |
int redrawY = firstLine * lineHeight - verticalScrollOffset; |
6070 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
6138 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
6071 |
boolean fullLineRedraw = ((getStyle() & SWT.FULL_SELECTION) != 0 && lastLine > firstLine); |
6139 |
boolean fullLineRedraw = ((getStyle() & SWT.FULL_SELECTION) != 0 && lastLine > firstLine); |
6072 |
|
6140 |
|
6073 |
// if redraw range includes last character on the first line, |
6141 |
// if redraw range includes last character on the first line, |
6074 |
// clear background to right widget border. fixes bug 19595. |
6142 |
// clear background to right widget border. fixes bug 19595. |
6075 |
if (clearBackground && endOffset - firstLineOffset >= line.length()) { |
6143 |
if (clearBackground && endOffset - firstLineOffset >= line.length()) { |
6076 |
fullLineRedraw = true; |
6144 |
fullLineRedraw = true; |
6077 |
} |
6145 |
} |
6078 |
// calculate redraw stop location |
6146 |
// calculate redraw stop location |
6079 |
if (fullLineRedraw) { |
6147 |
if (fullLineRedraw) { |
6080 |
redrawStopX = getClientArea().width - leftMargin; |
6148 |
redrawStopX = getClientArea().width - leftMargin; |
6081 |
} |
6149 |
} |
6082 |
else { |
6150 |
else { |
6083 |
redrawStopX = getXAtOffset(line, firstLine, endOffset - firstLineOffset) - leftMargin; |
6151 |
redrawStopX = getXAtOffset(line, firstLine, endOffset - firstLineOffset) - leftMargin; |
6084 |
} |
6152 |
} |
6085 |
draw(redrawX, redrawY, redrawStopX - redrawX, lineHeight, clearBackground); |
6153 |
draw(redrawX, redrawY, redrawStopX - redrawX, lineHeight, clearBackground); |
6086 |
// redraw last line if more than one line needs redrawing |
6154 |
// redraw last line if more than one line needs redrawing |
6087 |
if (lineCount > 1) { |
6155 |
if (lineCount > 1) { |
6088 |
int offsetInLastLine = endOffset - content.getOffsetAtLine(lastLine); |
6156 |
int offsetInLastLine = endOffset - content.getOffsetAtLine(lastLine); |
6089 |
// no redraw necessary if redraw offset is 0 |
6157 |
// no redraw necessary if redraw offset is 0 |
6090 |
if (offsetInLastLine > 0) { |
6158 |
if (offsetInLastLine > 0) { |
6091 |
line = content.getLine(lastLine); |
6159 |
line = content.getLine(lastLine); |
6092 |
// if redraw range includes last character on the last line, |
6160 |
// if redraw range includes last character on the last line, |
6093 |
// clear background to right widget border. fixes bug 19595. |
6161 |
// clear background to right widget border. fixes bug 19595. |
6094 |
if (clearBackground && offsetInLastLine >= line.length()) { |
6162 |
if (clearBackground && offsetInLastLine >= line.length()) { |
6095 |
fullLineRedraw = true; |
6163 |
fullLineRedraw = true; |
6096 |
} |
6164 |
} |
6097 |
if (fullLineRedraw) { |
6165 |
if (fullLineRedraw) { |
6098 |
redrawStopX = getClientArea().width - leftMargin; |
6166 |
redrawStopX = getClientArea().width - leftMargin; |
6099 |
} |
6167 |
} |
6100 |
else { |
6168 |
else { |
6101 |
redrawStopX = getXAtOffset(line, lastLine, offsetInLastLine) - leftMargin; |
6169 |
redrawStopX = getXAtOffset(line, lastLine, offsetInLastLine) - leftMargin; |
6102 |
} |
6170 |
} |
6103 |
redrawY = lastLine * lineHeight - verticalScrollOffset; |
6171 |
redrawY = lastLine * lineHeight - verticalScrollOffset; |
6104 |
draw(0, redrawY, redrawStopX, lineHeight, clearBackground); |
6172 |
draw(0, redrawY, redrawStopX, lineHeight, clearBackground); |
6105 |
} |
6173 |
} |
6106 |
} |
6174 |
} |
6107 |
} |
6175 |
} |
6108 |
/** |
6176 |
/** |
6109 |
* Fixes the widget to display a text change. |
6177 |
* Fixes the widget to display a text change. |
Lines 6115-6164
Link Here
|
6115 |
* @param replacedLineCount number of replaced lines. |
6183 |
* @param replacedLineCount number of replaced lines. |
6116 |
*/ |
6184 |
*/ |
6117 |
void redrawMultiLineChange(int y, int newLineCount, int replacedLineCount) { |
6185 |
void redrawMultiLineChange(int y, int newLineCount, int replacedLineCount) { |
6118 |
Rectangle clientArea = getClientArea(); |
6186 |
Rectangle clientArea = getClientArea(); |
6119 |
int lineCount = newLineCount - replacedLineCount; |
6187 |
int lineCount = newLineCount - replacedLineCount; |
6120 |
int sourceY; |
6188 |
int sourceY; |
6121 |
int destinationY; |
6189 |
int destinationY; |
6122 |
|
6190 |
|
6123 |
if (lineCount > 0) { |
6191 |
if (lineCount > 0) { |
6124 |
sourceY = Math.max(0, y + lineHeight); |
6192 |
sourceY = Math.max(0, y + lineHeight); |
6125 |
destinationY = sourceY + lineCount * lineHeight; |
6193 |
destinationY = sourceY + lineCount * lineHeight; |
6126 |
} |
6194 |
} |
6127 |
else { |
6195 |
else { |
6128 |
destinationY = Math.max(0, y + lineHeight); |
6196 |
destinationY = Math.max(0, y + lineHeight); |
6129 |
sourceY = destinationY - lineCount * lineHeight; |
6197 |
sourceY = destinationY - lineCount * lineHeight; |
6130 |
} |
6198 |
} |
6131 |
scroll( |
6199 |
scroll( |
6132 |
0, destinationY, // destination x, y |
6200 |
0, destinationY, // destination x, y |
6133 |
0, sourceY, // source x, y |
6201 |
0, sourceY, // source x, y |
6134 |
clientArea.width, clientArea.height, true); |
6202 |
clientArea.width, clientArea.height, true); |
6135 |
// Always redrawing causes the bottom line to flash when a line is |
6203 |
// Always redrawing causes the bottom line to flash when a line is |
6136 |
// deleted. This is because SWT merges the paint area of the scroll |
6204 |
// deleted. This is because SWT merges the paint area of the scroll |
6137 |
// with the paint area of the redraw call below. |
6205 |
// with the paint area of the redraw call below. |
6138 |
// To prevent this we could call update after the scroll. However, |
6206 |
// To prevent this we could call update after the scroll. However, |
6139 |
// adding update can cause even more flash if the client does other |
6207 |
// adding update can cause even more flash if the client does other |
6140 |
// redraw/update calls (ie. for syntax highlighting). |
6208 |
// redraw/update calls (ie. for syntax highlighting). |
6141 |
// We could also redraw only when a line has been added or when |
6209 |
// We could also redraw only when a line has been added or when |
6142 |
// contents has been added to a line. This would require getting |
6210 |
// contents has been added to a line. This would require getting |
6143 |
// line index info from the content and is not worth the trouble |
6211 |
// line index info from the content and is not worth the trouble |
6144 |
// (the flash is only on the bottom line and minor). |
6212 |
// (the flash is only on the bottom line and minor). |
6145 |
// Specifying the NO_MERGE_PAINTS style bit prevents the merged |
6213 |
// Specifying the NO_MERGE_PAINTS style bit prevents the merged |
6146 |
// redraw but could cause flash/slowness elsewhere. |
6214 |
// redraw but could cause flash/slowness elsewhere. |
6147 |
if (y + lineHeight > 0 && y <= clientArea.height) { |
6215 |
if (y + lineHeight > 0 && y <= clientArea.height) { |
6148 |
// redraw first changed line in case a line was split/joined |
6216 |
// redraw first changed line in case a line was split/joined |
6149 |
super.redraw(0, y, clientArea.width, lineHeight, true); |
6217 |
super.redraw(0, y, clientArea.width, lineHeight, true); |
6150 |
} |
6218 |
} |
6151 |
if (newLineCount > 0) { |
6219 |
if (newLineCount > 0) { |
6152 |
int redrawStartY = y + lineHeight; |
6220 |
int redrawStartY = y + lineHeight; |
6153 |
int redrawHeight = newLineCount * lineHeight; |
6221 |
int redrawHeight = newLineCount * lineHeight; |
6154 |
|
6222 |
|
6155 |
if (redrawStartY + redrawHeight > 0 && redrawStartY <= clientArea.height) { |
6223 |
if (redrawStartY + redrawHeight > 0 && redrawStartY <= clientArea.height) { |
6156 |
// display new text |
6224 |
// display new text |
6157 |
super.redraw(0, redrawStartY, clientArea.width, redrawHeight, true); |
6225 |
super.redraw(0, redrawStartY, clientArea.width, redrawHeight, true); |
6158 |
} |
6226 |
} |
6159 |
} |
6227 |
} |
6160 |
} |
6228 |
} |
6161 |
/** |
6229 |
/** |
6162 |
* Redraws the specified text range. |
6230 |
* Redraws the specified text range. |
6163 |
* <p> |
6231 |
* <p> |
6164 |
* |
6232 |
* |
Lines 6167-6204
Link Here
|
6167 |
* @param clearBackground true if the background should be cleared as |
6235 |
* @param clearBackground true if the background should be cleared as |
6168 |
* part of the redraw operation. If true, the entire redraw range will |
6236 |
* part of the redraw operation. If true, the entire redraw range will |
6169 |
* be cleared before anything is redrawn. If the redraw range includes |
6237 |
* be cleared before anything is redrawn. If the redraw range includes |
6170 |
* the last character of a line (i.e., the entire line is redrawn) the |
6238 |
* the last character of a line (i.e., the entire line is redrawn) the |
6171 |
* line is cleared all the way to the right border of the widget. |
6239 |
* line is cleared all the way to the right border of the widget. |
6172 |
* The redraw operation will be faster and smoother if clearBackground |
6240 |
* The redraw operation will be faster and smoother if clearBackground |
6173 |
* is set to false. Whether or not the flag can be set to false depends |
6241 |
* is set to false. Whether or not the flag can be set to false depends |
6174 |
* on the type of change that has taken place. If font styles or |
6242 |
* on the type of change that has taken place. If font styles or |
6175 |
* background colors for the redraw range have changed, clearBackground |
6243 |
* background colors for the redraw range have changed, clearBackground |
6176 |
* should be set to true. If only foreground colors have changed for |
6244 |
* should be set to true. If only foreground colors have changed for |
6177 |
* the redraw range, clearBackground can be set to false. |
6245 |
* the redraw range, clearBackground can be set to false. |
6178 |
* @exception SWTException <ul> |
6246 |
* @exception SWTException <ul> |
6179 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6247 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
6180 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6248 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6181 |
* </ul> |
6249 |
* </ul> |
6182 |
* @exception IllegalArgumentException <ul> |
6250 |
* @exception IllegalArgumentException <ul> |
6183 |
* <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
6251 |
* <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> |
6184 |
* </ul> |
6252 |
* </ul> |
6185 |
*/ |
6253 |
*/ |
6186 |
public void redrawRange(int start, int length, boolean clearBackground) { |
6254 |
public void redrawRange(int start, int length, boolean clearBackground) { |
6187 |
checkWidget(); |
6255 |
checkWidget(); |
6188 |
int end = start + length; |
6256 |
int end = start + length; |
6189 |
int contentLength = content.getCharCount(); |
6257 |
int contentLength = content.getCharCount(); |
6190 |
int firstLine; |
6258 |
int firstLine; |
6191 |
int lastLine; |
6259 |
int lastLine; |
6192 |
|
6260 |
|
6193 |
if (start > end || start < 0 || end > contentLength) { |
6261 |
if (start > end || start < 0 || end > contentLength) { |
6194 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6262 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6195 |
} |
6263 |
} |
6196 |
firstLine = content.getLineAtOffset(start); |
6264 |
firstLine = content.getLineAtOffset(start); |
6197 |
lastLine = content.getLineAtOffset(end); |
6265 |
lastLine = content.getLineAtOffset(end); |
6198 |
// reset all affected lines but let the redraw recalculate only |
6266 |
// reset all affected lines but let the redraw recalculate only |
6199 |
// those that are visible. |
6267 |
// those that are visible. |
6200 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6268 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6201 |
internalRedrawRange(start, length, clearBackground); |
6269 |
internalRedrawRange(start, length, clearBackground); |
6202 |
} |
6270 |
} |
6203 |
/** |
6271 |
/** |
6204 |
* Removes the specified bidirectional segment listener. |
6272 |
* Removes the specified bidirectional segment listener. |
Lines 6215-6223
Link Here
|
6215 |
* @since 2.0 |
6283 |
* @since 2.0 |
6216 |
*/ |
6284 |
*/ |
6217 |
public void removeBidiSegmentListener(BidiSegmentListener listener) { |
6285 |
public void removeBidiSegmentListener(BidiSegmentListener listener) { |
6218 |
checkWidget(); |
6286 |
checkWidget(); |
6219 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6287 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6220 |
removeListener(LineGetSegments, listener); |
6288 |
removeListener(LineGetSegments, listener); |
6221 |
} |
6289 |
} |
6222 |
/** |
6290 |
/** |
6223 |
* Removes the specified extended modify listener. |
6291 |
* Removes the specified extended modify listener. |
Lines 6233-6241
Link Here
|
6233 |
* </ul> |
6301 |
* </ul> |
6234 |
*/ |
6302 |
*/ |
6235 |
public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { |
6303 |
public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { |
6236 |
checkWidget(); |
6304 |
checkWidget(); |
6237 |
if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6305 |
if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6238 |
removeListener(ExtendedModify, extendedModifyListener); |
6306 |
removeListener(ExtendedModify, extendedModifyListener); |
6239 |
} |
6307 |
} |
6240 |
/** |
6308 |
/** |
6241 |
* Removes the specified line background listener. |
6309 |
* Removes the specified line background listener. |
Lines 6251-6265
Link Here
|
6251 |
* </ul> |
6319 |
* </ul> |
6252 |
*/ |
6320 |
*/ |
6253 |
public void removeLineBackgroundListener(LineBackgroundListener listener) { |
6321 |
public void removeLineBackgroundListener(LineBackgroundListener listener) { |
6254 |
checkWidget(); |
6322 |
checkWidget(); |
6255 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6323 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6256 |
removeListener(LineGetBackground, listener); |
6324 |
removeListener(LineGetBackground, listener); |
6257 |
// use default line styler if last user line styler was removed. |
6325 |
// use default line styler if last user line styler was removed. |
6258 |
if (isListening(LineGetBackground) == false && userLineBackground) { |
6326 |
if (isListening(LineGetBackground) == false && userLineBackground) { |
6259 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
6327 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
6260 |
addListener(LineGetBackground, typedListener); |
6328 |
addListener(LineGetBackground, typedListener); |
6261 |
userLineBackground = false; |
6329 |
userLineBackground = false; |
6262 |
} |
6330 |
} |
6263 |
} |
6331 |
} |
6264 |
/** |
6332 |
/** |
6265 |
* Removes the specified line style listener. |
6333 |
* Removes the specified line style listener. |
Lines 6275-6291
Link Here
|
6275 |
* </ul> |
6343 |
* </ul> |
6276 |
*/ |
6344 |
*/ |
6277 |
public void removeLineStyleListener(LineStyleListener listener) { |
6345 |
public void removeLineStyleListener(LineStyleListener listener) { |
6278 |
checkWidget(); |
6346 |
checkWidget(); |
6279 |
if (listener == null) { |
6347 |
if (listener == null) { |
6280 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6348 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6281 |
} |
6349 |
} |
6282 |
removeListener(LineGetStyle, listener); |
6350 |
removeListener(LineGetStyle, listener); |
6283 |
// use default line styler if last user line styler was removed. Fixes 1G7B1X2 |
6351 |
// use default line styler if last user line styler was removed. Fixes 1G7B1X2 |
6284 |
if (isListening(LineGetStyle) == false && userLineStyle) { |
6352 |
if (isListening(LineGetStyle) == false && userLineStyle) { |
6285 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
6353 |
StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); |
6286 |
addListener(LineGetStyle, typedListener); |
6354 |
addListener(LineGetStyle, typedListener); |
6287 |
userLineStyle = false; |
6355 |
userLineStyle = false; |
6288 |
} |
6356 |
} |
6289 |
} |
6357 |
} |
6290 |
/** |
6358 |
/** |
6291 |
* Removes the specified modify listener. |
6359 |
* Removes the specified modify listener. |
Lines 6301-6311
Link Here
|
6301 |
* </ul> |
6369 |
* </ul> |
6302 |
*/ |
6370 |
*/ |
6303 |
public void removeModifyListener(ModifyListener modifyListener) { |
6371 |
public void removeModifyListener(ModifyListener modifyListener) { |
6304 |
checkWidget(); |
6372 |
checkWidget(); |
6305 |
if (modifyListener == null) { |
6373 |
if (modifyListener == null) { |
6306 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6374 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6307 |
} |
6375 |
} |
6308 |
removeListener(SWT.Modify, modifyListener); |
6376 |
removeListener(SWT.Modify, modifyListener); |
6309 |
} |
6377 |
} |
6310 |
/** |
6378 |
/** |
6311 |
* Removes the specified selection listener. |
6379 |
* Removes the specified selection listener. |
Lines 6321-6331
Link Here
|
6321 |
* </ul> |
6389 |
* </ul> |
6322 |
*/ |
6390 |
*/ |
6323 |
public void removeSelectionListener(SelectionListener listener) { |
6391 |
public void removeSelectionListener(SelectionListener listener) { |
6324 |
checkWidget(); |
6392 |
checkWidget(); |
6325 |
if (listener == null) { |
6393 |
if (listener == null) { |
6326 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6394 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6327 |
} |
6395 |
} |
6328 |
removeListener(SWT.Selection, listener); |
6396 |
removeListener(SWT.Selection, listener); |
6329 |
} |
6397 |
} |
6330 |
/** |
6398 |
/** |
6331 |
* Removes the specified verify listener. |
6399 |
* Removes the specified verify listener. |
Lines 6341-6351
Link Here
|
6341 |
* </ul> |
6409 |
* </ul> |
6342 |
*/ |
6410 |
*/ |
6343 |
public void removeVerifyListener(VerifyListener verifyListener) { |
6411 |
public void removeVerifyListener(VerifyListener verifyListener) { |
6344 |
checkWidget(); |
6412 |
checkWidget(); |
6345 |
if (verifyListener == null) { |
6413 |
if (verifyListener == null) { |
6346 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6414 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6347 |
} |
6415 |
} |
6348 |
removeListener(SWT.Verify, verifyListener); |
6416 |
removeListener(SWT.Verify, verifyListener); |
6349 |
} |
6417 |
} |
6350 |
/** |
6418 |
/** |
6351 |
* Removes the specified key verify listener. |
6419 |
* Removes the specified key verify listener. |
Lines 6361-6382
Link Here
|
6361 |
* </ul> |
6429 |
* </ul> |
6362 |
*/ |
6430 |
*/ |
6363 |
public void removeVerifyKeyListener(VerifyKeyListener listener) { |
6431 |
public void removeVerifyKeyListener(VerifyKeyListener listener) { |
6364 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6432 |
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6365 |
removeListener(VerifyKey, listener); |
6433 |
removeListener(VerifyKey, listener); |
6366 |
} |
6434 |
} |
6367 |
/** |
6435 |
/** |
6368 |
* Replaces the styles in the given range with new styles. This method |
6436 |
* Replaces the styles in the given range with new styles. This method |
6369 |
* effectively deletes the styles in the given range and then adds the |
6437 |
* effectively deletes the styles in the given range and then adds the |
6370 |
* the new styles. |
6438 |
* the new styles. |
6371 |
* <p> |
6439 |
* <p> |
6372 |
* Should not be called if a LineStyleListener has been set since the |
6440 |
* Should not be called if a LineStyleListener has been set since the |
6373 |
* listener maintains the styles. |
6441 |
* listener maintains the styles. |
6374 |
* </p> |
6442 |
* </p> |
6375 |
* |
6443 |
* |
6376 |
* @param start offset of first character where styles will be deleted |
6444 |
* @param start offset of first character where styles will be deleted |
6377 |
* @param length length of the range to delete styles in |
6445 |
* @param length length of the range to delete styles in |
6378 |
* @param ranges StyleRange objects containing the new style information. |
6446 |
* @param ranges StyleRange objects containing the new style information. |
6379 |
* The ranges should not overlap and should be within the specified start |
6447 |
* The ranges should not overlap and should be within the specified start |
6380 |
* and length. The style rendering is undefined if the ranges do overlap |
6448 |
* and length. The style rendering is undefined if the ranges do overlap |
6381 |
* or are ill-defined. Must not be null. |
6449 |
* or are ill-defined. Must not be null. |
6382 |
* @exception SWTException <ul> |
6450 |
* @exception SWTException <ul> |
Lines 6384-6476
Link Here
|
6384 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6452 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6385 |
* </ul> |
6453 |
* </ul> |
6386 |
* @exception IllegalArgumentException <ul> |
6454 |
* @exception IllegalArgumentException <ul> |
6387 |
* <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6455 |
* <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6388 |
* <li>ERROR_NULL_ARGUMENT when string is null</li> |
6456 |
* <li>ERROR_NULL_ARGUMENT when string is null</li> |
6389 |
* </ul> |
6457 |
* </ul> |
6390 |
* @since 2.0 |
6458 |
* @since 2.0 |
6391 |
*/ |
6459 |
*/ |
6392 |
public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { |
6460 |
public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { |
6393 |
checkWidget(); |
6461 |
checkWidget(); |
6394 |
if (userLineStyle) { |
6462 |
if (userLineStyle) { |
6395 |
return; |
6463 |
return; |
6396 |
} |
6464 |
} |
6397 |
if (ranges == null) { |
6465 |
if (ranges == null) { |
6398 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6466 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6399 |
} |
6467 |
} |
6400 |
if (ranges.length == 0) { |
6468 |
if (ranges.length == 0) { |
6401 |
setStyleRange(new StyleRange(start, length, null, null)); |
6469 |
setStyleRange(new StyleRange(start, length, null, null)); |
6402 |
return; |
6470 |
return; |
6403 |
} |
6471 |
} |
6404 |
int end = start + length; |
6472 |
int end = start + length; |
6405 |
if (start > end || start < 0 || end > getCharCount()) { |
6473 |
if (start > end || start < 0 || end > getCharCount()) { |
6406 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6474 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6407 |
} |
6475 |
} |
6408 |
|
6476 |
|
6409 |
int firstLine = content.getLineAtOffset(start); |
6477 |
int firstLine = content.getLineAtOffset(start); |
6410 |
int lastLine = content.getLineAtOffset(end); |
6478 |
int lastLine = content.getLineAtOffset(end); |
6411 |
|
6479 |
|
6412 |
// if the area is not visible, there is no need to redraw |
6480 |
// if the area is not visible, there is no need to redraw |
6413 |
boolean redrawLines = isAreaVisible(firstLine, lastLine); |
6481 |
boolean redrawLines = isAreaVisible(firstLine, lastLine); |
6414 |
|
6482 |
|
6415 |
if (!redrawLines) { |
6483 |
if (!redrawLines) { |
6416 |
defaultLineStyler.replaceStyleRanges(start, length, ranges); |
6484 |
defaultLineStyler.replaceStyleRanges(start, length, ranges); |
6417 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6485 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6418 |
} else { |
6486 |
} else { |
6419 |
boolean redrawFirstLine = false; |
6487 |
boolean redrawFirstLine = false; |
6420 |
boolean redrawLastLine = false; |
6488 |
boolean redrawLastLine = false; |
6421 |
// the first and last line needs to be redrawn completely if the |
6489 |
// the first and last line needs to be redrawn completely if the |
6422 |
// font style is changing from SWT.NORMAL to something else or |
6490 |
// font style is changing from SWT.NORMAL to something else or |
6423 |
// vice versa. fixes 1G7M5WE. |
6491 |
// vice versa. fixes 1G7M5WE. |
6424 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
6492 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
6425 |
if (isBidi()) { |
6493 |
if (isBidi()) { |
6426 |
redrawFirstLine = true; |
6494 |
redrawFirstLine = true; |
6427 |
redrawLastLine = true; |
6495 |
redrawLastLine = true; |
6428 |
} else { |
6496 |
} else { |
6429 |
int firstLineEnd = firstLineOffset + content.getLine(firstLine).length(); |
6497 |
int firstLineEnd = firstLineOffset + content.getLine(firstLine).length(); |
6430 |
redrawFirstLine = isRedrawFirstLine(ranges, firstLine, firstLineOffset); |
6498 |
redrawFirstLine = isRedrawFirstLine(ranges, firstLine, firstLineOffset); |
6431 |
// check if any bold styles will be cleared |
6499 |
// check if any bold styles will be cleared |
6432 |
StyleRange clearRange = new StyleRange(firstLineOffset, firstLineEnd - firstLineOffset, null, null); |
6500 |
StyleRange clearRange = new StyleRange(firstLineOffset, firstLineEnd - firstLineOffset, null, null); |
6433 |
redrawFirstLine = redrawFirstLine || isRedrawFirstLine(new StyleRange[] {clearRange}, firstLine, firstLineOffset); |
6501 |
redrawFirstLine = redrawFirstLine || isRedrawFirstLine(new StyleRange[] {clearRange}, firstLine, firstLineOffset); |
6434 |
if (lastLine != firstLine) { |
6502 |
if (lastLine != firstLine) { |
6435 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
6503 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
6436 |
int lastLineEnd = lastLineOffset + content.getLine(lastLine).length(); |
6504 |
int lastLineEnd = lastLineOffset + content.getLine(lastLine).length(); |
6437 |
redrawLastLine = isRedrawLastLine(ranges, lastLine, lastLineOffset); |
6505 |
redrawLastLine = isRedrawLastLine(ranges, lastLine, lastLineOffset); |
6438 |
// check if any bold styles will be cleared |
6506 |
// check if any bold styles will be cleared |
6439 |
clearRange = new StyleRange(lastLineOffset, lastLineEnd - lastLineOffset, null, null); |
6507 |
clearRange = new StyleRange(lastLineOffset, lastLineEnd - lastLineOffset, null, null); |
6440 |
redrawLastLine = redrawLastLine || isRedrawLastLine(new StyleRange[] {clearRange}, lastLine, lastLineOffset); |
6508 |
redrawLastLine = redrawLastLine || isRedrawLastLine(new StyleRange[] {clearRange}, lastLine, lastLineOffset); |
6441 |
} |
6509 |
} |
6442 |
} |
6510 |
} |
6443 |
defaultLineStyler.replaceStyleRanges(start, length, ranges); |
6511 |
defaultLineStyler.replaceStyleRanges(start, length, ranges); |
6444 |
// reset all lines affected by the style change but let the redraw |
6512 |
// reset all lines affected by the style change but let the redraw |
6445 |
// recalculate only those that are visible. |
6513 |
// recalculate only those that are visible. |
6446 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6514 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
6447 |
internalRedrawRange(start, length, true); |
6515 |
internalRedrawRange(start, length, true); |
6448 |
if (redrawFirstLine) { |
6516 |
if (redrawFirstLine) { |
6449 |
redrawLine(firstLine, start - firstLineOffset); |
6517 |
redrawLine(firstLine, start - firstLineOffset); |
6450 |
} |
6518 |
} |
6451 |
if (redrawLastLine) { |
6519 |
if (redrawLastLine) { |
6452 |
redrawLine(lastLine, 0); |
6520 |
redrawLine(lastLine, 0); |
6453 |
} |
6521 |
} |
6454 |
} |
6522 |
} |
6455 |
|
6523 |
|
6456 |
// make sure that the caret is positioned correctly. |
6524 |
// make sure that the caret is positioned correctly. |
6457 |
// caret location may change if font style changes. |
6525 |
// caret location may change if font style changes. |
6458 |
// fixes 1G8FODP |
6526 |
// fixes 1G8FODP |
6459 |
setCaretLocation(); |
6527 |
setCaretLocation(); |
6460 |
} |
6528 |
} |
6461 |
/** |
6529 |
/** |
6462 |
* Replaces the given text range with new text. |
6530 |
* Replaces the given text range with new text. |
6463 |
* If the widget has the SWT.SINGLE style and "text" contains more than |
6531 |
* If the widget has the SWT.SINGLE style and "text" contains more than |
6464 |
* one line, only the first line is rendered but the text is stored |
6532 |
* one line, only the first line is rendered but the text is stored |
6465 |
* unchanged. A subsequent call to getText will return the same text |
6533 |
* unchanged. A subsequent call to getText will return the same text |
6466 |
* that was set. Note that only a single line of text should be set when |
6534 |
* that was set. Note that only a single line of text should be set when |
6467 |
* the SWT.SINGLE style is used. |
6535 |
* the SWT.SINGLE style is used. |
6468 |
* <p> |
6536 |
* <p> |
6469 |
* <b>NOTE:</b> During the replace operation the current selection is |
6537 |
* <b>NOTE:</b> During the replace operation the current selection is |
6470 |
* changed as follows: |
6538 |
* changed as follows: |
6471 |
* <ul> |
6539 |
* <ul> |
6472 |
* <li>selection before replaced text: selection unchanged |
6540 |
* <li>selection before replaced text: selection unchanged |
6473 |
* <li>selection after replaced text: adjust the selection so that same text |
6541 |
* <li>selection after replaced text: adjust the selection so that same text |
6474 |
* remains selected |
6542 |
* remains selected |
6475 |
* <li>selection intersects replaced text: selection is cleared and caret |
6543 |
* <li>selection intersects replaced text: selection is cleared and caret |
6476 |
* is placed after inserted text |
6544 |
* is placed after inserted text |
Lines 6485-6599
Link Here
|
6485 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6553 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6486 |
* </ul> |
6554 |
* </ul> |
6487 |
* @exception IllegalArgumentException <ul> |
6555 |
* @exception IllegalArgumentException <ul> |
6488 |
* <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6556 |
* <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> |
6489 |
* <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. |
6557 |
* <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. |
6490 |
* 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> |
6558 |
* 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> |
6491 |
* <li>ERROR_NULL_ARGUMENT when string is null</li> |
6559 |
* <li>ERROR_NULL_ARGUMENT when string is null</li> |
6492 |
* </ul> |
6560 |
* </ul> |
6493 |
*/ |
6561 |
*/ |
6494 |
public void replaceTextRange(int start, int length, String text) { |
6562 |
public void replaceTextRange(int start, int length, String text) { |
6495 |
checkWidget(); |
6563 |
checkWidget(); |
6496 |
int contentLength = getCharCount(); |
6564 |
int contentLength = getCharCount(); |
6497 |
int end = start + length; |
6565 |
int end = start + length; |
6498 |
Event event = new Event(); |
6566 |
Event event = new Event(); |
6499 |
|
6567 |
|
6500 |
if (start > end || start < 0 || end > contentLength) { |
6568 |
if (start > end || start < 0 || end > contentLength) { |
6501 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6569 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
6502 |
} |
6570 |
} |
6503 |
if (text == null) { |
6571 |
if (text == null) { |
6504 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6572 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
6505 |
} |
6573 |
} |
6506 |
event.start = start; |
6574 |
event.start = start; |
6507 |
event.end = end; |
6575 |
event.end = end; |
6508 |
event.text = text; |
6576 |
event.text = text; |
6509 |
modifyContent(event, false); |
6577 |
modifyContent(event, false); |
6510 |
} |
6578 |
} |
6511 |
/** |
6579 |
/** |
6512 |
* Resets the caret position, selection and scroll offsets. Recalculate |
6580 |
* Resets the caret position, selection and scroll offsets. Recalculate |
6513 |
* the content width and scroll bars. Redraw the widget. |
6581 |
* the content width and scroll bars. Redraw the widget. |
6514 |
*/ |
6582 |
*/ |
6515 |
void reset() { |
6583 |
void reset() { |
6516 |
ScrollBar verticalBar = getVerticalBar(); |
6584 |
ScrollBar verticalBar = getVerticalBar(); |
6517 |
ScrollBar horizontalBar = getHorizontalBar(); |
6585 |
ScrollBar horizontalBar = getHorizontalBar(); |
6518 |
caretOffset = 0; |
6586 |
caretOffset = 0; |
6519 |
topIndex = 0; |
6587 |
topIndex = 0; |
6520 |
topOffset = 0; |
6588 |
topOffset = 0; |
6521 |
verticalScrollOffset = 0; |
6589 |
verticalScrollOffset = 0; |
6522 |
horizontalScrollOffset = 0; |
6590 |
horizontalScrollOffset = 0; |
6523 |
resetSelection(); |
6591 |
resetSelection(); |
6524 |
// discard any styles that may have been set by creating a |
6592 |
// discard any styles that may have been set by creating a |
6525 |
// new default line styler |
6593 |
// new default line styler |
6526 |
if (defaultLineStyler != null) { |
6594 |
if (defaultLineStyler != null) { |
6527 |
removeLineBackgroundListener(defaultLineStyler); |
6595 |
removeLineBackgroundListener(defaultLineStyler); |
6528 |
removeLineStyleListener(defaultLineStyler); |
6596 |
removeLineStyleListener(defaultLineStyler); |
6529 |
installDefaultLineStyler(); |
6597 |
installDefaultLineStyler(); |
6530 |
} |
6598 |
} |
6531 |
calculateContentWidth(); |
6599 |
calculateContentWidth(); |
6532 |
if (verticalBar != null) { |
6600 |
if (verticalBar != null) { |
6533 |
verticalBar.setSelection(0); |
6601 |
verticalBar.setSelection(0); |
6534 |
} |
6602 |
} |
6535 |
if (horizontalBar != null) { |
6603 |
if (horizontalBar != null) { |
6536 |
horizontalBar.setSelection(0); |
6604 |
horizontalBar.setSelection(0); |
6537 |
} |
6605 |
} |
6538 |
setScrollBars(); |
6606 |
setScrollBars(); |
6539 |
setCaretLocation(); |
6607 |
setCaretLocation(); |
6540 |
super.redraw(); |
6608 |
super.redraw(); |
6541 |
} |
6609 |
} |
6542 |
/** |
6610 |
/** |
6543 |
* Resets the selection. |
6611 |
* Resets the selection. |
6544 |
*/ |
6612 |
*/ |
6545 |
void resetSelection() { |
6613 |
void resetSelection() { |
6546 |
selection.x = selection.y = caretOffset; |
6614 |
selection.x = selection.y = caretOffset; |
6547 |
selectionAnchor = -1; |
6615 |
selectionAnchor = -1; |
|
|
6616 |
// see if we need to update the mouse pointer |
6617 |
internalSetCursor(); |
6548 |
} |
6618 |
} |
6549 |
/** |
6619 |
/** |
6550 |
* Scrolls the widget horizontally. |
6620 |
* Scrolls the widget horizontally. |
6551 |
* <p> |
6621 |
* <p> |
6552 |
* |
6622 |
* |
6553 |
* @param pixels number of pixels to scroll, > 0 = scroll left, |
6623 |
* @param pixels number of pixels to scroll, > 0 = scroll left, |
6554 |
* < 0 scroll right |
6624 |
* < 0 scroll right |
6555 |
*/ |
6625 |
*/ |
6556 |
void scrollHorizontal(int pixels) { |
6626 |
void scrollHorizontal(int pixels) { |
6557 |
Rectangle clientArea; |
6627 |
Rectangle clientArea; |
6558 |
|
6628 |
|
6559 |
if (pixels == 0) { |
6629 |
if (pixels == 0) { |
6560 |
return; |
6630 |
return; |
6561 |
} |
6631 |
} |
6562 |
clientArea = getClientArea(); |
6632 |
clientArea = getClientArea(); |
6563 |
if (pixels > 0) { |
6633 |
if (pixels > 0) { |
6564 |
int sourceX = leftMargin + pixels; |
6634 |
int sourceX = leftMargin + pixels; |
6565 |
int scrollWidth = clientArea.width - sourceX - rightMargin; |
6635 |
int scrollWidth = clientArea.width - sourceX - rightMargin; |
6566 |
int scrollHeight = clientArea.height - topMargin - bottomMargin; |
6636 |
int scrollHeight = clientArea.height - topMargin - bottomMargin; |
6567 |
scroll( |
6637 |
scroll( |
6568 |
leftMargin, topMargin, // destination x, y |
6638 |
leftMargin, topMargin, // destination x, y |
6569 |
sourceX, topMargin, // source x, y |
6639 |
sourceX, topMargin, // source x, y |
6570 |
scrollWidth, scrollHeight, true); |
6640 |
scrollWidth, scrollHeight, true); |
6571 |
if (sourceX > scrollWidth) { |
6641 |
if (sourceX > scrollWidth) { |
6572 |
// redraw from end of scrolled area to beginning of scroll |
6642 |
// redraw from end of scrolled area to beginning of scroll |
6573 |
// invalidated area |
6643 |
// invalidated area |
6574 |
super.redraw( |
6644 |
super.redraw( |
6575 |
leftMargin + scrollWidth, topMargin, |
6645 |
leftMargin + scrollWidth, topMargin, |
6576 |
pixels - scrollWidth, scrollHeight, true); |
6646 |
pixels - scrollWidth, scrollHeight, true); |
6577 |
} |
6647 |
} |
6578 |
} |
6648 |
} |
6579 |
else { |
6649 |
else { |
6580 |
int destinationX = leftMargin - pixels; |
6650 |
int destinationX = leftMargin - pixels; |
6581 |
int scrollWidth = clientArea.width - destinationX - rightMargin; |
6651 |
int scrollWidth = clientArea.width - destinationX - rightMargin; |
6582 |
int scrollHeight = clientArea.height - topMargin - bottomMargin; |
6652 |
int scrollHeight = clientArea.height - topMargin - bottomMargin; |
6583 |
scroll( |
6653 |
scroll( |
6584 |
destinationX, topMargin, // destination x, y |
6654 |
destinationX, topMargin, // destination x, y |
6585 |
leftMargin, topMargin, // source x, y |
6655 |
leftMargin, topMargin, // source x, y |
6586 |
scrollWidth, scrollHeight, true); |
6656 |
scrollWidth, scrollHeight, true); |
6587 |
if (destinationX > scrollWidth) { |
6657 |
if (destinationX > scrollWidth) { |
6588 |
// redraw from end of scroll invalidated area to scroll |
6658 |
// redraw from end of scroll invalidated area to scroll |
6589 |
// destination |
6659 |
// destination |
6590 |
super.redraw( |
6660 |
super.redraw( |
6591 |
leftMargin + scrollWidth, topMargin, |
6661 |
leftMargin + scrollWidth, topMargin, |
6592 |
-pixels - scrollWidth, scrollHeight, true); |
6662 |
-pixels - scrollWidth, scrollHeight, true); |
6593 |
} |
6663 |
} |
6594 |
} |
6664 |
} |
6595 |
horizontalScrollOffset += pixels; |
6665 |
horizontalScrollOffset += pixels; |
6596 |
setCaretLocation(); |
6666 |
setCaretLocation(); |
6597 |
} |
6667 |
} |
6598 |
/** |
6668 |
/** |
6599 |
* Scrolls the widget horizontally and adjust the horizontal scroll |
6669 |
* Scrolls the widget horizontally and adjust the horizontal scroll |
Lines 6601-6623
Link Here
|
6601 |
* <p> |
6671 |
* <p> |
6602 |
* |
6672 |
* |
6603 |
* @param pixels number of pixels to scroll, > 0 = scroll left, |
6673 |
* @param pixels number of pixels to scroll, > 0 = scroll left, |
6604 |
* < 0 scroll right |
6674 |
* < 0 scroll right |
6605 |
* @return |
6675 |
* @return |
6606 |
* true=the widget was scrolled |
6676 |
* true=the widget was scrolled |
6607 |
* false=the widget was not scrolled, the given offset is not valid. |
6677 |
* false=the widget was not scrolled, the given offset is not valid. |
6608 |
*/ |
6678 |
*/ |
6609 |
boolean scrollHorizontalBar(int pixels) { |
6679 |
boolean scrollHorizontalBar(int pixels) { |
6610 |
if (pixels == 0) { |
6680 |
if (pixels == 0) { |
6611 |
return false; |
6681 |
return false; |
6612 |
} |
6682 |
} |
6613 |
ScrollBar horizontalBar = getHorizontalBar(); |
6683 |
ScrollBar horizontalBar = getHorizontalBar(); |
6614 |
if (horizontalBar != null) { |
6684 |
if (horizontalBar != null) { |
6615 |
horizontalBar.setSelection(horizontalScrollOffset + pixels); |
6685 |
horizontalBar.setSelection(horizontalScrollOffset + pixels); |
6616 |
} |
6686 |
} |
6617 |
scrollHorizontal(pixels); |
6687 |
scrollHorizontal(pixels); |
6618 |
return true; |
6688 |
return true; |
6619 |
} |
6689 |
} |
6620 |
/** |
6690 |
/** |
6621 |
* Selects all the text. |
6691 |
* Selects all the text. |
6622 |
* <p> |
6692 |
* <p> |
6623 |
* |
6693 |
* |
Lines 6627-6660
Link Here
|
6627 |
* </ul> |
6697 |
* </ul> |
6628 |
*/ |
6698 |
*/ |
6629 |
public void selectAll() { |
6699 |
public void selectAll() { |
6630 |
checkWidget(); |
6700 |
checkWidget(); |
6631 |
setSelection(new Point(0, Math.max(getCharCount(),0))); |
6701 |
setSelection(new Point(0, Math.max(getCharCount(),0))); |
6632 |
} |
6702 |
} |
6633 |
/** |
6703 |
/** |
6634 |
* Replaces/inserts text as defined by the event. |
6704 |
* Replaces/inserts text as defined by the event. |
6635 |
* <p> |
6705 |
* <p> |
6636 |
* |
6706 |
* |
6637 |
* @param event the text change event. |
6707 |
* @param event the text change event. |
6638 |
* <ul> |
6708 |
* <ul> |
6639 |
* <li>event.start - the replace start offset</li> |
6709 |
* <li>event.start - the replace start offset</li> |
6640 |
* <li>event.end - the replace end offset</li> |
6710 |
* <li>event.end - the replace end offset</li> |
6641 |
* <li>event.text - the new text</li> |
6711 |
* <li>event.text - the new text</li> |
6642 |
* </ul> |
6712 |
* </ul> |
6643 |
*/ |
6713 |
*/ |
6644 |
void sendKeyEvent(Event event) { |
6714 |
void sendKeyEvent(Event event) { |
6645 |
if (editable == false) { |
6715 |
if (editable == false) { |
6646 |
return; |
6716 |
return; |
6647 |
} |
6717 |
} |
6648 |
modifyContent(event, true); |
6718 |
modifyContent(event, true); |
6649 |
} |
6719 |
} |
6650 |
/** |
6720 |
/** |
6651 |
* Sends the specified selection event. |
6721 |
* Sends the specified selection event. |
6652 |
*/ |
6722 |
*/ |
6653 |
void sendSelectionEvent() { |
6723 |
void sendSelectionEvent() { |
6654 |
Event event = new Event(); |
6724 |
Event event = new Event(); |
6655 |
event.x = selection.x; |
6725 |
event.x = selection.x; |
6656 |
event.y = selection.y; |
6726 |
event.y = selection.y; |
6657 |
notifyListeners(SWT.Selection, event); |
6727 |
notifyListeners(SWT.Selection, event); |
6658 |
} |
6728 |
} |
6659 |
/** |
6729 |
/** |
6660 |
* Sets whether the widget wraps lines. |
6730 |
* Sets whether the widget wraps lines. |
Lines 6665-6723
Link Here
|
6665 |
* @since 2.0 |
6735 |
* @since 2.0 |
6666 |
*/ |
6736 |
*/ |
6667 |
public void setWordWrap(boolean wrap) { |
6737 |
public void setWordWrap(boolean wrap) { |
6668 |
checkWidget(); |
6738 |
checkWidget(); |
6669 |
|
6739 |
|
6670 |
if (wrap != wordWrap) { |
6740 |
if (wrap != wordWrap) { |
6671 |
ScrollBar horizontalBar = getHorizontalBar(); |
6741 |
ScrollBar horizontalBar = getHorizontalBar(); |
6672 |
|
6742 |
|
6673 |
wordWrap = wrap; |
6743 |
wordWrap = wrap; |
6674 |
if (wordWrap) { |
6744 |
if (wordWrap) { |
6675 |
logicalContent = content; |
6745 |
logicalContent = content; |
6676 |
content = new WrappedContent(renderer, logicalContent); |
6746 |
content = new WrappedContent(renderer, logicalContent); |
6677 |
} |
6747 |
} |
6678 |
else { |
6748 |
else { |
6679 |
content = logicalContent; |
6749 |
content = logicalContent; |
6680 |
} |
6750 |
} |
6681 |
calculateContentWidth(); |
6751 |
calculateContentWidth(); |
6682 |
horizontalScrollOffset = 0; |
6752 |
horizontalScrollOffset = 0; |
6683 |
if (horizontalBar != null) { |
6753 |
if (horizontalBar != null) { |
6684 |
horizontalBar.setVisible(!wordWrap); |
6754 |
horizontalBar.setVisible(!wordWrap); |
6685 |
} |
6755 |
} |
6686 |
setScrollBars(); |
6756 |
setScrollBars(); |
6687 |
setCaretLocation(); |
6757 |
setCaretLocation(); |
6688 |
super.redraw(); |
6758 |
super.redraw(); |
6689 |
} |
6759 |
} |
6690 |
} |
6760 |
} |
6691 |
/** |
6761 |
/** |
6692 |
* Sets the caret location and scrolls the caret offset into view. |
6762 |
* Sets the caret location and scrolls the caret offset into view. |
6693 |
*/ |
6763 |
*/ |
6694 |
void showBidiCaret() { |
6764 |
void showBidiCaret() { |
6695 |
int line = content.getLineAtOffset(caretOffset); |
6765 |
int line = content.getLineAtOffset(caretOffset); |
6696 |
int lineOffset = content.getOffsetAtLine(line); |
6766 |
int lineOffset = content.getOffsetAtLine(line); |
6697 |
int offsetInLine = caretOffset - lineOffset; |
6767 |
int offsetInLine = caretOffset - lineOffset; |
6698 |
String lineText = content.getLine(line); |
6768 |
String lineText = content.getLine(line); |
6699 |
int xAtOffset = 0; |
6769 |
int xAtOffset = 0; |
6700 |
boolean scrolled = false; |
6770 |
boolean scrolled = false; |
6701 |
GC gc = getGC(); |
6771 |
GC gc = getGC(); |
6702 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
6772 |
StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); |
6703 |
// getXAtOffset, inlined for better performance |
6773 |
// getXAtOffset, inlined for better performance |
6704 |
xAtOffset = getBidiTextPosition(lineText, offsetInLine, bidi) + leftMargin; |
6774 |
xAtOffset = getBidiTextPosition(lineText, offsetInLine, bidi) + leftMargin; |
6705 |
if (offsetInLine > lineText.length()) { |
6775 |
if (offsetInLine > lineText.length()) { |
6706 |
// offset is not on the line. return an x location one character |
6776 |
// offset is not on the line. return an x location one character |
6707 |
// after the line to indicate the line delimiter. |
6777 |
// after the line to indicate the line delimiter. |
6708 |
xAtOffset += lineEndSpaceWidth; |
6778 |
xAtOffset += lineEndSpaceWidth; |
6709 |
} |
6779 |
} |
6710 |
xAtOffset -= horizontalScrollOffset; |
6780 |
xAtOffset -= horizontalScrollOffset; |
6711 |
// |
6781 |
// |
6712 |
scrolled = showLocation(xAtOffset, line); |
6782 |
scrolled = showLocation(xAtOffset, line); |
6713 |
if (scrolled == false) { |
6783 |
if (scrolled == false) { |
6714 |
setBidiCaretLocation(bidi); |
6784 |
setBidiCaretLocation(bidi); |
6715 |
} |
6785 |
} |
6716 |
gc.dispose(); |
6786 |
gc.dispose(); |
6717 |
} |
6787 |
} |
6718 |
/** |
6788 |
/** |
6719 |
* Sets the receiver's caret. Set the caret's height and location. |
6789 |
* Sets the receiver's caret. Set the caret's height and location. |
6720 |
* |
6790 |
* |
6721 |
* </p> |
6791 |
* </p> |
6722 |
* @param caret the new caret for the receiver |
6792 |
* @param caret the new caret for the receiver |
6723 |
* |
6793 |
* |
Lines 6727-6826
Link Here
|
6727 |
* </ul> |
6797 |
* </ul> |
6728 |
*/ |
6798 |
*/ |
6729 |
public void setCaret(Caret caret) { |
6799 |
public void setCaret(Caret caret) { |
6730 |
checkWidget (); |
6800 |
checkWidget (); |
6731 |
super.setCaret(caret); |
6801 |
super.setCaret(caret); |
6732 |
if (caret != null) { |
6802 |
if (caret != null) { |
6733 |
if (isBidi() == false) { |
6803 |
if (isBidi() == false) { |
6734 |
caret.setSize(caret.getSize().x, lineHeight); |
6804 |
caret.setSize(caret.getSize().x, lineHeight); |
6735 |
} |
6805 |
} |
6736 |
setCaretLocation(); |
6806 |
setCaretLocation(); |
6737 |
if (isBidi()) { |
6807 |
if (isBidi()) { |
6738 |
setBidiKeyboardLanguage(); |
6808 |
setBidiKeyboardLanguage(); |
6739 |
} |
6809 |
} |
6740 |
} |
6810 |
} |
6741 |
} |
6811 |
} |
6742 |
/** |
6812 |
/** |
6743 |
* @see org.eclipse.swt.widgets.Control#setBackground |
6813 |
* @see org.eclipse.swt.widgets.Control#setBackground |
6744 |
*/ |
6814 |
*/ |
6745 |
public void setBackground(Color color) { |
6815 |
public void setBackground(Color color) { |
6746 |
checkWidget(); |
6816 |
checkWidget(); |
6747 |
super.setBackground(color); |
6817 |
super.setBackground(color); |
6748 |
background = color; |
6818 |
background = color; |
6749 |
redraw(); |
6819 |
redraw(); |
6750 |
} |
6820 |
} |
6751 |
/** |
6821 |
/** |
6752 |
* Set the caret to indicate the current typing direction. |
6822 |
* Set the caret to indicate the current typing direction. |
6753 |
*/ |
6823 |
*/ |
6754 |
void setBidiCaretDirection() { |
6824 |
void setBidiCaretDirection() { |
6755 |
Caret caret = getCaret(); |
6825 |
Caret caret = getCaret(); |
6756 |
int direction = StyledTextBidi.getKeyboardLanguageDirection(); |
6826 |
int direction = StyledTextBidi.getKeyboardLanguageDirection(); |
6757 |
|
6827 |
|
6758 |
if (caret == null || direction == caretDirection) { |
6828 |
if (caret == null || direction == caretDirection) { |
6759 |
return; |
6829 |
return; |
6760 |
} |
6830 |
} |
6761 |
caretDirection = direction; |
6831 |
caretDirection = direction; |
6762 |
if (direction == SWT.DEFAULT) { |
6832 |
if (direction == SWT.DEFAULT) { |
6763 |
caret.setImage(null); |
6833 |
caret.setImage(null); |
6764 |
caret.setSize(caret.getSize().x, lineHeight); |
6834 |
caret.setSize(caret.getSize().x, lineHeight); |
6765 |
} |
6835 |
} |
6766 |
else |
6836 |
else |
6767 |
if (caretDirection == SWT.LEFT) { |
6837 |
if (caretDirection == SWT.LEFT) { |
6768 |
caret.setImage(leftCaretBitmap); |
6838 |
caret.setImage(leftCaretBitmap); |
6769 |
} |
6839 |
} |
6770 |
else |
6840 |
else |
6771 |
if (caretDirection == SWT.RIGHT) { |
6841 |
if (caretDirection == SWT.RIGHT) { |
6772 |
caret.setImage(rightCaretBitmap); |
6842 |
caret.setImage(rightCaretBitmap); |
6773 |
} |
6843 |
} |
6774 |
} |
6844 |
} |
6775 |
/** |
6845 |
/** |
6776 |
* Moves the Caret to the current caret offset. |
6846 |
* Moves the Caret to the current caret offset. |
6777 |
* <p> |
6847 |
* <p> |
6778 |
* |
6848 |
* |
6779 |
* @param bidi StyledTextBidi object to use for measuring. |
6849 |
* @param bidi StyledTextBidi object to use for measuring. |
6780 |
* May be left null in which case a new object will be created. |
6850 |
* May be left null in which case a new object will be created. |
6781 |
*/ |
6851 |
*/ |
6782 |
void setBidiCaretLocation(StyledTextBidi bidi) { |
6852 |
void setBidiCaretLocation(StyledTextBidi bidi) { |
6783 |
int caretLine = getCaretLine(); |
6853 |
int caretLine = getCaretLine(); |
6784 |
|
6854 |
|
6785 |
setBidiCaretLocation(bidi, caretLine); |
6855 |
setBidiCaretLocation(bidi, caretLine); |
6786 |
} |
6856 |
} |
6787 |
/** |
6857 |
/** |
6788 |
* Moves the Caret to the current caret offset. |
6858 |
* Moves the Caret to the current caret offset. |
6789 |
* <p> |
6859 |
* <p> |
6790 |
* |
6860 |
* |
6791 |
* @param bidi StyledTextBidi object to use for measuring. |
6861 |
* @param bidi StyledTextBidi object to use for measuring. |
6792 |
* May be left null in which case a new object will be created. |
6862 |
* May be left null in which case a new object will be created. |
6793 |
* @param caretLine line the caret should be placed on. Relative to |
6863 |
* @param caretLine line the caret should be placed on. Relative to |
6794 |
* first line in document |
6864 |
* first line in document |
6795 |
*/ |
6865 |
*/ |
6796 |
void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) { |
6866 |
void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) { |
6797 |
Caret caret = getCaret(); |
6867 |
Caret caret = getCaret(); |
6798 |
String lineText = content.getLine(caretLine); |
6868 |
String lineText = content.getLine(caretLine); |
6799 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6869 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6800 |
int offsetInLine = caretOffset - lineStartOffset; |
6870 |
int offsetInLine = caretOffset - lineStartOffset; |
6801 |
GC gc = null; |
6871 |
GC gc = null; |
6802 |
|
6872 |
|
6803 |
if (bidi == null) { |
6873 |
if (bidi == null) { |
6804 |
gc = getGC(); |
6874 |
gc = getGC(); |
6805 |
bidi = getStyledTextBidi(lineText, lineStartOffset, gc); |
6875 |
bidi = getStyledTextBidi(lineText, lineStartOffset, gc); |
6806 |
} |
6876 |
} |
6807 |
if (lastCaretDirection == SWT.NULL) { |
6877 |
if (lastCaretDirection == SWT.NULL) { |
6808 |
columnX = bidi.getTextPosition(offsetInLine) + leftMargin - horizontalScrollOffset; |
6878 |
columnX = bidi.getTextPosition(offsetInLine) + leftMargin - horizontalScrollOffset; |
6809 |
} else { |
6879 |
} else { |
6810 |
columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset; |
6880 |
columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset; |
6811 |
} |
6881 |
} |
6812 |
if (StyledTextBidi.getKeyboardLanguageDirection() == SWT.RIGHT) { |
6882 |
if (StyledTextBidi.getKeyboardLanguageDirection() == SWT.RIGHT) { |
6813 |
columnX -= (getCaretWidth() - 1); |
6883 |
columnX -= (getCaretWidth() - 1); |
6814 |
} |
6884 |
} |
6815 |
if (caret != null) { |
6885 |
if (caret != null) { |
6816 |
setBidiCaretDirection(); |
6886 |
setBidiCaretDirection(); |
6817 |
caret.setLocation( |
6887 |
caret.setLocation( |
6818 |
columnX, |
6888 |
columnX, |
6819 |
caretLine * lineHeight - verticalScrollOffset + topMargin); |
6889 |
caretLine * lineHeight - verticalScrollOffset + topMargin); |
6820 |
} |
6890 |
} |
6821 |
if (gc != null) { |
6891 |
if (gc != null) { |
6822 |
gc.dispose(); |
6892 |
gc.dispose(); |
6823 |
} |
6893 |
} |
6824 |
} |
6894 |
} |
6825 |
/** |
6895 |
/** |
6826 |
* Sets the BIDI coloring mode. When true the BIDI text display |
6896 |
* Sets the BIDI coloring mode. When true the BIDI text display |
Lines 6837-6923
Link Here
|
6837 |
* </p> |
6907 |
* </p> |
6838 |
*/ |
6908 |
*/ |
6839 |
public void setBidiColoring(boolean mode) { |
6909 |
public void setBidiColoring(boolean mode) { |
6840 |
checkWidget(); |
6910 |
checkWidget(); |
6841 |
bidiColoring = mode; |
6911 |
bidiColoring = mode; |
6842 |
} |
6912 |
} |
6843 |
/** |
6913 |
/** |
6844 |
* Switches the keyboard language according to the current editing |
6914 |
* Switches the keyboard language according to the current editing |
6845 |
* position and cursor direction. |
6915 |
* position and cursor direction. |
6846 |
*/ |
6916 |
*/ |
6847 |
void setBidiKeyboardLanguage() { |
6917 |
void setBidiKeyboardLanguage() { |
6848 |
int caretLine = getCaretLine(); |
6918 |
int caretLine = getCaretLine(); |
6849 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6919 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6850 |
int offsetInLine = caretOffset - lineStartOffset; |
6920 |
int offsetInLine = caretOffset - lineStartOffset; |
6851 |
String lineText = content.getLine(caretLine); |
6921 |
String lineText = content.getLine(caretLine); |
6852 |
GC gc = getGC(); |
6922 |
GC gc = getGC(); |
6853 |
StyledTextBidi bidi; |
6923 |
StyledTextBidi bidi; |
6854 |
int lineLength = lineText.length(); |
6924 |
int lineLength = lineText.length(); |
6855 |
|
6925 |
|
6856 |
// Don't supply the bold styles/font since we don't want to measure anything |
6926 |
// Don't supply the bold styles/font since we don't want to measure anything |
6857 |
bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); |
6927 |
bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); |
6858 |
if (offsetInLine == 0) { |
6928 |
if (offsetInLine == 0) { |
6859 |
bidi.setKeyboardLanguage(offsetInLine); |
6929 |
bidi.setKeyboardLanguage(offsetInLine); |
6860 |
} |
6930 |
} |
6861 |
else |
6931 |
else |
6862 |
if (offsetInLine >= lineLength) { |
6932 |
if (offsetInLine >= lineLength) { |
6863 |
offsetInLine = Math.min(offsetInLine, lineLength - 1); |
6933 |
offsetInLine = Math.min(offsetInLine, lineLength - 1); |
6864 |
bidi.setKeyboardLanguage(offsetInLine); |
6934 |
bidi.setKeyboardLanguage(offsetInLine); |
6865 |
} |
6935 |
} |
6866 |
else |
6936 |
else |
6867 |
if (lastCaretDirection == ST.COLUMN_NEXT) { |
6937 |
if (lastCaretDirection == ST.COLUMN_NEXT) { |
6868 |
// continue with previous character type |
6938 |
// continue with previous character type |
6869 |
bidi.setKeyboardLanguage(offsetInLine - 1); |
6939 |
bidi.setKeyboardLanguage(offsetInLine - 1); |
6870 |
} |
6940 |
} |
6871 |
else { |
6941 |
else { |
6872 |
bidi.setKeyboardLanguage(offsetInLine); |
6942 |
bidi.setKeyboardLanguage(offsetInLine); |
6873 |
} |
6943 |
} |
6874 |
gc.dispose(); |
6944 |
gc.dispose(); |
6875 |
} |
6945 |
} |
6876 |
/** |
6946 |
/** |
6877 |
* Moves the Caret to the current caret offset. |
6947 |
* Moves the Caret to the current caret offset. |
6878 |
* <p> |
6948 |
* <p> |
6879 |
* |
6949 |
* |
6880 |
* @param newCaretX the new x location of the caret. |
6950 |
* @param newCaretX the new x location of the caret. |
6881 |
* passed in for better performance when it has already been |
6951 |
* passed in for better performance when it has already been |
6882 |
* calculated outside this method. |
6952 |
* calculated outside this method. |
6883 |
* @param line index of the line the caret is on. Relative to |
6953 |
* @param line index of the line the caret is on. Relative to |
6884 |
* the first line in the document. |
6954 |
* the first line in the document. |
6885 |
*/ |
6955 |
*/ |
6886 |
void setCaretLocation(int newCaretX, int line) { |
6956 |
void setCaretLocation(int newCaretX, int line) { |
6887 |
if (isBidi()) { |
6957 |
if (isBidi()) { |
6888 |
setBidiCaretLocation(null, line); |
6958 |
setBidiCaretLocation(null, line); |
6889 |
} |
6959 |
} |
6890 |
else { |
6960 |
else { |
6891 |
Caret caret = getCaret(); |
6961 |
Caret caret = getCaret(); |
6892 |
|
6962 |
|
6893 |
columnX = newCaretX; |
6963 |
columnX = newCaretX; |
6894 |
if (caret != null) { |
6964 |
if (caret != null) { |
6895 |
caret.setLocation( |
6965 |
caret.setLocation( |
6896 |
newCaretX, |
6966 |
newCaretX, |
6897 |
line * lineHeight - verticalScrollOffset + topMargin); |
6967 |
line * lineHeight - verticalScrollOffset + topMargin); |
6898 |
} |
6968 |
} |
6899 |
} |
6969 |
} |
6900 |
} |
6970 |
} |
6901 |
/** |
6971 |
/** |
6902 |
* Moves the Caret to the current caret offset. |
6972 |
* Moves the Caret to the current caret offset. |
6903 |
*/ |
6973 |
*/ |
6904 |
void setCaretLocation() { |
6974 |
void setCaretLocation() { |
6905 |
if (isBidi()) { |
6975 |
if (isBidi()) { |
6906 |
setBidiCaretLocation(null); |
6976 |
setBidiCaretLocation(null); |
6907 |
} |
6977 |
} |
6908 |
else { |
6978 |
else { |
6909 |
Caret caret = getCaret(); |
6979 |
Caret caret = getCaret(); |
6910 |
int caretLine = getCaretLine(); |
6980 |
int caretLine = getCaretLine(); |
6911 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6981 |
int lineStartOffset = content.getOffsetAtLine(caretLine); |
6912 |
|
6982 |
|
6913 |
columnX = getXAtOffset( |
6983 |
columnX = getXAtOffset( |
6914 |
content.getLine(caretLine), caretLine, caretOffset - lineStartOffset); |
6984 |
content.getLine(caretLine), caretLine, caretOffset - lineStartOffset); |
6915 |
if (caret != null) { |
6985 |
if (caret != null) { |
6916 |
caret.setLocation( |
6986 |
caret.setLocation( |
6917 |
columnX, |
6987 |
columnX, |
6918 |
caretLine * lineHeight - verticalScrollOffset + topMargin); |
6988 |
caretLine * lineHeight - verticalScrollOffset + topMargin); |
6919 |
} |
6989 |
} |
6920 |
} |
6990 |
} |
6921 |
} |
6991 |
} |
6922 |
/** |
6992 |
/** |
6923 |
* Sets the caret offset. |
6993 |
* Sets the caret offset. |
Lines 6928-6967
Link Here
|
6928 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6998 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
6929 |
* </ul> |
6999 |
* </ul> |
6930 |
* @exception IllegalArgumentException <ul> |
7000 |
* @exception IllegalArgumentException <ul> |
6931 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7001 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
6932 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7002 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
6933 |
* </ul> |
7003 |
* </ul> |
6934 |
*/ |
7004 |
*/ |
6935 |
public void setCaretOffset(int offset) { |
7005 |
public void setCaretOffset(int offset) { |
6936 |
checkWidget(); |
7006 |
checkWidget(); |
6937 |
int length = getCharCount(); |
7007 |
int length = getCharCount(); |
6938 |
|
7008 |
|
6939 |
if (length > 0 && offset != caretOffset) { |
7009 |
if (length > 0 && offset != caretOffset) { |
6940 |
if (offset < 0) { |
7010 |
if (offset < 0) { |
6941 |
caretOffset = 0; |
7011 |
caretOffset = 0; |
6942 |
} |
7012 |
} |
6943 |
else |
7013 |
else |
6944 |
if (offset > length) { |
7014 |
if (offset > length) { |
6945 |
caretOffset = length; |
7015 |
caretOffset = length; |
6946 |
} |
7016 |
} |
6947 |
else { |
7017 |
else { |
6948 |
if (isLineDelimiter(offset)) { |
7018 |
if (isLineDelimiter(offset)) { |
6949 |
// offset is inside a multi byte line delimiter. This is an |
7019 |
// offset is inside a multi byte line delimiter. This is an |
6950 |
// illegal operation and an exception is thrown. Fixes 1GDKK3R |
7020 |
// illegal operation and an exception is thrown. Fixes 1GDKK3R |
6951 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7021 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
6952 |
} |
7022 |
} |
6953 |
caretOffset = offset; |
7023 |
caretOffset = offset; |
6954 |
} |
7024 |
} |
6955 |
// clear the selection if the caret is moved. |
7025 |
// clear the selection if the caret is moved. |
6956 |
// don't notify listeners about the selection change. |
7026 |
// don't notify listeners about the selection change. |
6957 |
clearSelection(false); |
7027 |
clearSelection(false); |
6958 |
} |
7028 |
} |
6959 |
// always update the caret location. fixes 1G8FODP |
7029 |
// always update the caret location. fixes 1G8FODP |
6960 |
setCaretLocation(); |
7030 |
setCaretLocation(); |
6961 |
if (isBidi()) { |
7031 |
if (isBidi()) { |
6962 |
setBidiKeyboardLanguage(); |
7032 |
setBidiKeyboardLanguage(); |
6963 |
} |
7033 |
} |
6964 |
} |
7034 |
} |
6965 |
/** |
7035 |
/** |
6966 |
* Copies the specified text range to the clipboard. The text will be placed |
7036 |
* Copies the specified text range to the clipboard. The text will be placed |
6967 |
* in the clipboard in plain text format and RTF format. |
7037 |
* in the clipboard in plain text format and RTF format. |
Lines 6969-6989
Link Here
|
6969 |
* |
7039 |
* |
6970 |
* @param start start index of the text |
7040 |
* @param start start index of the text |
6971 |
* @param length length of text to place in clipboard |
7041 |
* @param length length of text to place in clipboard |
6972 |
* |
7042 |
* |
6973 |
* @exception SWTError, see Clipboard.setContents |
7043 |
* @exception SWTError, see Clipboard.setContents |
6974 |
* @see org.eclipse.swt.dnd.Clipboard.setContents |
7044 |
* @see org.eclipse.swt.dnd.Clipboard.setContents |
6975 |
*/ |
7045 |
*/ |
6976 |
void setClipboardContent(int start, int length) throws SWTError { |
7046 |
void setClipboardContent(int start, int length) throws SWTError { |
6977 |
RTFTransfer rtfTransfer = RTFTransfer.getInstance(); |
7047 |
RTFTransfer rtfTransfer = RTFTransfer.getInstance(); |
6978 |
TextTransfer plainTextTransfer = TextTransfer.getInstance(); |
7048 |
TextTransfer plainTextTransfer = TextTransfer.getInstance(); |
6979 |
RTFWriter rtfWriter = new RTFWriter(start, length); |
7049 |
RTFWriter rtfWriter = new RTFWriter(start, length); |
6980 |
TextWriter plainTextWriter = new TextWriter(start, length); |
7050 |
TextWriter plainTextWriter = new TextWriter(start, length); |
6981 |
String rtfText = getPlatformDelimitedText(rtfWriter); |
7051 |
String rtfText = getPlatformDelimitedText(rtfWriter); |
6982 |
String plainText = getPlatformDelimitedText(plainTextWriter); |
7052 |
String plainText = getPlatformDelimitedText(plainTextWriter); |
6983 |
|
7053 |
|
6984 |
clipboard.setContents( |
7054 |
clipboard.setContents( |
6985 |
new String[]{rtfText, plainText}, |
7055 |
new String[]{rtfText, plainText}, |
6986 |
new Transfer[]{rtfTransfer, plainTextTransfer}); |
7056 |
new Transfer[]{rtfTransfer, plainTextTransfer}); |
6987 |
} |
7057 |
} |
6988 |
/** |
7058 |
/** |
6989 |
* Sets the content implementation to use for text storage. |
7059 |
* Sets the content implementation to use for text storage. |
Lines 6999-7064
Link Here
|
6999 |
* </ul> |
7069 |
* </ul> |
7000 |
*/ |
7070 |
*/ |
7001 |
public void setContent(StyledTextContent newContent) { |
7071 |
public void setContent(StyledTextContent newContent) { |
7002 |
checkWidget(); |
7072 |
checkWidget(); |
7003 |
if (newContent == null) { |
7073 |
if (newContent == null) { |
7004 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7074 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7005 |
} |
7075 |
} |
7006 |
if (content != null) { |
7076 |
if (content != null) { |
7007 |
content.removeTextChangeListener(textChangeListener); |
7077 |
content.removeTextChangeListener(textChangeListener); |
7008 |
} |
7078 |
} |
7009 |
logicalContent = newContent; |
7079 |
logicalContent = newContent; |
7010 |
if (wordWrap) { |
7080 |
if (wordWrap) { |
7011 |
content = new WrappedContent(renderer, logicalContent); |
7081 |
content = new WrappedContent(renderer, logicalContent); |
7012 |
} |
7082 |
} |
7013 |
else { |
7083 |
else { |
7014 |
content = logicalContent; |
7084 |
content = logicalContent; |
7015 |
} |
7085 |
} |
7016 |
content.addTextChangeListener(textChangeListener); |
7086 |
content.addTextChangeListener(textChangeListener); |
7017 |
reset(); |
7087 |
reset(); |
7018 |
} |
7088 |
} |
7019 |
/** |
7089 |
/** |
7020 |
* Sets the receiver's cursor to the cursor specified by the |
7090 |
* Sets the receiver's cursor to the cursor specified by the |
7021 |
* argument. Overridden to handle the null case since the |
7091 |
* argument. Overridden to handle the null case since the |
7022 |
* StyledText widget uses an ibeam as its default cursor. |
7092 |
* StyledText widget uses an ibeam as its default cursor. |
7023 |
* |
7093 |
* |
7024 |
* @see org.eclipse.swt.widgets.Control#setCursor |
7094 |
* @see org.eclipse.swt.widgets.Control#setCursor |
7025 |
*/ |
7095 |
*/ |
7026 |
public void setCursor (Cursor cursor) { |
7096 |
public void setCursor (Cursor cursor) { |
7027 |
if (cursor == null) { |
7097 |
if (cursor == null || cursor.equals(ibeamCursor)) { |
7028 |
super.setCursor(ibeamCursor); |
7098 |
customCursor = null; |
7029 |
} else { |
7099 |
} else { |
7030 |
super.setCursor(cursor); |
7100 |
customCursor = cursor; |
7031 |
} |
7101 |
} |
|
|
7102 |
internalSetCursor(); |
7032 |
} |
7103 |
} |
7033 |
/** |
7104 |
/** |
7034 |
* Sets whether the widget implements double click mouse behavior. |
7105 |
* Sets whether the widget implements double click mouse behavior. |
7035 |
* </p> |
7106 |
* </p> |
7036 |
* |
7107 |
* |
7037 |
* @param enable if true double clicking a word selects the word, if false |
7108 |
* @param enable if true double clicking a word selects the word, if false |
7038 |
* double clicks have the same effect as regular mouse clicks. |
7109 |
* double clicks have the same effect as regular mouse clicks. |
7039 |
* @exception SWTException <ul> |
7110 |
* @exception SWTException <ul> |
7040 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7111 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7041 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7112 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7042 |
* </ul> |
7113 |
* </ul> |
7043 |
*/ |
7114 |
*/ |
7044 |
public void setDoubleClickEnabled(boolean enable) { |
7115 |
public void setDoubleClickEnabled(boolean enable) { |
7045 |
checkWidget(); |
7116 |
checkWidget(); |
7046 |
doubleClickEnabled = enable; |
7117 |
doubleClickEnabled = enable; |
7047 |
} |
7118 |
} |
7048 |
/** |
7119 |
/** |
7049 |
* Sets whether the widget content can be edited. |
7120 |
* Sets whether the widget content can be edited. |
7050 |
* </p> |
7121 |
* </p> |
7051 |
* |
7122 |
* |
7052 |
* @param editable if true content can be edited, if false content can not be |
7123 |
* @param editable if true content can be edited, if false content can not be |
7053 |
* edited |
7124 |
* edited |
7054 |
* @exception SWTException <ul> |
7125 |
* @exception SWTException <ul> |
7055 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7126 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7056 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7127 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7057 |
* </ul> |
7128 |
* </ul> |
7058 |
*/ |
7129 |
*/ |
7059 |
public void setEditable(boolean editable) { |
7130 |
public void setEditable(boolean editable) { |
7060 |
checkWidget(); |
7131 |
checkWidget(); |
7061 |
this.editable = editable; |
7132 |
this.editable = editable; |
7062 |
} |
7133 |
} |
7063 |
/** |
7134 |
/** |
7064 |
* Sets a new font to render text with. |
7135 |
* Sets a new font to render text with. |
Lines 7074-7166
Link Here
|
7074 |
* </ul> |
7145 |
* </ul> |
7075 |
*/ |
7146 |
*/ |
7076 |
public void setFont(Font font) { |
7147 |
public void setFont(Font font) { |
7077 |
checkWidget(); |
7148 |
checkWidget(); |
7078 |
int oldLineHeight = lineHeight; |
7149 |
int oldLineHeight = lineHeight; |
7079 |
|
7150 |
|
7080 |
super.setFont(font); |
7151 |
super.setFont(font); |
7081 |
initializeRenderer(); |
7152 |
initializeRenderer(); |
7082 |
// keep the same top line visible. fixes 5815 |
7153 |
// keep the same top line visible. fixes 5815 |
7083 |
if (lineHeight != oldLineHeight) { |
7154 |
if (lineHeight != oldLineHeight) { |
7084 |
setVerticalScrollOffset(verticalScrollOffset * lineHeight / oldLineHeight, true); |
7155 |
setVerticalScrollOffset(verticalScrollOffset * lineHeight / oldLineHeight, true); |
7085 |
claimBottomFreeSpace(); |
7156 |
claimBottomFreeSpace(); |
7086 |
} |
7157 |
} |
7087 |
calculateContentWidth(); |
7158 |
calculateContentWidth(); |
7088 |
calculateScrollBars(); |
7159 |
calculateScrollBars(); |
7089 |
if (isBidi()) { |
7160 |
if (isBidi()) { |
7090 |
caretDirection = SWT.NULL; |
7161 |
caretDirection = SWT.NULL; |
7091 |
createCaretBitmaps(); |
7162 |
createCaretBitmaps(); |
7092 |
setBidiCaretDirection(); |
7163 |
setBidiCaretDirection(); |
7093 |
} |
7164 |
} |
7094 |
else { |
7165 |
else { |
7095 |
Caret caret = getCaret(); |
7166 |
Caret caret = getCaret(); |
7096 |
if (caret != null) { |
7167 |
if (caret != null) { |
7097 |
caret.setSize(caret.getSize().x, lineHeight); |
7168 |
caret.setSize(caret.getSize().x, lineHeight); |
7098 |
} |
7169 |
} |
7099 |
} |
7170 |
} |
7100 |
// always set the caret location. Fixes 6685 |
7171 |
// always set the caret location. Fixes 6685 |
7101 |
setCaretLocation(); |
7172 |
setCaretLocation(); |
7102 |
super.redraw(); |
7173 |
super.redraw(); |
7103 |
} |
7174 |
} |
7104 |
/** |
7175 |
/** |
7105 |
* @see org.eclipse.swt.widgets.Control#setForeground |
7176 |
* @see org.eclipse.swt.widgets.Control#setForeground |
7106 |
*/ |
7177 |
*/ |
7107 |
public void setForeground(Color color) { |
7178 |
public void setForeground(Color color) { |
7108 |
checkWidget(); |
7179 |
checkWidget(); |
7109 |
super.setForeground(color); |
7180 |
super.setForeground(color); |
7110 |
foreground = color; |
7181 |
foreground = color; |
7111 |
redraw(); |
7182 |
redraw(); |
7112 |
} |
7183 |
} |
7113 |
/** |
7184 |
/** |
7114 |
* Sets the horizontal scroll offset relative to the start of the line. |
7185 |
* Sets the horizontal scroll offset relative to the start of the line. |
7115 |
* Do nothing if there is no text set. |
7186 |
* Do nothing if there is no text set. |
7116 |
* <p> |
7187 |
* <p> |
7117 |
* <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the |
7188 |
* <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the |
7118 |
* widget. |
7189 |
* widget. |
7119 |
* </p> |
7190 |
* </p> |
7120 |
* |
7191 |
* |
7121 |
* @param offset horizontal scroll offset relative to the start |
7192 |
* @param offset horizontal scroll offset relative to the start |
7122 |
* of the line, measured in character increments starting at 0, if |
7193 |
* of the line, measured in character increments starting at 0, if |
7123 |
* equal to 0 the content is not scrolled, if > 0 = the content is scrolled. |
7194 |
* equal to 0 the content is not scrolled, if > 0 = the content is scrolled. |
7124 |
* @exception SWTException <ul> |
7195 |
* @exception SWTException <ul> |
7125 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7196 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7126 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7197 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7127 |
* </ul> |
7198 |
* </ul> |
7128 |
*/ |
7199 |
*/ |
7129 |
public void setHorizontalIndex(int offset) { |
7200 |
public void setHorizontalIndex(int offset) { |
7130 |
checkWidget(); |
7201 |
checkWidget(); |
7131 |
int clientAreaWidth = getClientArea().width; |
7202 |
int clientAreaWidth = getClientArea().width; |
7132 |
if (getCharCount() == 0) { |
7203 |
if (getCharCount() == 0) { |
7133 |
return; |
7204 |
return; |
7134 |
} |
7205 |
} |
7135 |
if (offset < 0) { |
7206 |
if (offset < 0) { |
7136 |
offset = 0; |
7207 |
offset = 0; |
7137 |
} |
7208 |
} |
7138 |
offset *= getHorizontalIncrement(); |
7209 |
offset *= getHorizontalIncrement(); |
7139 |
// allow any value if client area width is unknown or 0. |
7210 |
// allow any value if client area width is unknown or 0. |
7140 |
// offset will be checked in resize handler. |
7211 |
// offset will be checked in resize handler. |
7141 |
// don't use isVisible since width is known even if widget |
7212 |
// don't use isVisible since width is known even if widget |
7142 |
// is temporarily invisible |
7213 |
// is temporarily invisible |
7143 |
if (clientAreaWidth > 0) { |
7214 |
if (clientAreaWidth > 0) { |
7144 |
int width = lineCache.getWidth(); |
7215 |
int width = lineCache.getWidth(); |
7145 |
// prevent scrolling if the content fits in the client area. |
7216 |
// prevent scrolling if the content fits in the client area. |
7146 |
// align end of longest line with right border of client area |
7217 |
// align end of longest line with right border of client area |
7147 |
// if offset is out of range. |
7218 |
// if offset is out of range. |
7148 |
if (offset > width - clientAreaWidth) { |
7219 |
if (offset > width - clientAreaWidth) { |
7149 |
offset = Math.max(0, width - clientAreaWidth); |
7220 |
offset = Math.max(0, width - clientAreaWidth); |
7150 |
} |
7221 |
} |
7151 |
} |
7222 |
} |
7152 |
scrollHorizontalBar(offset - horizontalScrollOffset); |
7223 |
scrollHorizontalBar(offset - horizontalScrollOffset); |
7153 |
} |
7224 |
} |
7154 |
/** |
7225 |
/** |
7155 |
* Sets the horizontal pixel offset relative to the start of the line. |
7226 |
* Sets the horizontal pixel offset relative to the start of the line. |
7156 |
* Do nothing if there is no text set. |
7227 |
* Do nothing if there is no text set. |
7157 |
* <p> |
7228 |
* <p> |
7158 |
* <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text |
7229 |
* <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text |
7159 |
* is set in the widget. |
7230 |
* is set in the widget. |
7160 |
* </p> |
7231 |
* </p> |
7161 |
* |
7232 |
* |
7162 |
* @param pixel horizontal pixel offset relative to the start |
7233 |
* @param pixel horizontal pixel offset relative to the start |
7163 |
* of the line. |
7234 |
* of the line. |
7164 |
* @exception SWTException <ul> |
7235 |
* @exception SWTException <ul> |
7165 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7236 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7166 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7237 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
Lines 7168-7252
Link Here
|
7168 |
* @since 2.0 |
7239 |
* @since 2.0 |
7169 |
*/ |
7240 |
*/ |
7170 |
public void setHorizontalPixel(int pixel) { |
7241 |
public void setHorizontalPixel(int pixel) { |
7171 |
checkWidget(); |
7242 |
checkWidget(); |
7172 |
int clientAreaWidth = getClientArea().width; |
7243 |
int clientAreaWidth = getClientArea().width; |
7173 |
if (getCharCount() == 0) { |
7244 |
if (getCharCount() == 0) { |
7174 |
return; |
7245 |
return; |
7175 |
} |
7246 |
} |
7176 |
if (pixel < 0) { |
7247 |
if (pixel < 0) { |
7177 |
pixel = 0; |
7248 |
pixel = 0; |
7178 |
} |
7249 |
} |
7179 |
// allow any value if client area width is unknown or 0. |
7250 |
// allow any value if client area width is unknown or 0. |
7180 |
// offset will be checked in resize handler. |
7251 |
// offset will be checked in resize handler. |
7181 |
// don't use isVisible since width is known even if widget |
7252 |
// don't use isVisible since width is known even if widget |
7182 |
// is temporarily invisible |
7253 |
// is temporarily invisible |
7183 |
if (clientAreaWidth > 0) { |
7254 |
if (clientAreaWidth > 0) { |
7184 |
int width = lineCache.getWidth(); |
7255 |
int width = lineCache.getWidth(); |
7185 |
// prevent scrolling if the content fits in the client area. |
7256 |
// prevent scrolling if the content fits in the client area. |
7186 |
// align end of longest line with right border of client area |
7257 |
// align end of longest line with right border of client area |
7187 |
// if offset is out of range. |
7258 |
// if offset is out of range. |
7188 |
if (pixel > width - clientAreaWidth) { |
7259 |
if (pixel > width - clientAreaWidth) { |
7189 |
pixel = Math.max(0, width - clientAreaWidth); |
7260 |
pixel = Math.max(0, width - clientAreaWidth); |
7190 |
} |
7261 |
} |
7191 |
} |
7262 |
} |
7192 |
scrollHorizontalBar(pixel - horizontalScrollOffset); |
7263 |
scrollHorizontalBar(pixel - horizontalScrollOffset); |
7193 |
} |
7264 |
} |
7194 |
/** |
7265 |
/** |
7195 |
* Adjusts the maximum and the page size of the horizontal scroll bar |
7266 |
* Adjusts the maximum and the page size of the horizontal scroll bar |
7196 |
* to reflect content width changes. |
7267 |
* to reflect content width changes. |
7197 |
*/ |
7268 |
*/ |
7198 |
void setHorizontalScrollBar() { |
7269 |
void setHorizontalScrollBar() { |
7199 |
ScrollBar horizontalBar = getHorizontalBar(); |
7270 |
ScrollBar horizontalBar = getHorizontalBar(); |
7200 |
|
7271 |
|
7201 |
if (horizontalBar != null && horizontalBar.getVisible()) { |
7272 |
if (horizontalBar != null && horizontalBar.getVisible()) { |
7202 |
final int INACTIVE = 1; |
7273 |
final int INACTIVE = 1; |
7203 |
Rectangle clientArea = getClientArea(); |
7274 |
Rectangle clientArea = getClientArea(); |
7204 |
// only set the real values if the scroll bar can be used |
7275 |
// only set the real values if the scroll bar can be used |
7205 |
// (ie. because the thumb size is less than the scroll maximum) |
7276 |
// (ie. because the thumb size is less than the scroll maximum) |
7206 |
// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7277 |
// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7207 |
if (clientArea.width < lineCache.getWidth()) { |
7278 |
if (clientArea.width < lineCache.getWidth()) { |
7208 |
horizontalBar.setValues( |
7279 |
horizontalBar.setValues( |
7209 |
horizontalBar.getSelection(), |
7280 |
horizontalBar.getSelection(), |
7210 |
horizontalBar.getMinimum(), |
7281 |
horizontalBar.getMinimum(), |
7211 |
lineCache.getWidth(), // maximum |
7282 |
lineCache.getWidth(), // maximum |
7212 |
clientArea.width - leftMargin - rightMargin, // thumb size |
7283 |
clientArea.width - leftMargin - rightMargin, // thumb size |
7213 |
horizontalBar.getIncrement(), |
7284 |
horizontalBar.getIncrement(), |
7214 |
clientArea.width - leftMargin - rightMargin); // page size |
7285 |
clientArea.width - leftMargin - rightMargin); // page size |
7215 |
} |
7286 |
} |
7216 |
else |
7287 |
else |
7217 |
if (horizontalBar.getThumb() != INACTIVE || horizontalBar.getMaximum() != INACTIVE) { |
7288 |
if (horizontalBar.getThumb() != INACTIVE || horizontalBar.getMaximum() != INACTIVE) { |
7218 |
horizontalBar.setValues( |
7289 |
horizontalBar.setValues( |
7219 |
horizontalBar.getSelection(), |
7290 |
horizontalBar.getSelection(), |
7220 |
horizontalBar.getMinimum(), |
7291 |
horizontalBar.getMinimum(), |
7221 |
INACTIVE, |
7292 |
INACTIVE, |
7222 |
INACTIVE, |
7293 |
INACTIVE, |
7223 |
horizontalBar.getIncrement(), |
7294 |
horizontalBar.getIncrement(), |
7224 |
INACTIVE); |
7295 |
INACTIVE); |
7225 |
} |
7296 |
} |
7226 |
} |
7297 |
} |
7227 |
} |
7298 |
} |
7228 |
/** |
7299 |
/** |
7229 |
* Sets the background color of the specified lines. |
7300 |
* Sets the background color of the specified lines. |
7230 |
* The background color is drawn for the width of the widget. All |
7301 |
* The background color is drawn for the width of the widget. All |
7231 |
* line background colors are discarded when setText is called. |
7302 |
* line background colors are discarded when setText is called. |
7232 |
* The text background color if defined in a StyleRange overlays the |
7303 |
* The text background color if defined in a StyleRange overlays the |
7233 |
* line background color. Should not be called if a LineBackgroundListener |
7304 |
* line background color. Should not be called if a LineBackgroundListener |
7234 |
* has been set since the listener maintains the line backgrounds. |
7305 |
* has been set since the listener maintains the line backgrounds. |
7235 |
* <p> |
7306 |
* <p> |
7236 |
* Line background colors are maintained relative to the line text, not the |
7307 |
* Line background colors are maintained relative to the line text, not the |
7237 |
* line index that is specified in this method call. |
7308 |
* line index that is specified in this method call. |
7238 |
* During text changes, when entire lines are inserted or removed, the line |
7309 |
* During text changes, when entire lines are inserted or removed, the line |
7239 |
* background colors that are associated with the lines after the change |
7310 |
* background colors that are associated with the lines after the change |
7240 |
* will "move" with their respective text. An entire line is defined as |
7311 |
* will "move" with their respective text. An entire line is defined as |
7241 |
* extending from the first character on a line to the last and including the |
7312 |
* extending from the first character on a line to the last and including the |
7242 |
* line delimiter. |
7313 |
* line delimiter. |
7243 |
* </p> |
7314 |
* </p> |
7244 |
* <p> |
7315 |
* <p> |
7245 |
* When two lines are joined by deleting a line delimiter, the top line |
7316 |
* When two lines are joined by deleting a line delimiter, the top line |
7246 |
* background takes precedence and the color of the bottom line is deleted. |
7317 |
* background takes precedence and the color of the bottom line is deleted. |
7247 |
* For all other text changes line background colors will remain unchanged. |
7318 |
* For all other text changes line background colors will remain unchanged. |
7248 |
* </p> |
7319 |
* </p> |
7249 |
* |
7320 |
* |
7250 |
* @param startLine first line the color is applied to, 0 based |
7321 |
* @param startLine first line the color is applied to, 0 based |
7251 |
* @param lineCount number of lines the color applies to. |
7322 |
* @param lineCount number of lines the color applies to. |
7252 |
* @param background line background color |
7323 |
* @param background line background color |
Lines 7259-7345
Link Here
|
7259 |
* </ul> |
7330 |
* </ul> |
7260 |
*/ |
7331 |
*/ |
7261 |
public void setLineBackground(int startLine, int lineCount, Color background) { |
7332 |
public void setLineBackground(int startLine, int lineCount, Color background) { |
7262 |
checkWidget(); |
7333 |
checkWidget(); |
7263 |
int partialBottomIndex = getPartialBottomIndex(); |
7334 |
int partialBottomIndex = getPartialBottomIndex(); |
7264 |
|
7335 |
|
7265 |
// this API can not be used if the client is providing the line background |
7336 |
// this API can not be used if the client is providing the line background |
7266 |
if (userLineBackground) { |
7337 |
if (userLineBackground) { |
7267 |
return; |
7338 |
return; |
7268 |
} |
7339 |
} |
7269 |
if (startLine < 0 || startLine + lineCount > logicalContent.getLineCount()) { |
7340 |
if (startLine < 0 || startLine + lineCount > logicalContent.getLineCount()) { |
7270 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7341 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7271 |
} |
7342 |
} |
7272 |
defaultLineStyler.setLineBackground(startLine, lineCount, background); |
7343 |
defaultLineStyler.setLineBackground(startLine, lineCount, background); |
7273 |
// do nothing if redraw range is completely invisible |
7344 |
// do nothing if redraw range is completely invisible |
7274 |
if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { |
7345 |
if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { |
7275 |
return; |
7346 |
return; |
7276 |
} |
7347 |
} |
7277 |
// only redraw visible lines |
7348 |
// only redraw visible lines |
7278 |
if (startLine < topIndex) { |
7349 |
if (startLine < topIndex) { |
7279 |
lineCount -= topIndex - startLine; |
7350 |
lineCount -= topIndex - startLine; |
7280 |
startLine = topIndex; |
7351 |
startLine = topIndex; |
7281 |
} |
7352 |
} |
7282 |
if (startLine + lineCount - 1 > partialBottomIndex) { |
7353 |
if (startLine + lineCount - 1 > partialBottomIndex) { |
7283 |
lineCount = partialBottomIndex - startLine + 1; |
7354 |
lineCount = partialBottomIndex - startLine + 1; |
7284 |
} |
7355 |
} |
7285 |
startLine -= topIndex; |
7356 |
startLine -= topIndex; |
7286 |
super.redraw( |
7357 |
super.redraw( |
7287 |
leftMargin, startLine * lineHeight + topMargin, |
7358 |
leftMargin, startLine * lineHeight + topMargin, |
7288 |
getClientArea().width - leftMargin - rightMargin, lineCount * lineHeight, true); |
7359 |
getClientArea().width - leftMargin - rightMargin, lineCount * lineHeight, true); |
7289 |
} |
7360 |
} |
7290 |
/** |
7361 |
/** |
7291 |
* Flips selection anchor based on word selection direction. |
7362 |
* Flips selection anchor based on word selection direction. |
7292 |
*/ |
7363 |
*/ |
7293 |
void setMouseWordSelectionAnchor() { |
7364 |
void setMouseWordSelectionAnchor() { |
7294 |
if (mouseDoubleClick == false) { |
7365 |
if (mouseDoubleClick == false) { |
7295 |
return; |
7366 |
return; |
7296 |
} |
7367 |
} |
7297 |
if (caretOffset < doubleClickSelection.x) { |
7368 |
if (caretOffset < doubleClickSelection.x) { |
7298 |
selectionAnchor = doubleClickSelection.y; |
7369 |
selectionAnchor = doubleClickSelection.y; |
7299 |
} |
7370 |
} |
7300 |
else |
7371 |
else |
7301 |
if (caretOffset > doubleClickSelection.y) { |
7372 |
if (caretOffset > doubleClickSelection.y) { |
7302 |
selectionAnchor = doubleClickSelection.x; |
7373 |
selectionAnchor = doubleClickSelection.x; |
7303 |
} |
7374 |
} |
7304 |
} |
7375 |
} |
7305 |
/** |
7376 |
/** |
7306 |
* Adjusts the maximum and the page size of the scroll bars to |
7377 |
* Adjusts the maximum and the page size of the scroll bars to |
7307 |
* reflect content width/length changes. |
7378 |
* reflect content width/length changes. |
7308 |
*/ |
7379 |
*/ |
7309 |
void setScrollBars() { |
7380 |
void setScrollBars() { |
7310 |
ScrollBar verticalBar = getVerticalBar(); |
7381 |
ScrollBar verticalBar = getVerticalBar(); |
7311 |
|
7382 |
|
7312 |
if (verticalBar != null) { |
7383 |
if (verticalBar != null) { |
7313 |
Rectangle clientArea = getClientArea(); |
7384 |
Rectangle clientArea = getClientArea(); |
7314 |
final int INACTIVE = 1; |
7385 |
final int INACTIVE = 1; |
7315 |
int maximum = content.getLineCount() * getVerticalIncrement(); |
7386 |
int maximum = content.getLineCount() * getVerticalIncrement(); |
7316 |
|
7387 |
|
7317 |
// only set the real values if the scroll bar can be used |
7388 |
// only set the real values if the scroll bar can be used |
7318 |
// (ie. because the thumb size is less than the scroll maximum) |
7389 |
// (ie. because the thumb size is less than the scroll maximum) |
7319 |
// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7390 |
// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 |
7320 |
if (clientArea.height < maximum) { |
7391 |
if (clientArea.height < maximum) { |
7321 |
verticalBar.setValues( |
7392 |
verticalBar.setValues( |
7322 |
verticalBar.getSelection(), |
7393 |
verticalBar.getSelection(), |
7323 |
verticalBar.getMinimum(), |
7394 |
verticalBar.getMinimum(), |
7324 |
maximum, |
7395 |
maximum, |
7325 |
clientArea.height, // thumb size |
7396 |
clientArea.height, // thumb size |
7326 |
verticalBar.getIncrement(), |
7397 |
verticalBar.getIncrement(), |
7327 |
clientArea.height); // page size |
7398 |
clientArea.height); // page size |
7328 |
} |
7399 |
} |
7329 |
else |
7400 |
else |
7330 |
if (verticalBar.getThumb() != INACTIVE || verticalBar.getMaximum() != INACTIVE) { |
7401 |
if (verticalBar.getThumb() != INACTIVE || verticalBar.getMaximum() != INACTIVE) { |
7331 |
verticalBar.setValues( |
7402 |
verticalBar.setValues( |
7332 |
verticalBar.getSelection(), |
7403 |
verticalBar.getSelection(), |
7333 |
verticalBar.getMinimum(), |
7404 |
verticalBar.getMinimum(), |
7334 |
INACTIVE, |
7405 |
INACTIVE, |
7335 |
INACTIVE, |
7406 |
INACTIVE, |
7336 |
verticalBar.getIncrement(), |
7407 |
verticalBar.getIncrement(), |
7337 |
INACTIVE); |
7408 |
INACTIVE); |
7338 |
} |
7409 |
} |
7339 |
} |
7410 |
} |
7340 |
setHorizontalScrollBar(); |
7411 |
setHorizontalScrollBar(); |
7341 |
} |
7412 |
} |
7342 |
/** |
7413 |
/** |
7343 |
* Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). |
7414 |
* Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). |
7344 |
* <p> |
7415 |
* <p> |
7345 |
* |
7416 |
* |
Lines 7351-7374
Link Here
|
7351 |
* </ul> |
7422 |
* </ul> |
7352 |
* @exception IllegalArgumentException <ul> |
7423 |
* @exception IllegalArgumentException <ul> |
7353 |
* <li>ERROR_INVALID_RANGE when start is outside the widget content |
7424 |
* <li>ERROR_INVALID_RANGE when start is outside the widget content |
7354 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7425 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7355 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7426 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7356 |
* </ul> |
7427 |
* </ul> |
7357 |
*/ |
7428 |
*/ |
7358 |
public void setSelection(int start) { |
7429 |
public void setSelection(int start) { |
7359 |
// checkWidget test done in setSelectionRange |
7430 |
// checkWidget test done in setSelectionRange |
7360 |
setSelection(start, start); |
7431 |
setSelection(start, start); |
7361 |
} |
7432 |
} |
7362 |
/** |
7433 |
/** |
7363 |
* Sets the selection and scrolls it into view. |
7434 |
* Sets the selection and scrolls it into view. |
7364 |
* <p> |
7435 |
* <p> |
7365 |
* Indexing is zero based. Text selections are specified in terms of |
7436 |
* Indexing is zero based. Text selections are specified in terms of |
7366 |
* caret positions. In a text widget that contains N characters, there are |
7437 |
* caret positions. In a text widget that contains N characters, there are |
7367 |
* N+1 caret positions, ranging from 0..N |
7438 |
* N+1 caret positions, ranging from 0..N |
7368 |
* </p> |
7439 |
* </p> |
7369 |
* |
7440 |
* |
7370 |
* @param point x=selection start offset, y=selection end offset |
7441 |
* @param point x=selection start offset, y=selection end offset |
7371 |
* The caret will be placed at the selection start when x > y. |
7442 |
* The caret will be placed at the selection start when x > y. |
7372 |
* @see #setSelection(int,int) |
7443 |
* @see #setSelection(int,int) |
7373 |
* @exception SWTException <ul> |
7444 |
* @exception SWTException <ul> |
7374 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7445 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 7377-7390
Link Here
|
7377 |
* @exception IllegalArgumentException <ul> |
7448 |
* @exception IllegalArgumentException <ul> |
7378 |
* <li>ERROR_NULL_ARGUMENT when point is null</li> |
7449 |
* <li>ERROR_NULL_ARGUMENT when point is null</li> |
7379 |
* <li>ERROR_INVALID_RANGE when start or end is outside the widget content |
7450 |
* <li>ERROR_INVALID_RANGE when start or end is outside the widget content |
7380 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7451 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7381 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7452 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7382 |
* </ul> |
7453 |
* </ul> |
7383 |
*/ |
7454 |
*/ |
7384 |
public void setSelection(Point point) { |
7455 |
public void setSelection(Point point) { |
7385 |
checkWidget(); |
7456 |
checkWidget(); |
7386 |
if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); |
7457 |
if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); |
7387 |
setSelection(point.x, point.y); |
7458 |
setSelection(point.x, point.y); |
7388 |
} |
7459 |
} |
7389 |
/** |
7460 |
/** |
7390 |
* Sets the receiver's selection background color to the color specified |
7461 |
* Sets the receiver's selection background color to the color specified |
Lines 7394-7400
Link Here
|
7394 |
* @param color the new color (or null) |
7465 |
* @param color the new color (or null) |
7395 |
* |
7466 |
* |
7396 |
* @exception IllegalArgumentException <ul> |
7467 |
* @exception IllegalArgumentException <ul> |
7397 |
* <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7468 |
* <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7398 |
* </ul> |
7469 |
* </ul> |
7399 |
* @exception SWTException <ul> |
7470 |
* @exception SWTException <ul> |
7400 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7471 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 7403-7415
Link Here
|
7403 |
* @since 2.1 |
7474 |
* @since 2.1 |
7404 |
*/ |
7475 |
*/ |
7405 |
public void setSelectionBackground (Color color) { |
7476 |
public void setSelectionBackground (Color color) { |
7406 |
checkWidget (); |
7477 |
checkWidget (); |
7407 |
if (color != null) { |
7478 |
if (color != null) { |
7408 |
if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7479 |
if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7409 |
} |
7480 |
} |
7410 |
selectionBackground = color; |
7481 |
selectionBackground = color; |
7411 |
redraw(); |
7482 |
redraw(); |
7412 |
} |
7483 |
} |
7413 |
/** |
7484 |
/** |
7414 |
* Sets the receiver's selection foreground color to the color specified |
7485 |
* Sets the receiver's selection foreground color to the color specified |
7415 |
* by the argument, or to the default system color for the control |
7486 |
* by the argument, or to the default system color for the control |
Lines 7418-7424
Link Here
|
7418 |
* @param color the new color (or null) |
7489 |
* @param color the new color (or null) |
7419 |
* |
7490 |
* |
7420 |
* @exception IllegalArgumentException <ul> |
7491 |
* @exception IllegalArgumentException <ul> |
7421 |
* <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7492 |
* <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> |
7422 |
* </ul> |
7493 |
* </ul> |
7423 |
* @exception SWTException <ul> |
7494 |
* @exception SWTException <ul> |
7424 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7495 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 7427-7449
Link Here
|
7427 |
* @since 2.1 |
7498 |
* @since 2.1 |
7428 |
*/ |
7499 |
*/ |
7429 |
public void setSelectionForeground (Color color) { |
7500 |
public void setSelectionForeground (Color color) { |
7430 |
checkWidget (); |
7501 |
checkWidget (); |
7431 |
if (color != null) { |
7502 |
if (color != null) { |
7432 |
if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7503 |
if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7433 |
} |
7504 |
} |
7434 |
selectionForeground = color; |
7505 |
selectionForeground = color; |
7435 |
redraw(); |
7506 |
redraw(); |
7436 |
} |
7507 |
} |
7437 |
/** |
7508 |
/** |
7438 |
* Sets the selection and scrolls it into view. |
7509 |
* Sets the selection and scrolls it into view. |
7439 |
* <p> |
7510 |
* <p> |
7440 |
* Indexing is zero based. Text selections are specified in terms of |
7511 |
* Indexing is zero based. Text selections are specified in terms of |
7441 |
* caret positions. In a text widget that contains N characters, there are |
7512 |
* caret positions. In a text widget that contains N characters, there are |
7442 |
* N+1 caret positions, ranging from 0..N |
7513 |
* N+1 caret positions, ranging from 0..N |
7443 |
* </p> |
7514 |
* </p> |
7444 |
* |
7515 |
* |
7445 |
* @param start selection start offset. The caret will be placed at the |
7516 |
* @param start selection start offset. The caret will be placed at the |
7446 |
* selection start when start > end. |
7517 |
* selection start when start > end. |
7447 |
* @param end selection end offset |
7518 |
* @param end selection end offset |
7448 |
* @see #setSelectionRange(int,int) |
7519 |
* @see #setSelectionRange(int,int) |
7449 |
* @exception SWTException <ul> |
7520 |
* @exception SWTException <ul> |
Lines 7452-7551
Link Here
|
7452 |
* </ul> |
7523 |
* </ul> |
7453 |
* @exception IllegalArgumentException <ul> |
7524 |
* @exception IllegalArgumentException <ul> |
7454 |
* <li>ERROR_INVALID_RANGE when start or end is outside the widget content |
7525 |
* <li>ERROR_INVALID_RANGE when start or end is outside the widget content |
7455 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7526 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7456 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7527 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7457 |
* </ul> |
7528 |
* </ul> |
7458 |
*/ |
7529 |
*/ |
7459 |
public void setSelection(int start, int end) { |
7530 |
public void setSelection(int start, int end) { |
7460 |
// checkWidget test done in setSelectionRange |
7531 |
// checkWidget test done in setSelectionRange |
7461 |
setSelectionRange(start, end - start); |
7532 |
setSelectionRange(start, end - start); |
7462 |
showSelection(); |
7533 |
showSelection(); |
7463 |
} |
7534 |
} |
7464 |
/** |
7535 |
/** |
7465 |
* Sets the selection. The new selection may not be visible. Call showSelection to scroll |
7536 |
* Sets the selection. The new selection may not be visible. Call showSelection to scroll |
7466 |
* the selection into view. |
7537 |
* the selection into view. |
7467 |
* <p> |
7538 |
* <p> |
7468 |
* |
7539 |
* |
7469 |
* @param start offset of the first selected character, start >= 0 must be true. |
7540 |
* @param start offset of the first selected character, start >= 0 must be true. |
7470 |
* @param length number of characters to select, 0 <= start + length <= getCharCount() |
7541 |
* @param length number of characters to select, 0 <= start + length <= getCharCount() |
7471 |
* must be true. |
7542 |
* must be true. |
7472 |
* A negative length places the caret at the visual start of the selection. |
7543 |
* A negative length places the caret at the visual start of the selection. |
7473 |
* @exception SWTException <ul> |
7544 |
* @exception SWTException <ul> |
7474 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7545 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7475 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7546 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7476 |
* </ul> |
7547 |
* </ul> |
7477 |
* @exception IllegalArgumentException <ul> |
7548 |
* @exception IllegalArgumentException <ul> |
7478 |
* <li>ERROR_INVALID_RANGE when the range specified by start and length is outside the widget content |
7549 |
* <li>ERROR_INVALID_RANGE when the range specified by start and length is outside the widget content |
7479 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7550 |
* <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a |
7480 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7551 |
* multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) |
7481 |
* </ul> |
7552 |
* </ul> |
7482 |
*/ |
7553 |
*/ |
7483 |
public void setSelectionRange(int start, int length) { |
7554 |
public void setSelectionRange(int start, int length) { |
7484 |
checkWidget(); |
7555 |
checkWidget(); |
7485 |
int contentLength = getCharCount(); |
7556 |
int contentLength = getCharCount(); |
7486 |
int end = start + length; |
7557 |
int end = start + length; |
7487 |
|
7558 |
|
7488 |
if (start < 0 || end < 0 || start > contentLength || end > contentLength) { |
7559 |
if (start < 0 || end < 0 || start > contentLength || end > contentLength) { |
7489 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7560 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7490 |
} |
7561 |
} |
7491 |
if (isLineDelimiter(start) || isLineDelimiter(end)) { |
7562 |
if (isLineDelimiter(start) || isLineDelimiter(end)) { |
7492 |
// the start offset or end offset of the selection range is inside a |
7563 |
// the start offset or end offset of the selection range is inside a |
7493 |
// multi byte line delimiter. This is an illegal operation and an exception |
7564 |
// multi byte line delimiter. This is an illegal operation and an exception |
7494 |
// is thrown. Fixes 1GDKK3R |
7565 |
// is thrown. Fixes 1GDKK3R |
7495 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7566 |
SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
7496 |
} |
7567 |
} |
7497 |
internalSetSelection(start, length, false); |
7568 |
internalSetSelection(start, length, false); |
7498 |
// always update the caret location. fixes 1G8FODP |
7569 |
// always update the caret location. fixes 1G8FODP |
7499 |
setCaretLocation(); |
7570 |
setCaretLocation(); |
7500 |
if (isBidi()) { |
7571 |
if (isBidi()) { |
7501 |
setBidiKeyboardLanguage(); |
7572 |
setBidiKeyboardLanguage(); |
7502 |
} |
7573 |
} |
7503 |
} |
7574 |
} |
7504 |
/** |
7575 |
/** |
7505 |
* Sets the selection. |
7576 |
* Sets the selection. |
7506 |
* The new selection may not be visible. Call showSelection to scroll |
7577 |
* The new selection may not be visible. Call showSelection to scroll |
7507 |
* the selection into view. |
7578 |
* the selection into view. |
7508 |
* <p> |
7579 |
* <p> |
7509 |
* |
7580 |
* |
7510 |
* @param start offset of the first selected character, start >= 0 must be true. |
7581 |
* @param start offset of the first selected character, start >= 0 must be true. |
7511 |
* @param length number of characters to select, 0 <= start + length |
7582 |
* @param length number of characters to select, 0 <= start + length |
7512 |
* <= getCharCount() must be true. |
7583 |
* <= getCharCount() must be true. |
7513 |
* A negative length places the caret at the selection start. |
7584 |
* A negative length places the caret at the selection start. |
7514 |
* @param sendEvent a Selection event is sent when set to true and when |
7585 |
* @param sendEvent a Selection event is sent when set to true and when |
7515 |
* the selection is reset. |
7586 |
* the selection is reset. |
7516 |
*/ |
7587 |
*/ |
7517 |
void internalSetSelection(int start, int length, boolean sendEvent) { |
7588 |
void internalSetSelection(int start, int length, boolean sendEvent) { |
7518 |
int end = start + length; |
7589 |
int end = start + length; |
7519 |
|
7590 |
|
7520 |
if (start > end) { |
7591 |
if (start > end) { |
7521 |
int temp = end; |
7592 |
int temp = end; |
7522 |
end = start; |
7593 |
end = start; |
7523 |
start = temp; |
7594 |
start = temp; |
7524 |
} |
7595 |
} |
7525 |
// is the selection range different or is the selection direction |
7596 |
// is the selection range different or is the selection direction |
7526 |
// different? |
7597 |
// different? |
7527 |
if (selection.x != start || selection.y != end || |
7598 |
if (selection.x != start || selection.y != end || |
7528 |
(length > 0 && selectionAnchor != selection.x) || |
7599 |
(length > 0 && selectionAnchor != selection.x) || |
7529 |
(length < 0 && selectionAnchor != selection.y)) { |
7600 |
(length < 0 && selectionAnchor != selection.y)) { |
7530 |
clearSelection(sendEvent); |
7601 |
clearSelection(sendEvent); |
7531 |
if (length < 0) { |
7602 |
if (length < 0) { |
7532 |
selectionAnchor = selection.y = end; |
7603 |
selectionAnchor = selection.y = end; |
7533 |
caretOffset = selection.x = start; |
7604 |
caretOffset = selection.x = start; |
7534 |
} |
7605 |
} |
7535 |
else { |
7606 |
else { |
7536 |
selectionAnchor = selection.x = start; |
7607 |
selectionAnchor = selection.x = start; |
7537 |
caretOffset = selection.y = end; |
7608 |
caretOffset = selection.y = end; |
7538 |
} |
7609 |
} |
7539 |
internalRedrawRange(selection.x, selection.y - selection.x, true); |
7610 |
internalRedrawRange(selection.x, selection.y - selection.x, true); |
7540 |
} |
7611 |
} |
|
|
7612 |
// see if we need to update the mouse pointer |
7613 |
internalSetCursor(); |
7614 |
} |
7615 |
/** |
7616 |
* Sets the mouse pointer based on whether it is over a selection and whether |
7617 |
* a custom cursor has been set. |
7618 |
*/ |
7619 |
void internalSetCursor() { |
7620 |
Point pos = this.toControl(getDisplay().getCursorLocation()); |
7621 |
internalSetCursor(pos.x, pos.y); |
7622 |
} |
7623 |
/** |
7624 |
* Sets the mouse pointer based on whether it is over a selection and whether |
7625 |
* a custom cursor has been set. |
7626 |
* |
7627 |
* @param x mouse x position in client coordinates |
7628 |
* @param y mouse y position in client coordinates |
7629 |
*/ |
7630 |
void internalSetCursor(int x, int y) { |
7631 |
int mouseLineIndex = (y + verticalScrollOffset) / lineHeight; |
7632 |
|
7633 |
if (mouseLineIndex < 0 || mouseLineIndex > content.getLineCount() - 1) { |
7634 |
// mouse is above or below content, set ibeam/custom cursor |
7635 |
Cursor cursor = (customCursor != null) ? customCursor : ibeamCursor; |
7636 |
if (!currentCursor.equals(cursor)) { |
7637 |
currentCursor = cursor; |
7638 |
super.setCursor(cursor); |
7639 |
} |
7640 |
} else { |
7641 |
if (isMouseOverSelection(x, y)) { |
7642 |
// mouse is over a selection, set arrow cursor |
7643 |
if (!currentCursor.equals(arrowCursor)) { |
7644 |
currentCursor = arrowCursor; |
7645 |
super.setCursor(arrowCursor); |
7646 |
} |
7647 |
} else { |
7648 |
Cursor cursor = (customCursor != null) ? customCursor : ibeamCursor; |
7649 |
// mouse is not over a selection, set ibeam/custom cursor |
7650 |
if (!currentCursor.equals(cursor)) { |
7651 |
currentCursor = cursor; |
7652 |
super.setCursor(cursor); |
7653 |
} |
7654 |
} |
7655 |
} |
7541 |
} |
7656 |
} |
7542 |
/** |
7657 |
/** |
7543 |
* Adds the specified style. The new style overwrites existing styles for the |
7658 |
* Adds the specified style. The new style overwrites existing styles for the |
7544 |
* specified range. Existing style ranges are adjusted if they partially |
7659 |
* specified range. Existing style ranges are adjusted if they partially |
7545 |
* overlap with the new style, To clear an individual style, call setStyleRange |
7660 |
* overlap with the new style, To clear an individual style, call setStyleRange |
7546 |
* with a StyleRange that has null attributes. |
7661 |
* with a StyleRange that has null attributes. |
7547 |
* <p> |
7662 |
* <p> |
7548 |
* Should not be called if a LineStyleListener has been set since the |
7663 |
* Should not be called if a LineStyleListener has been set since the |
7549 |
* listener maintains the styles. |
7664 |
* listener maintains the styles. |
7550 |
* </p> |
7665 |
* </p> |
7551 |
* |
7666 |
* |
Lines 7557-7640
Link Here
|
7557 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7672 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7558 |
* </ul> |
7673 |
* </ul> |
7559 |
* @exception IllegalArgumentException <ul> |
7674 |
* @exception IllegalArgumentException <ul> |
7560 |
* <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> |
7675 |
* <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> |
7561 |
* </ul> |
7676 |
* </ul> |
7562 |
*/ |
7677 |
*/ |
7563 |
public void setStyleRange(StyleRange range) { |
7678 |
public void setStyleRange(StyleRange range) { |
7564 |
checkWidget(); |
7679 |
checkWidget(); |
7565 |
|
7680 |
|
7566 |
// this API can not be used if the client is providing the line styles |
7681 |
// this API can not be used if the client is providing the line styles |
7567 |
if (userLineStyle) { |
7682 |
if (userLineStyle) { |
7568 |
return; |
7683 |
return; |
7569 |
} |
7684 |
} |
7570 |
// check the range, make sure it falls within the range of the |
7685 |
// check the range, make sure it falls within the range of the |
7571 |
// text |
7686 |
// text |
7572 |
if (range != null && range.start + range.length > content.getCharCount()) { |
7687 |
if (range != null && range.start + range.length > content.getCharCount()) { |
7573 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7688 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7574 |
} |
7689 |
} |
7575 |
if (range != null) { |
7690 |
if (range != null) { |
7576 |
boolean redrawFirstLine = false; |
7691 |
boolean redrawFirstLine = false; |
7577 |
boolean redrawLastLine = false; |
7692 |
boolean redrawLastLine = false; |
7578 |
int firstLine = content.getLineAtOffset(range.start); |
7693 |
int firstLine = content.getLineAtOffset(range.start); |
7579 |
int lastLine = content.getLineAtOffset(range.start + range.length); |
7694 |
int lastLine = content.getLineAtOffset(range.start + range.length); |
7580 |
|
7695 |
|
7581 |
// if the style is not visible, there is no need to redraw |
7696 |
// if the style is not visible, there is no need to redraw |
7582 |
boolean redrawLines = isAreaVisible(firstLine, lastLine); |
7697 |
boolean redrawLines = isAreaVisible(firstLine, lastLine); |
7583 |
|
7698 |
|
7584 |
if (!redrawLines) { |
7699 |
if (!redrawLines) { |
7585 |
defaultLineStyler.setStyleRange(range); |
7700 |
defaultLineStyler.setStyleRange(range); |
7586 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7701 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7587 |
} else { |
7702 |
} else { |
7588 |
// the first and last line needs to be redrawn completely if the |
7703 |
// the first and last line needs to be redrawn completely if the |
7589 |
// font style is changing from SWT.NORMAL to something else or |
7704 |
// font style is changing from SWT.NORMAL to something else or |
7590 |
// vice versa. fixes 1G7M5WE. |
7705 |
// vice versa. fixes 1G7M5WE. |
7591 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
7706 |
int firstLineOffset = content.getOffsetAtLine(firstLine); |
7592 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
7707 |
int lastLineOffset = content.getOffsetAtLine(lastLine); |
7593 |
if (isBidi()) { |
7708 |
if (isBidi()) { |
7594 |
if (firstLine != lastLine) { |
7709 |
if (firstLine != lastLine) { |
7595 |
redrawFirstLine = true; |
7710 |
redrawFirstLine = true; |
7596 |
} |
7711 |
} |
7597 |
redrawLastLine = true; |
7712 |
redrawLastLine = true; |
7598 |
} else { |
7713 |
} else { |
7599 |
redrawFirstLine = isRedrawFirstLine(new StyleRange[] {range}, firstLine, firstLineOffset); |
7714 |
redrawFirstLine = isRedrawFirstLine(new StyleRange[] {range}, firstLine, firstLineOffset); |
7600 |
if (lastLine != firstLine) { |
7715 |
if (lastLine != firstLine) { |
7601 |
redrawLastLine = isRedrawLastLine(new StyleRange[] {range}, lastLine, lastLineOffset); |
7716 |
redrawLastLine = isRedrawLastLine(new StyleRange[] {range}, lastLine, lastLineOffset); |
7602 |
} |
7717 |
} |
7603 |
} |
7718 |
} |
7604 |
defaultLineStyler.setStyleRange(range); |
7719 |
defaultLineStyler.setStyleRange(range); |
7605 |
// reset all lines affected by the style change but let the redraw |
7720 |
// reset all lines affected by the style change but let the redraw |
7606 |
// recalculate only those that are visible. |
7721 |
// recalculate only those that are visible. |
7607 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7722 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7608 |
internalRedrawRange(range.start, range.length, true); |
7723 |
internalRedrawRange(range.start, range.length, true); |
7609 |
if (redrawFirstLine) { |
7724 |
if (redrawFirstLine) { |
7610 |
redrawLine(firstLine, range.start - firstLineOffset); |
7725 |
redrawLine(firstLine, range.start - firstLineOffset); |
7611 |
} |
7726 |
} |
7612 |
if (redrawLastLine) { |
7727 |
if (redrawLastLine) { |
7613 |
redrawLine(lastLine, 0); |
7728 |
redrawLine(lastLine, 0); |
7614 |
} |
7729 |
} |
7615 |
} |
7730 |
} |
7616 |
} else { |
7731 |
} else { |
7617 |
// clearing all styles |
7732 |
// clearing all styles |
7618 |
defaultLineStyler.setStyleRange(range); |
7733 |
defaultLineStyler.setStyleRange(range); |
7619 |
lineCache.reset(0, content.getLineCount(), false); |
7734 |
lineCache.reset(0, content.getLineCount(), false); |
7620 |
redraw(); |
7735 |
redraw(); |
7621 |
} |
7736 |
} |
7622 |
|
7737 |
|
7623 |
// make sure that the caret is positioned correctly. |
7738 |
// make sure that the caret is positioned correctly. |
7624 |
// caret location may change if font style changes. |
7739 |
// caret location may change if font style changes. |
7625 |
// fixes 1G8FODP |
7740 |
// fixes 1G8FODP |
7626 |
setCaretLocation(); |
7741 |
setCaretLocation(); |
7627 |
} |
7742 |
} |
7628 |
/** |
7743 |
/** |
7629 |
* Sets styles to be used for rendering the widget content. All styles |
7744 |
* Sets styles to be used for rendering the widget content. All styles |
7630 |
* in the widget will be replaced with the given set of styles. |
7745 |
* in the widget will be replaced with the given set of styles. |
7631 |
* <p> |
7746 |
* <p> |
7632 |
* Should not be called if a LineStyleListener has been set since the |
7747 |
* Should not be called if a LineStyleListener has been set since the |
7633 |
* listener maintains the styles. |
7748 |
* listener maintains the styles. |
7634 |
* </p> |
7749 |
* </p> |
7635 |
* |
7750 |
* |
7636 |
* @param ranges StyleRange objects containing the style information. |
7751 |
* @param ranges StyleRange objects containing the style information. |
7637 |
* The ranges should not overlap. The style rendering is undefined if |
7752 |
* The ranges should not overlap. The style rendering is undefined if |
7638 |
* the ranges do overlap. Must not be null. |
7753 |
* the ranges do overlap. Must not be null. |
7639 |
* @exception SWTException <ul> |
7754 |
* @exception SWTException <ul> |
7640 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7755 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
Lines 7642-7686
Link Here
|
7642 |
* </ul> |
7757 |
* </ul> |
7643 |
* @exception IllegalArgumentException <ul> |
7758 |
* @exception IllegalArgumentException <ul> |
7644 |
* <li>ERROR_NULL_ARGUMENT when listener is null</li> |
7759 |
* <li>ERROR_NULL_ARGUMENT when listener is null</li> |
7645 |
* <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> |
7760 |
* <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> |
7646 |
* </ul> |
7761 |
* </ul> |
7647 |
*/ |
7762 |
*/ |
7648 |
public void setStyleRanges(StyleRange[] ranges) { |
7763 |
public void setStyleRanges(StyleRange[] ranges) { |
7649 |
checkWidget(); |
7764 |
checkWidget(); |
7650 |
// this API can not be used if the client is providing the line styles |
7765 |
// this API can not be used if the client is providing the line styles |
7651 |
if (userLineStyle) { |
7766 |
if (userLineStyle) { |
7652 |
return; |
7767 |
return; |
7653 |
} |
7768 |
} |
7654 |
if (ranges == null) { |
7769 |
if (ranges == null) { |
7655 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7770 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7656 |
} |
7771 |
} |
7657 |
// check the last range, make sure it falls within the range of the |
7772 |
// check the last range, make sure it falls within the range of the |
7658 |
// current text |
7773 |
// current text |
7659 |
if (ranges.length != 0) { |
7774 |
if (ranges.length != 0) { |
7660 |
StyleRange last = ranges[ranges.length-1]; |
7775 |
StyleRange last = ranges[ranges.length-1]; |
7661 |
int lastEnd = last.start + last.length; |
7776 |
int lastEnd = last.start + last.length; |
7662 |
int firstLine = content.getLineAtOffset(ranges[0].start); |
7777 |
int firstLine = content.getLineAtOffset(ranges[0].start); |
7663 |
int lastLine; |
7778 |
int lastLine; |
7664 |
if (lastEnd > content.getCharCount()) { |
7779 |
if (lastEnd > content.getCharCount()) { |
7665 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7780 |
SWT.error(SWT.ERROR_INVALID_RANGE); |
7666 |
} |
7781 |
} |
7667 |
lastLine = content.getLineAtOffset(lastEnd); |
7782 |
lastLine = content.getLineAtOffset(lastEnd); |
7668 |
// reset all lines affected by the style change |
7783 |
// reset all lines affected by the style change |
7669 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7784 |
lineCache.reset(firstLine, lastLine - firstLine + 1, true); |
7670 |
} |
7785 |
} |
7671 |
else { |
7786 |
else { |
7672 |
// reset all lines |
7787 |
// reset all lines |
7673 |
lineCache.reset(0, content.getLineCount(), false); |
7788 |
lineCache.reset(0, content.getLineCount(), false); |
7674 |
} |
7789 |
} |
7675 |
defaultLineStyler.setStyleRanges(ranges); |
7790 |
defaultLineStyler.setStyleRanges(ranges); |
7676 |
redraw(); // should only redraw affected area to avoid flashing |
7791 |
redraw(); // should only redraw affected area to avoid flashing |
7677 |
// make sure that the caret is positioned correctly. |
7792 |
// make sure that the caret is positioned correctly. |
7678 |
// caret location may change if font style changes. |
7793 |
// caret location may change if font style changes. |
7679 |
// fixes 1G8FODP |
7794 |
// fixes 1G8FODP |
7680 |
setCaretLocation(); |
7795 |
setCaretLocation(); |
7681 |
} |
7796 |
} |
7682 |
/** |
7797 |
/** |
7683 |
* Sets the tab width. |
7798 |
* Sets the tab width. |
7684 |
* <p> |
7799 |
* <p> |
7685 |
* |
7800 |
* |
7686 |
* @param tabs tab width measured in characters. |
7801 |
* @param tabs tab width measured in characters. |
Lines 7690-7726
Link Here
|
7690 |
* </ul> |
7805 |
* </ul> |
7691 |
*/ |
7806 |
*/ |
7692 |
public void setTabs(int tabs) { |
7807 |
public void setTabs(int tabs) { |
7693 |
checkWidget(); |
7808 |
checkWidget(); |
7694 |
tabLength = tabs; |
7809 |
tabLength = tabs; |
7695 |
renderer.setTabLength(tabLength); |
7810 |
renderer.setTabLength(tabLength); |
7696 |
if (caretOffset > 0) { |
7811 |
if (caretOffset > 0) { |
7697 |
caretOffset = 0; |
7812 |
caretOffset = 0; |
7698 |
if (isBidi()) { |
7813 |
if (isBidi()) { |
7699 |
showBidiCaret(); |
7814 |
showBidiCaret(); |
7700 |
} |
7815 |
} |
7701 |
else { |
7816 |
else { |
7702 |
showCaret(); |
7817 |
showCaret(); |
7703 |
} |
7818 |
} |
7704 |
clearSelection(false); |
7819 |
clearSelection(false); |
7705 |
} |
7820 |
} |
7706 |
// reset all line widths when the tab width changes |
7821 |
// reset all line widths when the tab width changes |
7707 |
lineCache.reset(0, content.getLineCount(), false); |
7822 |
lineCache.reset(0, content.getLineCount(), false); |
7708 |
redraw(); |
7823 |
redraw(); |
7709 |
} |
7824 |
} |
7710 |
/** |
7825 |
/** |
7711 |
* Sets the widget content. |
7826 |
* Sets the widget content. |
7712 |
* If the widget has the SWT.SINGLE style and "text" contains more than |
7827 |
* If the widget has the SWT.SINGLE style and "text" contains more than |
7713 |
* one line, only the first line is rendered but the text is stored |
7828 |
* one line, only the first line is rendered but the text is stored |
7714 |
* unchanged. A subsequent call to getText will return the same text |
7829 |
* unchanged. A subsequent call to getText will return the same text |
7715 |
* that was set. |
7830 |
* that was set. |
7716 |
* <p> |
7831 |
* <p> |
7717 |
* <b>Note:</b> Only a single line of text should be set when the SWT.SINGLE |
7832 |
* <b>Note:</b> Only a single line of text should be set when the SWT.SINGLE |
7718 |
* style is used. |
7833 |
* style is used. |
7719 |
* </p> |
7834 |
* </p> |
7720 |
* |
7835 |
* |
7721 |
* @param text new widget content. Replaces existing content. Line styles |
7836 |
* @param text new widget content. Replaces existing content. Line styles |
7722 |
* that were set using StyledText API are discarded. The |
7837 |
* that were set using StyledText API are discarded. The |
7723 |
* current selection is also discarded. |
7838 |
* current selection is also discarded. |
7724 |
* @exception SWTException <ul> |
7839 |
* @exception SWTException <ul> |
7725 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7840 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7726 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7841 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
Lines 7730-7761
Link Here
|
7730 |
* </ul> |
7845 |
* </ul> |
7731 |
*/ |
7846 |
*/ |
7732 |
public void setText(String text) { |
7847 |
public void setText(String text) { |
7733 |
checkWidget(); |
7848 |
checkWidget(); |
7734 |
Event event = new Event(); |
7849 |
Event event = new Event(); |
7735 |
|
7850 |
|
7736 |
if (text == null) { |
7851 |
if (text == null) { |
7737 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7852 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
7738 |
} |
7853 |
} |
7739 |
event.start = 0; |
7854 |
event.start = 0; |
7740 |
event.end = getCharCount(); |
7855 |
event.end = getCharCount(); |
7741 |
event.text = text; |
7856 |
event.text = text; |
7742 |
event.doit = true; |
7857 |
event.doit = true; |
7743 |
notifyListeners(SWT.Verify, event); |
7858 |
notifyListeners(SWT.Verify, event); |
7744 |
if (event.doit) { |
7859 |
if (event.doit) { |
7745 |
StyledTextEvent styledTextEvent = null; |
7860 |
StyledTextEvent styledTextEvent = null; |
7746 |
|
7861 |
|
7747 |
if (isListening(ExtendedModify)) { |
7862 |
if (isListening(ExtendedModify)) { |
7748 |
styledTextEvent = new StyledTextEvent(logicalContent); |
7863 |
styledTextEvent = new StyledTextEvent(logicalContent); |
7749 |
styledTextEvent.start = event.start; |
7864 |
styledTextEvent.start = event.start; |
7750 |
styledTextEvent.end = event.start + event.text.length(); |
7865 |
styledTextEvent.end = event.start + event.text.length(); |
7751 |
styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); |
7866 |
styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); |
7752 |
} |
7867 |
} |
7753 |
content.setText(event.text); |
7868 |
content.setText(event.text); |
7754 |
notifyListeners(SWT.Modify, event); |
7869 |
notifyListeners(SWT.Modify, event); |
7755 |
if (styledTextEvent != null) { |
7870 |
if (styledTextEvent != null) { |
7756 |
notifyListeners(ExtendedModify, styledTextEvent); |
7871 |
notifyListeners(ExtendedModify, styledTextEvent); |
7757 |
} |
7872 |
} |
7758 |
} |
7873 |
} |
7759 |
} |
7874 |
} |
7760 |
/** |
7875 |
/** |
7761 |
* Sets the text limit. |
7876 |
* Sets the text limit. |
Lines 7774-7823
Link Here
|
7774 |
* </ul> |
7889 |
* </ul> |
7775 |
*/ |
7890 |
*/ |
7776 |
public void setTextLimit(int limit) { |
7891 |
public void setTextLimit(int limit) { |
7777 |
checkWidget(); |
7892 |
checkWidget(); |
7778 |
if (limit == 0) { |
7893 |
if (limit == 0) { |
7779 |
SWT.error(SWT.ERROR_CANNOT_BE_ZERO); |
7894 |
SWT.error(SWT.ERROR_CANNOT_BE_ZERO); |
7780 |
} |
7895 |
} |
7781 |
textLimit = limit; |
7896 |
textLimit = limit; |
7782 |
} |
7897 |
} |
7783 |
/** |
7898 |
/** |
7784 |
* Sets the top index. Do nothing if there is no text set. |
7899 |
* Sets the top index. Do nothing if there is no text set. |
7785 |
* <p> |
7900 |
* <p> |
7786 |
* The top index is the index of the line that is currently at the top |
7901 |
* The top index is the index of the line that is currently at the top |
7787 |
* of the widget. The top index changes when the widget is scrolled. |
7902 |
* of the widget. The top index changes when the widget is scrolled. |
7788 |
* Indexing starts from zero. |
7903 |
* Indexing starts from zero. |
7789 |
* Note: The top index is reset to 0 when new text is set in the widget. |
7904 |
* Note: The top index is reset to 0 when new text is set in the widget. |
7790 |
* </p> |
7905 |
* </p> |
7791 |
* |
7906 |
* |
7792 |
* @param index new top index. Must be between 0 and |
7907 |
* @param index new top index. Must be between 0 and |
7793 |
* getLineCount() - fully visible lines per page. If no lines are fully |
7908 |
* getLineCount() - fully visible lines per page. If no lines are fully |
7794 |
* visible the maximum value is getLineCount() - 1. An out of range |
7909 |
* visible the maximum value is getLineCount() - 1. An out of range |
7795 |
* index will be adjusted accordingly. |
7910 |
* index will be adjusted accordingly. |
7796 |
* @exception SWTException <ul> |
7911 |
* @exception SWTException <ul> |
7797 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7912 |
* <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> |
7913 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7799 |
* </ul> |
7914 |
* </ul> |
7800 |
*/ |
7915 |
*/ |
7801 |
public void setTopIndex(int topIndex) { |
7916 |
public void setTopIndex(int topIndex) { |
7802 |
checkWidget(); |
7917 |
checkWidget(); |
7803 |
int lineCount = logicalContent.getLineCount(); |
7918 |
int lineCount = logicalContent.getLineCount(); |
7804 |
int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); |
7919 |
int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); |
7805 |
|
7920 |
|
7806 |
if (getCharCount() == 0) { |
7921 |
if (getCharCount() == 0) { |
7807 |
return; |
7922 |
return; |
7808 |
} |
7923 |
} |
7809 |
if (topIndex < 0) { |
7924 |
if (topIndex < 0) { |
7810 |
topIndex = 0; |
7925 |
topIndex = 0; |
7811 |
} |
7926 |
} |
7812 |
else |
7927 |
else |
7813 |
if (topIndex > lineCount - pageSize) { |
7928 |
if (topIndex > lineCount - pageSize) { |
7814 |
topIndex = lineCount - pageSize; |
7929 |
topIndex = lineCount - pageSize; |
7815 |
} |
7930 |
} |
7816 |
if (wordWrap) { |
7931 |
if (wordWrap) { |
7817 |
int logicalLineOffset = logicalContent.getOffsetAtLine(topIndex); |
7932 |
int logicalLineOffset = logicalContent.getOffsetAtLine(topIndex); |
7818 |
topIndex = content.getLineAtOffset(logicalLineOffset); |
7933 |
topIndex = content.getLineAtOffset(logicalLineOffset); |
7819 |
} |
7934 |
} |
7820 |
setVerticalScrollOffset(topIndex * getVerticalIncrement(), true); |
7935 |
setVerticalScrollOffset(topIndex * getVerticalIncrement(), true); |
7821 |
} |
7936 |
} |
7822 |
/** |
7937 |
/** |
7823 |
* Sets the top pixel offset. Do nothing if there is no text set. |
7938 |
* Sets the top pixel offset. Do nothing if there is no text set. |
Lines 7828-7836
Link Here
|
7828 |
* Note: The top pixel is reset to 0 when new text is set in the widget. |
7943 |
* Note: The top pixel is reset to 0 when new text is set in the widget. |
7829 |
* </p> |
7944 |
* </p> |
7830 |
* |
7945 |
* |
7831 |
* @param pixel new top pixel offset. Must be between 0 and |
7946 |
* @param pixel new top pixel offset. Must be between 0 and |
7832 |
* (getLineCount() - visible lines per page) / getLineHeight()). An out |
7947 |
* (getLineCount() - visible lines per page) / getLineHeight()). An out |
7833 |
* of range offset will be adjusted accordingly. |
7948 |
* of range offset will be adjusted accordingly. |
7834 |
* @exception SWTException <ul> |
7949 |
* @exception SWTException <ul> |
7835 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7950 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
7836 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
7951 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
Lines 7838-7967
Link Here
|
7838 |
* @since 2.0 |
7953 |
* @since 2.0 |
7839 |
*/ |
7954 |
*/ |
7840 |
public void setTopPixel(int pixel) { |
7955 |
public void setTopPixel(int pixel) { |
7841 |
checkWidget(); |
7956 |
checkWidget(); |
7842 |
int lineCount =content.getLineCount(); |
7957 |
int lineCount =content.getLineCount(); |
7843 |
int height = getClientArea().height; |
7958 |
int height = getClientArea().height; |
7844 |
int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); |
7959 |
int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); |
7845 |
|
7960 |
|
7846 |
if (getCharCount() == 0) { |
7961 |
if (getCharCount() == 0) { |
7847 |
return; |
7962 |
return; |
7848 |
} |
7963 |
} |
7849 |
if (pixel < 0) { |
7964 |
if (pixel < 0) { |
7850 |
pixel = 0; |
7965 |
pixel = 0; |
7851 |
} |
7966 |
} |
7852 |
else |
7967 |
else |
7853 |
if (pixel > maxTopPixel) { |
7968 |
if (pixel > maxTopPixel) { |
7854 |
pixel = maxTopPixel; |
7969 |
pixel = maxTopPixel; |
7855 |
} |
7970 |
} |
7856 |
setVerticalScrollOffset(pixel, true); |
7971 |
setVerticalScrollOffset(pixel, true); |
7857 |
} |
7972 |
} |
7858 |
/** |
7973 |
/** |
7859 |
* Scrolls the widget vertically. |
7974 |
* Scrolls the widget vertically. |
7860 |
* <p> |
7975 |
* <p> |
7861 |
* |
7976 |
* |
7862 |
* @param pixelOffset the new vertical scroll offset |
7977 |
* @param pixelOffset the new vertical scroll offset |
7863 |
* @param adjustScrollBar |
7978 |
* @param adjustScrollBar |
7864 |
* true= the scroll thumb will be moved to reflect the new scroll offset. |
7979 |
* true= the scroll thumb will be moved to reflect the new scroll offset. |
7865 |
* false = the scroll thumb will not be moved |
7980 |
* false = the scroll thumb will not be moved |
7866 |
* @return |
7981 |
* @return |
7867 |
* true=the widget was scrolled |
7982 |
* true=the widget was scrolled |
7868 |
* false=the widget was not scrolled, the given offset is not valid. |
7983 |
* false=the widget was not scrolled, the given offset is not valid. |
7869 |
*/ |
7984 |
*/ |
7870 |
boolean setVerticalScrollOffset(int pixelOffset, boolean adjustScrollBar) { |
7985 |
boolean setVerticalScrollOffset(int pixelOffset, boolean adjustScrollBar) { |
7871 |
Rectangle clientArea; |
7986 |
Rectangle clientArea; |
7872 |
ScrollBar verticalBar = getVerticalBar(); |
7987 |
ScrollBar verticalBar = getVerticalBar(); |
7873 |
|
7988 |
|
7874 |
if (pixelOffset == verticalScrollOffset) { |
7989 |
if (pixelOffset == verticalScrollOffset) { |
7875 |
return false; |
7990 |
return false; |
7876 |
} |
7991 |
} |
7877 |
if (verticalBar != null && adjustScrollBar) { |
7992 |
if (verticalBar != null && adjustScrollBar) { |
7878 |
verticalBar.setSelection(pixelOffset); |
7993 |
verticalBar.setSelection(pixelOffset); |
7879 |
} |
7994 |
} |
7880 |
clientArea = getClientArea(); |
7995 |
clientArea = getClientArea(); |
7881 |
scroll( |
7996 |
scroll( |
7882 |
0, 0, // destination x, y |
7997 |
0, 0, // destination x, y |
7883 |
0, pixelOffset - verticalScrollOffset, // source x, y |
7998 |
0, pixelOffset - verticalScrollOffset, // source x, y |
7884 |
clientArea.width, clientArea.height, true); |
7999 |
clientArea.width, clientArea.height, true); |
7885 |
|
8000 |
|
7886 |
verticalScrollOffset = pixelOffset; |
8001 |
verticalScrollOffset = pixelOffset; |
7887 |
calculateTopIndex(); |
8002 |
calculateTopIndex(); |
7888 |
setCaretLocation(); |
8003 |
setCaretLocation(); |
7889 |
return true; |
8004 |
return true; |
7890 |
} |
8005 |
} |
7891 |
/** |
8006 |
/** |
7892 |
* Scrolls the specified location into view. |
8007 |
* Scrolls the specified location into view. |
7893 |
* <p> |
8008 |
* <p> |
7894 |
* |
8009 |
* |
7895 |
* @param x the x coordinate that should be made visible. |
8010 |
* @param x the x coordinate that should be made visible. |
7896 |
* @param line the line that should be made visible. Relative to the |
8011 |
* @param line the line that should be made visible. Relative to the |
7897 |
* first line in the document. |
8012 |
* first line in the document. |
7898 |
* @return |
8013 |
* @return |
7899 |
* true=the widget was scrolled to make the specified location visible. |
8014 |
* true=the widget was scrolled to make the specified location visible. |
7900 |
* false=the specified location is already visible, the widget was |
8015 |
* false=the specified location is already visible, the widget was |
7901 |
* not scrolled. |
8016 |
* not scrolled. |
7902 |
*/ |
8017 |
*/ |
7903 |
boolean showLocation(int x, int line) { |
8018 |
boolean showLocation(int x, int line) { |
7904 |
int clientAreaWidth = getClientArea().width - leftMargin - rightMargin; |
8019 |
int clientAreaWidth = getClientArea().width - leftMargin - rightMargin; |
7905 |
int verticalIncrement = getVerticalIncrement(); |
8020 |
int verticalIncrement = getVerticalIncrement(); |
7906 |
int horizontalIncrement = clientAreaWidth / 4; |
8021 |
int horizontalIncrement = clientAreaWidth / 4; |
7907 |
boolean scrolled = false; |
8022 |
boolean scrolled = false; |
7908 |
|
8023 |
|
7909 |
if (x < leftMargin) { |
8024 |
if (x < leftMargin) { |
7910 |
// always make 1/4 of a page visible |
8025 |
// always make 1/4 of a page visible |
7911 |
x = Math.max(horizontalScrollOffset * -1, x - horizontalIncrement); |
8026 |
x = Math.max(horizontalScrollOffset * -1, x - horizontalIncrement); |
7912 |
scrolled = scrollHorizontalBar(x); |
8027 |
scrolled = scrollHorizontalBar(x); |
7913 |
} |
8028 |
} |
7914 |
else |
8029 |
else |
7915 |
if (x >= clientAreaWidth) { |
8030 |
if (x >= clientAreaWidth) { |
7916 |
// always make 1/4 of a page visible |
8031 |
// always make 1/4 of a page visible |
7917 |
x = Math.min(lineCache.getWidth() - horizontalScrollOffset, x + horizontalIncrement); |
8032 |
x = Math.min(lineCache.getWidth() - horizontalScrollOffset, x + horizontalIncrement); |
7918 |
scrolled = scrollHorizontalBar(x - clientAreaWidth); |
8033 |
scrolled = scrollHorizontalBar(x - clientAreaWidth); |
7919 |
} |
8034 |
} |
7920 |
if (line < topIndex) { |
8035 |
if (line < topIndex) { |
7921 |
scrolled = setVerticalScrollOffset(line * verticalIncrement, true); |
8036 |
scrolled = setVerticalScrollOffset(line * verticalIncrement, true); |
7922 |
} |
8037 |
} |
7923 |
else |
8038 |
else |
7924 |
if (line > getBottomIndex()) { |
8039 |
if (line > getBottomIndex()) { |
7925 |
scrolled = setVerticalScrollOffset((line + 1) * verticalIncrement - getClientArea().height, true); |
8040 |
scrolled = setVerticalScrollOffset((line + 1) * verticalIncrement - getClientArea().height, true); |
7926 |
} |
8041 |
} |
7927 |
return scrolled; |
8042 |
return scrolled; |
7928 |
} |
8043 |
} |
7929 |
/** |
8044 |
/** |
7930 |
* Sets the caret location and scrolls the caret offset into view. |
8045 |
* Sets the caret location and scrolls the caret offset into view. |
7931 |
*/ |
8046 |
*/ |
7932 |
void showCaret() { |
8047 |
void showCaret() { |
7933 |
int caretLine = content.getLineAtOffset(caretOffset); |
8048 |
int caretLine = content.getLineAtOffset(caretOffset); |
7934 |
|
8049 |
|
7935 |
showCaret(caretLine); |
8050 |
showCaret(caretLine); |
7936 |
} |
8051 |
} |
7937 |
/** |
8052 |
/** |
7938 |
* Sets the caret location and scrolls the caret offset into view. |
8053 |
* Sets the caret location and scrolls the caret offset into view. |
7939 |
*/ |
8054 |
*/ |
7940 |
void showCaret(int caretLine) { |
8055 |
void showCaret(int caretLine) { |
7941 |
int lineOffset = content.getOffsetAtLine(caretLine); |
8056 |
int lineOffset = content.getOffsetAtLine(caretLine); |
7942 |
String lineText = content.getLine(caretLine); |
8057 |
String lineText = content.getLine(caretLine); |
7943 |
int offsetInLine = caretOffset - lineOffset; |
8058 |
int offsetInLine = caretOffset - lineOffset; |
7944 |
int xAtOffset = getXAtOffset(lineText, caretLine, offsetInLine); |
8059 |
int xAtOffset = getXAtOffset(lineText, caretLine, offsetInLine); |
7945 |
boolean scrolled = showLocation(xAtOffset, caretLine); |
8060 |
boolean scrolled = showLocation(xAtOffset, caretLine); |
7946 |
boolean setWrapCaretLocation = false; |
8061 |
boolean setWrapCaretLocation = false; |
7947 |
Caret caret = getCaret(); |
8062 |
Caret caret = getCaret(); |
7948 |
|
8063 |
|
7949 |
if (wordWrap && caret != null) { |
8064 |
if (wordWrap && caret != null) { |
7950 |
int caretY = caret.getLocation().y; |
8065 |
int caretY = caret.getLocation().y; |
7951 |
if ((caretY + verticalScrollOffset) / getVerticalIncrement() - 1 != caretLine) { |
8066 |
if ((caretY + verticalScrollOffset) / getVerticalIncrement() - 1 != caretLine) { |
7952 |
setWrapCaretLocation = true; |
8067 |
setWrapCaretLocation = true; |
7953 |
} |
8068 |
} |
7954 |
} |
8069 |
} |
7955 |
if (scrolled == false || setWrapCaretLocation) { |
8070 |
if (scrolled == false || setWrapCaretLocation) { |
7956 |
// set the caret location if a scroll operation did not set it (as a |
8071 |
// set the caret location if a scroll operation did not set it (as a |
7957 |
// sideeffect of scrolling) or when in word wrap mode and the caret |
8072 |
// sideeffect of scrolling) or when in word wrap mode and the caret |
7958 |
// line was explicitly specified (i.e., because getWrapCaretLine does |
8073 |
// line was explicitly specified (i.e., because getWrapCaretLine does |
7959 |
// not return the desired line causing scrolling to not set it correctly) |
8074 |
// not return the desired line causing scrolling to not set it correctly) |
7960 |
setCaretLocation(xAtOffset, caretLine); |
8075 |
setCaretLocation(xAtOffset, caretLine); |
7961 |
} |
8076 |
} |
7962 |
if (isBidi()) { |
8077 |
if (isBidi()) { |
7963 |
setBidiKeyboardLanguage(); |
8078 |
setBidiKeyboardLanguage(); |
7964 |
} |
8079 |
} |
7965 |
} |
8080 |
} |
7966 |
/** |
8081 |
/** |
7967 |
* Scrolls the specified offset into view. |
8082 |
* Scrolls the specified offset into view. |
Lines 7970-7982
Link Here
|
7970 |
* @param offset offset that should be scolled into view |
8085 |
* @param offset offset that should be scolled into view |
7971 |
*/ |
8086 |
*/ |
7972 |
void showOffset(int offset) { |
8087 |
void showOffset(int offset) { |
7973 |
int line = content.getLineAtOffset(offset); |
8088 |
int line = content.getLineAtOffset(offset); |
7974 |
int lineOffset = content.getOffsetAtLine(line); |
8089 |
int lineOffset = content.getOffsetAtLine(line); |
7975 |
int offsetInLine = offset - lineOffset; |
8090 |
int offsetInLine = offset - lineOffset; |
7976 |
String lineText = content.getLine(line); |
8091 |
String lineText = content.getLine(line); |
7977 |
int xAtOffset = getXAtOffset(lineText, line, offsetInLine); |
8092 |
int xAtOffset = getXAtOffset(lineText, line, offsetInLine); |
7978 |
|
8093 |
|
7979 |
showLocation(xAtOffset, line); |
8094 |
showLocation(xAtOffset, line); |
7980 |
} |
8095 |
} |
7981 |
/** |
8096 |
/** |
7982 |
/** |
8097 |
/** |
Lines 7991-8082
Link Here
|
7991 |
* </ul> |
8106 |
* </ul> |
7992 |
*/ |
8107 |
*/ |
7993 |
public void showSelection() { |
8108 |
public void showSelection() { |
7994 |
checkWidget(); |
8109 |
checkWidget(); |
7995 |
boolean selectionFits; |
8110 |
boolean selectionFits; |
7996 |
int startOffset, startLine, startX, endOffset, endLine, endX, offsetInLine; |
8111 |
int startOffset, startLine, startX, endOffset, endLine, endX, offsetInLine; |
7997 |
|
8112 |
|
7998 |
// is selection from right-to-left? |
8113 |
// is selection from right-to-left? |
7999 |
boolean rightToLeft = caretOffset == selection.x; |
8114 |
boolean rightToLeft = caretOffset == selection.x; |
8000 |
|
8115 |
|
8001 |
if (rightToLeft) { |
8116 |
if (rightToLeft) { |
8002 |
startOffset = selection.y; |
8117 |
startOffset = selection.y; |
8003 |
endOffset = selection.x; |
8118 |
endOffset = selection.x; |
8004 |
} else { |
8119 |
} else { |
8005 |
startOffset = selection.x; |
8120 |
startOffset = selection.x; |
8006 |
endOffset = selection.y; |
8121 |
endOffset = selection.y; |
8007 |
} |
8122 |
} |
8008 |
|
8123 |
|
8009 |
// calculate the logical start and end values for the selection |
8124 |
// calculate the logical start and end values for the selection |
8010 |
startLine = content.getLineAtOffset(startOffset); |
8125 |
startLine = content.getLineAtOffset(startOffset); |
8011 |
offsetInLine = startOffset - content.getOffsetAtLine(startLine); |
8126 |
offsetInLine = startOffset - content.getOffsetAtLine(startLine); |
8012 |
startX = getXAtOffset(content.getLine(startLine), startLine, offsetInLine); |
8127 |
startX = getXAtOffset(content.getLine(startLine), startLine, offsetInLine); |
8013 |
endLine = content.getLineAtOffset(endOffset); |
8128 |
endLine = content.getLineAtOffset(endOffset); |
8014 |
offsetInLine = endOffset - content.getOffsetAtLine(endLine); |
8129 |
offsetInLine = endOffset - content.getOffsetAtLine(endLine); |
8015 |
endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); |
8130 |
endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); |
8016 |
|
8131 |
|
8017 |
// can the selection be fully displayed within the widget's visible width? |
8132 |
// can the selection be fully displayed within the widget's visible width? |
8018 |
int w = getClientArea().width; |
8133 |
int w = getClientArea().width; |
8019 |
if (rightToLeft) { |
8134 |
if (rightToLeft) { |
8020 |
selectionFits = startX - endX <= w; |
8135 |
selectionFits = startX - endX <= w; |
8021 |
} else { |
8136 |
} else { |
8022 |
selectionFits = endX - startX <= w; |
8137 |
selectionFits = endX - startX <= w; |
8023 |
} |
8138 |
} |
8024 |
|
8139 |
|
8025 |
if (selectionFits) { |
8140 |
if (selectionFits) { |
8026 |
// show as much of the selection as possible by first showing |
8141 |
// show as much of the selection as possible by first showing |
8027 |
// the start of the selection |
8142 |
// the start of the selection |
8028 |
showLocation(startX, startLine); |
8143 |
showLocation(startX, startLine); |
8029 |
// endX value could change if showing startX caused a scroll to occur |
8144 |
// endX value could change if showing startX caused a scroll to occur |
8030 |
endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); |
8145 |
endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); |
8031 |
showLocation(endX, endLine); |
8146 |
showLocation(endX, endLine); |
8032 |
} else { |
8147 |
} else { |
8033 |
// just show the end of the selection since the selection start |
8148 |
// just show the end of the selection since the selection start |
8034 |
// will not be visible |
8149 |
// will not be visible |
8035 |
showLocation(endX, endLine); |
8150 |
showLocation(endX, endLine); |
8036 |
} |
8151 |
} |
8037 |
} |
8152 |
} |
8038 |
/** |
8153 |
/** |
8039 |
* Updates the caret direction when a delete operation occured based on |
8154 |
* Updates the caret direction when a delete operation occured based on |
8040 |
* the type of the delete operation (next/previous character) and the |
8155 |
* the type of the delete operation (next/previous character) and the |
8041 |
* caret location (at a direction boundary or inside a direction segment). |
8156 |
* caret location (at a direction boundary or inside a direction segment). |
8042 |
* The intent is to place the caret at the visual location where a |
8157 |
* The intent is to place the caret at the visual location where a |
8043 |
* character was deleted. |
8158 |
* character was deleted. |
8044 |
* <p> |
8159 |
* <p> |
8045 |
* |
8160 |
* |
8046 |
* @param isBackspace true=the previous character was deleted, false=the |
8161 |
* @param isBackspace true=the previous character was deleted, false=the |
8047 |
* character next to the caret location was deleted |
8162 |
* character next to the caret location was deleted |
8048 |
* @param isDirectionBoundary true=the caret is between a R2L and L2R segment, |
8163 |
* @param isDirectionBoundary true=the caret is between a R2L and L2R segment, |
8049 |
* false=the caret is within a direction segment |
8164 |
* false=the caret is within a direction segment |
8050 |
*/ |
8165 |
*/ |
8051 |
void updateBidiDirection(boolean isBackspace, boolean isDirectionBoundary) { |
8166 |
void updateBidiDirection(boolean isBackspace, boolean isDirectionBoundary) { |
8052 |
if (isDirectionBoundary) { |
8167 |
if (isDirectionBoundary) { |
8053 |
if (isBackspace) { |
8168 |
if (isBackspace) { |
8054 |
// Deleted previous character (backspace) at a direction boundary |
8169 |
// Deleted previous character (backspace) at a direction boundary |
8055 |
// Go to direction segment of deleted character |
8170 |
// Go to direction segment of deleted character |
8056 |
lastCaretDirection = ST.COLUMN_NEXT; |
8171 |
lastCaretDirection = ST.COLUMN_NEXT; |
8057 |
} |
8172 |
} |
8058 |
else { |
8173 |
else { |
8059 |
// Deleted next character. Go to direction segment of deleted character |
8174 |
// Deleted next character. Go to direction segment of deleted character |
8060 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
8175 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
8061 |
} |
8176 |
} |
8062 |
} |
8177 |
} |
8063 |
else { |
8178 |
else { |
8064 |
if (isBackspace) { |
8179 |
if (isBackspace) { |
8065 |
// Delete previous character inside direction segment (i.e., not at a direction boundary) |
8180 |
// Delete previous character inside direction segment (i.e., not at a direction boundary) |
8066 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
8181 |
lastCaretDirection = ST.COLUMN_PREVIOUS; |
8067 |
} |
8182 |
} |
8068 |
else { |
8183 |
else { |
8069 |
// Deleted next character. |
8184 |
// Deleted next character. |
8070 |
lastCaretDirection = ST.COLUMN_NEXT; |
8185 |
lastCaretDirection = ST.COLUMN_NEXT; |
8071 |
} |
8186 |
} |
8072 |
} |
8187 |
} |
8073 |
} |
8188 |
} |
8074 |
/** |
8189 |
/** |
8075 |
* Updates the selection and caret position depending on the text change. |
8190 |
* Updates the selection and caret position depending on the text change. |
8076 |
* If the selection intersects with the replaced text, the selection is |
8191 |
* If the selection intersects with the replaced text, the selection is |
8077 |
* reset and the caret moved to the end of the new text. |
8192 |
* reset and the caret moved to the end of the new text. |
8078 |
* If the selection is behind the replaced text it is moved so that the |
8193 |
* If the selection is behind the replaced text it is moved so that the |
8079 |
* same text remains selected. If the selection is before the replaced text |
8194 |
* same text remains selected. If the selection is before the replaced text |
8080 |
* it is left unchanged. |
8195 |
* it is left unchanged. |
8081 |
* <p> |
8196 |
* <p> |
8082 |
* |
8197 |
* |
Lines 8085-8170
Link Here
|
8085 |
* @param newLength length of new text |
8200 |
* @param newLength length of new text |
8086 |
*/ |
8201 |
*/ |
8087 |
void updateSelection(int startOffset, int replacedLength, int newLength) { |
8202 |
void updateSelection(int startOffset, int replacedLength, int newLength) { |
8088 |
if (selection.y <= startOffset) { |
8203 |
if (selection.y <= startOffset) { |
8089 |
// selection ends before text change |
8204 |
// selection ends before text change |
8090 |
return; |
8205 |
return; |
8091 |
} |
8206 |
} |
8092 |
if (selection.x < startOffset) { |
8207 |
if (selection.x < startOffset) { |
8093 |
// clear selection fragment before text change |
8208 |
// clear selection fragment before text change |
8094 |
internalRedrawRange(selection.x, startOffset - selection.x, true); |
8209 |
internalRedrawRange(selection.x, startOffset - selection.x, true); |
8095 |
} |
8210 |
} |
8096 |
if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { |
8211 |
if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { |
8097 |
// clear selection fragment after text change. |
8212 |
// clear selection fragment after text change. |
8098 |
// do this only when the selection is actually affected by the |
8213 |
// do this only when the selection is actually affected by the |
8099 |
// change. Selection is only affected if it intersects the change (1GDY217). |
8214 |
// change. Selection is only affected if it intersects the change (1GDY217). |
8100 |
int netNewLength = newLength - replacedLength; |
8215 |
int netNewLength = newLength - replacedLength; |
8101 |
int redrawStart = startOffset + newLength; |
8216 |
int redrawStart = startOffset + newLength; |
8102 |
internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart, true); |
8217 |
internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart, true); |
8103 |
} |
8218 |
} |
8104 |
if (selection.y > startOffset && selection.x < startOffset + replacedLength) { |
8219 |
if (selection.y > startOffset && selection.x < startOffset + replacedLength) { |
8105 |
// selection intersects replaced text. set caret behind text change |
8220 |
// selection intersects replaced text. set caret behind text change |
8106 |
internalSetSelection(startOffset + newLength, 0, true); |
8221 |
internalSetSelection(startOffset + newLength, 0, true); |
8107 |
// always update the caret location. fixes 1G8FODP |
8222 |
// always update the caret location. fixes 1G8FODP |
8108 |
setCaretLocation(); |
8223 |
setCaretLocation(); |
8109 |
} |
8224 |
} |
8110 |
else { |
8225 |
else { |
8111 |
// move selection to keep same text selected |
8226 |
// move selection to keep same text selected |
8112 |
internalSetSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); |
8227 |
internalSetSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); |
8113 |
// always update the caret location. fixes 1G8FODP |
8228 |
// always update the caret location. fixes 1G8FODP |
8114 |
setCaretLocation(); |
8229 |
setCaretLocation(); |
8115 |
} |
8230 |
} |
8116 |
} |
8231 |
} |
8117 |
/** |
8232 |
/** |
8118 |
* Rewraps all lines |
8233 |
* Rewraps all lines |
8119 |
* <p> |
8234 |
* <p> |
8120 |
* |
8235 |
* |
8121 |
* @param oldClientAreaWidth client area width before resize |
8236 |
* @param oldClientAreaWidth client area width before resize |
8122 |
* occurred |
8237 |
* occurred |
8123 |
*/ |
8238 |
*/ |
8124 |
void wordWrapResize(int oldClientAreaWidth) { |
8239 |
void wordWrapResize(int oldClientAreaWidth) { |
8125 |
WrappedContent wrappedContent = (WrappedContent) content; |
8240 |
WrappedContent wrappedContent = (WrappedContent) content; |
8126 |
int newTopIndex; |
8241 |
int newTopIndex; |
8127 |
|
8242 |
|
8128 |
// all lines are wrapped and no rewrap required if widget has already |
8243 |
// all lines are wrapped and no rewrap required if widget has already |
8129 |
// been visible, client area is now wider and visual (wrapped) line |
8244 |
// been visible, client area is now wider and visual (wrapped) line |
8130 |
// count equals logical line count. |
8245 |
// count equals logical line count. |
8131 |
if (oldClientAreaWidth != 0 && clientAreaWidth > oldClientAreaWidth && |
8246 |
if (oldClientAreaWidth != 0 && clientAreaWidth > oldClientAreaWidth && |
8132 |
wrappedContent.getLineCount() == logicalContent.getLineCount()) { |
8247 |
wrappedContent.getLineCount() == logicalContent.getLineCount()) { |
8133 |
return; |
8248 |
return; |
8134 |
} |
8249 |
} |
8135 |
wrappedContent.wrapLines(); |
8250 |
wrappedContent.wrapLines(); |
8136 |
|
8251 |
|
8137 |
// adjust the top index so that top line remains the same |
8252 |
// adjust the top index so that top line remains the same |
8138 |
newTopIndex = content.getLineAtOffset(topOffset); |
8253 |
newTopIndex = content.getLineAtOffset(topOffset); |
8139 |
// topOffset is the beginning of the top line. therefore it |
8254 |
// topOffset is the beginning of the top line. therefore it |
8140 |
// needs to be adjusted because in a wrapped line this is also |
8255 |
// needs to be adjusted because in a wrapped line this is also |
8141 |
// the end of the preceeding line. |
8256 |
// the end of the preceeding line. |
8142 |
if (newTopIndex < content.getLineCount() - 1 && |
8257 |
if (newTopIndex < content.getLineCount() - 1 && |
8143 |
topOffset == content.getOffsetAtLine(newTopIndex + 1)) { |
8258 |
topOffset == content.getOffsetAtLine(newTopIndex + 1)) { |
8144 |
newTopIndex++; |
8259 |
newTopIndex++; |
8145 |
} |
8260 |
} |
8146 |
if (newTopIndex != topIndex) { |
8261 |
if (newTopIndex != topIndex) { |
8147 |
ScrollBar verticalBar = getVerticalBar(); |
8262 |
ScrollBar verticalBar = getVerticalBar(); |
8148 |
// adjust index and pixel offset manually instead of calling |
8263 |
// adjust index and pixel offset manually instead of calling |
8149 |
// setVerticalScrollOffset because the widget does not actually need |
8264 |
// setVerticalScrollOffset because the widget does not actually need |
8150 |
// to be scrolled. causes flash otherwise. |
8265 |
// to be scrolled. causes flash otherwise. |
8151 |
verticalScrollOffset += (newTopIndex - topIndex) * getVerticalIncrement(); |
8266 |
verticalScrollOffset += (newTopIndex - topIndex) * getVerticalIncrement(); |
8152 |
// verticalScrollOffset may become negative if first line was |
8267 |
// verticalScrollOffset may become negative if first line was |
8153 |
// partially visible and second line was top line. prevent this from |
8268 |
// partially visible and second line was top line. prevent this from |
8154 |
// happening to fix 8503. |
8269 |
// happening to fix 8503. |
8155 |
if (verticalScrollOffset < 0) { |
8270 |
if (verticalScrollOffset < 0) { |
8156 |
verticalScrollOffset = 0; |
8271 |
verticalScrollOffset = 0; |
8157 |
} |
8272 |
} |
8158 |
topIndex = newTopIndex; |
8273 |
topIndex = newTopIndex; |
8159 |
topOffset = content.getOffsetAtLine(topIndex); |
8274 |
topOffset = content.getOffsetAtLine(topIndex); |
8160 |
if (verticalBar != null) { |
8275 |
if (verticalBar != null) { |
8161 |
verticalBar.setSelection(verticalScrollOffset); |
8276 |
verticalBar.setSelection(verticalScrollOffset); |
8162 |
} |
8277 |
} |
8163 |
} |
8278 |
} |
8164 |
// caret may be on a different line after a rewrap. |
8279 |
// caret may be on a different line after a rewrap. |
8165 |
// call setCaretLocation after fixing vertical scroll offset. |
8280 |
// call setCaretLocation after fixing vertical scroll offset. |
8166 |
setCaretLocation(); |
8281 |
setCaretLocation(); |
8167 |
// word wrap may have changed on one of the visible lines |
8282 |
// word wrap may have changed on one of the visible lines |
8168 |
super.redraw(); |
8283 |
super.redraw(); |
8169 |
} |
8284 |
} |
8170 |
} |
8285 |
} |