|
|
< Day Day Up > |
|
7.3 Class Text7.3.1 Example
7.3.2 Text Hierarchy
7.3.3 Text Styles
7.3.4 Text Events
Text controls are common user interface elements that allow the user to edit strings. Text controls are selectable. The selection in a text control is the insertion point for characters. If the selection extends over one or more characters, the text control indicates this by drawing the selected characters in a different manner than the unselected characters. If the selection does not extend over any characters, it is indicated by a caret (also called an I-beam). A caret is a thin vertical line that appears between characters. The caret provides a visual cue for the user, indicating where keystrokes will go. On some platforms, the caret blinks to get attention. Text controls support only "plain" text. This means that all characters in the control are the same font and color. Applications that need a more flexible text editing control can use org.eclipse.swt.custom.StyledText, which was designed for use by Eclipse. Note that StyledText is not a native widget. It is common for an application program to detect when a text control has changed or to filter characters as they are typed. For example, a program may want to prompt the user to save changes when the shell is closed or ensure that only digits can be entered. To do this, programs listen for the SWT.Modify and SWT.Verify events, described later in this section. There are two kinds of text controls: those that can contain only a single line of text and those that can contain multiple lines of text. 7.3.5 Single-Line and Multiline Text ControlsThe SWT.SINGLE style is used to create single-line text controls. The following code fragment creates a single-line text control with a border, then sets the contents of the control to the string "Texan".
Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
text.setText("Texan");
Multiline text controls are created with the style SWT.MULTI. Unlike their single-line counterparts, they can include scroll bars. Scroll bars are created when you specify the SWT.H_SCROLL or SWT.V_SCROLL styles. The following code fragment creates a multiline text control with a border and scroll bars.
int style =
SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL;
Text text = new Text(parent, style);
In the following sections, some concepts apply to one or both kinds of text controls. When a concept applies to only one type of text control, this is indicated in the discussion. 7.3.6 String OperationsText controls support setting and getting their text in the same manner as Button, Label, and many other widgets in SWT.
7.3.7 Passwords and the Echo CharacterSingle-line text controls can be used to obtain a password from the user. As the user types, a specific character (called the echo character) is displayed instead of the one that was typed. The SWT.PASSWORD style is used to create text controls that display in this fashion. The following code fragment uses SWT.PASSWORD to create a single-line text control capable of acquiring a password from the user.
int style = SWT.SINGLE | SWT.BORDER | SWT.PASSWORD;
Text text = new Text(parent, style);
text.setText("fred54"); //this text won't be displayed
Note that the echo character is platform-specific and can change between themes and even between releases of the operating system.[9] To force the echo character to be the same on every platform, the setEchoChar() method can be used.
Generally speaking, it is unwise to set the echo character because it is part of the platform look and feel. 7.3.8 Lines and Line HeightYou can query the number of lines in a text control and the height of each line using getLineCount() and getLineHeight().
The getLineHeight() method is used mainly when computing the initial size of a text control. The following program uses getLineHeight() and FontMetrics (see Class FontMetrics in the Fonts chapter) to set the size of a multiline text control so that it displays about five rows of text and is about ten characters wide.
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Text text = new Text(shell, SWT.H_SCROLL|SWT.V_SCROLL);
int rows = 5, columns = 10;
GC gc = new GC(text);
FontMetrics fm = gc.getFontMetrics();
gc.dispose();
int height = rows * text.getLineHeight();
int width = columns * fm.getAverageCharWidth();
text.setSize(text.computeSize (width, height));
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
Figure 7.2 shows the result of running this example and typing three lines of text into the control. Figure 7.2.
7.3.9 Line DelimitersDifferent operating systems use different line delimiters to separate lines in multiline text controls.[10] Because SWT uses the native text control and cannot change the delimiter that it uses, strings are processed by SWT text controls using these platform-specific line delimiters.[11]
Using the line delimiter for one platform when running on another can cause portability problems. To ensure that you always use the right delimiter, you can use the constant Text.DELIMITER or the method getLineDelimiter().
The following code fragment sets the contents of a multiline Text control to contain three lines of text.
String lf = Text.DELIMITER;
text.setText("Line 1" + lf + "Line 2" + lf + "Line 3");
As a convenience, multiline text controls can also accept text that is delimited using "\n" on every platform. This means that using the text control line delimiter is not absolutely necessary when setting text into a text control. However, when text is queried back, the string that is returned uses the platform delimiter. Thus, making use of this convenience is problematic for all but the simplest uses of the control. For example, if your code computes string offsets in a string delimited by "\n", these offsets will not match character positions in the text control on Microsoft Windows. The best way to avoid this kind of error is to ensure that the source string also uses the operating system delimiter. Because the text control will accept "\n" as a delimiter, one possible way to convert the string is using setText() and getText(), like the following. String string = "Line 1\nLine 2\nLine 3\nLine 4"; text.setText(string); string = text.getText(); 7.3.10 The SelectionSubstrings within a text control can be selected using the setSelection() method. This method takes a selection range. Indices are zero-based and describe a range of integer selection positions anywhere from 0 to N, where N is the number of characters in the control. At first glance, it might seem that including the Nth "character" in the selection range is an error. However, this makes sense because selection indices address caret positions, not characters. Caret positions occur between characters. Given N characters, there are N+1 possible caret positions. To address N+1 positions, the indices 0 to N are needed. Figure 7.3 shows the caret positions in a string that is five characters long: Figure 7.3. Caret positions in a string within a text control.
When the start of the selection is the same as the end, the selection range is empty, and an I-beam is displayed.
The following code fragment uses setSelection(int, int) to select the word There in a text control.
text.setText("Hello There Fred!");
text.setSelection(6, 11);
The following program creates a shell and a text control and initializes it, then uses setSelection(int, int) to select the first occurrence of the string "word" in the control. Figure 7.4 shows the result of running this example.
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
int style = SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER;
Text text = new Text(shell, style);
text.setText("Here is\na word that\nneeds selecting.");
shell.setSize(200, 200);
shell.open();
String string = "word";
int index = text.getText().indexOf(string);
if (index != -1) {
text.setSelection(index, index + string.length());
}
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
Figure 7.4. Selecting a word in a text control.
7.3.11 Inserting and AppendingCharacters are inserted into a text control using the insert() method. Insertion always happens at the selection. It is not possible to insert text at an arbitrary location within a text control without first moving the selection to the new location.[12]
If the selection is an I-beam, the new text is inserted, as you would expect. If the selection is a range, the characters within the range are deleted, making the selection an I-beam and inserting the new characters. If you think about it, the insert() method behaves as though the characters were typed into the control.
The following code fragment first selects There, then replaces it with the string "New Text".
text.setText("Hello There Fred!");
text.setSelection(6, 11);
text.insert("New Text");
Inserting a string at the end of a text control is very a common operation. For this reason, the convenience operation append() is provided.
Appending a string is equivalent to setting the selection to the end of the control, inserting the new string, then setting the selection to the end once more. The following code fragment uses append() to append the string "New Text". It then performs the equivalent operation with the string "More New Text" using the methods setSelection() and insert().
text.append("New Text");
text.setSelection (text.getCharCount());
text.insert("More new text");
text.setSelection(text.getCharCount());
7.3.12 WrappingWhen a multiline text control is created with the SWT.WRAP style, it will wrap any line that cannot be fully displayed in the control. If you provide both the SWT.WRAP and SWT.H_SCROLL styles, SWT.H_SCROLL is ignored (i.e., the control will not create a horizontal scroll bar). A horizontal scroll bar is used to allow text lines that are wider than the width of the control to be fully seen so that, given that this cannot happen if the text is wrapped, the scroll bar is unnecessary. For more information about wrapping, see Labels That Wrap. 7.3.13 Clipboard OperationsText controls provide the copy(), cut(), and paste() clipboard operations. Text controls also support platform-specific keystrokes to perform these operations within the control. Some platforms provide a built-in Cut/Copy/Paste context menu. The clipboard operation methods are useful whenever you want to build your own context menu that contains these operations.
7.3.14 ScrollingText controls, along with the other controls that scroll in SWT, use the concept of top index to determine where to scroll. The top index of a text control is the zero-relative index of the topmost visible line in the control. For single-line text controls, the top index is always zero. The top index is set using the setTopIndex() method.
Sometimes you might need to bring the selection to the attention of the user. The showSelection() method is used to scroll the control so that the selection is visible. Note that calling showSelection() after setSelection() is unnecessary because setSelection() already scrolls to show the new selection. However, there are circumstances where the selection may have changed and scrolled out of view.
7.3.15 Text LimitsSome programs, particularly those that interact with databases, might need to restrict the amount of text that can be entered into a text control. For example, they do this to ensure that they do not attempt to store more characters in a database field than it will accept.
7.3.16 Text EventsSWT.DefaultSelection (SelectionEvent)The SWT.DefaultSelection event (typed event SelectionEvent) is sent whenever the user presses the <Enter> key for single-line text controls or uses a platform-specific mechanism to cause the event. Multiline text controls do not send the event, instead using the <Enter> key to insert a new line. The default selection event for a text control contains meaningful values in only the display, widget, and type fields. SWT.Modify (ModifyEvent)Table 7.1 shows the modify event for text controls.
The SWT.Modify event (typed event ModifyEvent) is sent after characters have been inserted or deleted from a text control. The event is sent both when the user types and when the program changes the characters in the control. Modify events contain meaningful values in only the display, widget, and type fields. Using SWT.Modify to Check Changes before Closing a ShellThe following example uses the SWT.Modify event to track the modified state of a text control. In the example, the text control is considered modified when characters have been entered that have not been saved. When the shell is closed, the user is prompted to save the changes, as shown in Figure 7.5. Note that when the program modifies the text control by setting the initial string, the modified flag must be cleared. This is necessary because SWT.Modify is sent any time the characters within the text control are changed.
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("ModifyExample");
shell.setLayout(new FillLayout());
int style = SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER;
Text text = new Text(shell, style);
final boolean[] modified = new boolean [1];
text.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event e) {
modified[0] = true;
}
});
shell.addListener(SWT.Close, new Listener() {
public void handleEvent(Event e) {
if (!modified[0]) return;
int style = SWT.PRIMARY_MODAL |
SWT.YES | SWT.NO | SWT.CANCEL;
MessageBox box = new MessageBox(shell, style);
box.setText(shell.getText());
box.setMessage("Save changes?");
switch (box.open()) {
case SWT.YES:
System.out.println ("Saving ...");
// if (!saveText()) break;
//FALL THROUGH
case SWT.NO :
break;
case SWT.CANCEL :
e.doit = false;
break;
}
}
});
text.setText("Initial text.");
modified[0] = false;
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
Figure 7.5.
This example is simple. It does not include the code that loads or saves the contents of the text control to a file. As well as performing the appropriate operation, code that loaded or saved the contents of the text control would need to clear the modified flag. This is necessary to allow the flag to be reset the next time the user types a character. Using SWT.Modify to Warn the User of Invalid InputSometimes a program will warn the user with an error message when an invalid character is typed. This allows users temporarily to enter invalid input and fix it at their leisure. The SWT.Modify event is perfect for this task, because it is sent after the characters have been entered. The following example warns the user when a character that is not a letter or a digit is typed into a text control. The warning message is displayed in a label that appears underneath the text control. To ensure that the warning message is valid, it is updated after every character. This ensures that when the user fixes the error, the warning message disappears.
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new RowLayout(SWT.VERTICAL));
final Text text = new Text(shell, SWT.BORDER);
text.setLayoutData(new RowData(250, SWT.DEFAULT));
final Label label = new Label(shell, SWT.NONE);
text.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
String string = text.getText();
int index = 0;
while (index < string.length()) {
char ch = string.charAt(index);
if (!Character.isLetterOrDigit(ch)) break;
index++;
}
if (index != string.length()) {
label.setText(
"Must contain only letters and digits");
} else {
label.setText("");
}
shell.layout();
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
Figure 7.6 shows this example running after the user has typed the string "Hello?". Figure 7.6.
SWT.Verify (VerifyEvent)Table 7.2 shows the verify event for a text control.
The SWT.Verify event (typed event VerifyEvent) is sent before characters are inserted or deleted from a text control. The event is sent both when the user types and when the program changes the characters in the control. The relevant event fields during a verify event for a text control are as follows.
In contrast to the SWT.Modify event, because SWT.Verify is sent before the text control is changed, the program can filter the string that is about to be entered or cancel the operation. The following example uses the SWT.Verify event to allow only digits to be entered into a single-line text control:
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Text text = new Text(shell, SWT.BORDER | SWT.SINGLE);
text.setSize (text.computeSize (128, SWT.DEFAULT));
text.addListener(SWT.Verify, new Listener() {
public void handleEvent(Event e) {
String text = e.text;
char[] chars = new char[text.length()];
text.getChars(0, chars.length, chars, 0);
for (int i = 0; i < chars.length; i++) {
if (!('0' <= chars[i] && chars[i] <= '9')){
e.doit = false;
return;
}
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
The SWT.Verify event contains sufficient information to maintain a copy of the contents of a text control. The following example implements a text control that emulates the SWT.PASSWORD style, inserting an asterisk for every character the user types or pastes into the text, as shown in Figure 7.7. The actual string that the user entered is stored in the variable string.
static String string = "";
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Text text = new Text(shell, SWT.BORDER | SWT.SINGLE);
text.setSize(text.computeSize(128, SWT.DEFAULT));
text.addListener(SWT.Verify, new Listener() {
public void handleEvent(Event e) {
String prefix = string.substring(0, e.start);
String suffix =
string.substring(e.end, string.length());
string = prefix + e.text + suffix;
int length = e.text.length();
e.text = "";
for (int i = 0; i < length; i++) e.text += '*';
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
System.out.println("String is " + string + ".");
display.dispose();
}
Figure 7.7.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
< Day Day Up > |
|