|  | <html> | 
|  | <head> | 
|  | <title>Getting Your Feet Wet with the SWT StyledText Widget</title> | 
|  | <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"> | 
|  | <link rel="stylesheet" href="../../default_style.css"> | 
|  | </head> | 
|  | <body> | 
|  | <div align="right">  <font face="Times New Roman, Times, serif" size="2">Copyright | 
|  | © 2001-2004 International Business Machines Corp.</font> </div> | 
|  | <table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" > | 
|  | <tr> | 
|  | <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse | 
|  | Corner Article</font></font></b></td> | 
|  | </tr> | 
|  | </table> | 
|  |  | 
|  | <h1><img SRC="Idea.jpg" width="120" height="86"></h1> | 
|  |  | 
|  | <h1 ALIGN="CENTER">Getting Your Feet Wet with the SWT<br> | 
|  | StyledText Widget </h1> | 
|  | <b> | 
|  |  | 
|  | <blockquote> | 
|  | <p>Summary</p> | 
|  | </blockquote> | 
|  | </b> | 
|  |  | 
|  | <blockquote> | 
|  | <p>The<i> StyledText</i> widget is a customizable widget that can be used to display and | 
|  | edit text with different colors and font styles. This article presents an overview of the | 
|  | concepts, issues, and rules that you should be aware of when using the <i>StyledText</i> | 
|  | widget.</p> | 
|  | <p><b>By Lynne Kues and Knut Radloff, OTI</b> | 
|  | <br> | 
|  | May 7, 2001; updated July 19, 2004 for Eclipse 3.0</p> | 
|  | </blockquote> | 
|  |  | 
|  | <hr width="100%"> | 
|  |  | 
|  | <h2>Overview</h2> | 
|  |  | 
|  | <p>The<i> StyledText</i> widget provides a fast and easy to use means to display and edit | 
|  | text. Within the StyledText widget, the following attributes can be specified:</p> | 
|  |  | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <ul> | 
|  | <li>text foreground color </li> | 
|  | <li>text background color </li> | 
|  | <li>text font style (i.e., normal, bold or italic) </li> | 
|  | <li>line background color </li> | 
|  | </ul> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  |  | 
|  | <p>These attributes are referred to as "styles". In addition, the <i>StyledText</i> | 
|  | widget provides standard navigation/editing keyboard behavior, allows for user-defined key | 
|  | bindings, and will perform word wrapping. Note that support for fonts with italic style was | 
|  | added as of version 3.0.  However, the <i>StyledText</i> widget does not support mixing of | 
|  | multiple fonts. | 
|  |  | 
|  | <p>The <i>StyledText</i> widget can be customized using pluggable objects to manage | 
|  | text content and styles. You can provide your own implementation of these objects | 
|  | in order to tailor the widget to your needs. Or if you have no need to customize | 
|  | the widget, easy to use API for managing styles and text content is available, | 
|  | making the pluggable nature of the widget completely transparent. How to customize | 
|  | the <em>StyledText</em> widget and why you might want to do so will be discussed | 
|  | in our other article, <a href="../StyledText%202/article2.html">Into the Deep | 
|  | End of the StyledText Widget</a>.</p> | 
|  |  | 
|  | <p>The <i>StyledText</i> widget is used by the JFace Text Framework, which is part of the Eclipse Platform. | 
|  | The JFace Text Framework provides a layer of abstraction on top of the <i>StyledText</i> widget. | 
|  | The layer is pluggable and supports text formatting, content code assist capabilities, and | 
|  | a source viewer. </p> | 
|  |  | 
|  | <h3>A Simple Example </h3> | 
|  |  | 
|  | <p>The following is a simple example that shows how to create a <i>StyledText</i> widget | 
|  | and set text. This example will be built upon in subsequent sections of this article.</p> | 
|  |  | 
|  | <p align="center"><img border="0" src="Image0.gif" width="200" height="100"></p> | 
|  |  | 
|  | <pre><font COLOR="#000084">import</font><font COLOR="#000000"> org.eclipse.swt.*;</font><font | 
|  | COLOR="#000084"> | 
|  | import</font><font COLOR="#000000"> org.eclipse.swt.custom.*; | 
|  | </font><font | 
|  | COLOR="#000084">import<font COLOR="#000000"> org.eclipse.swt.graphics.*; | 
|  | </font>import</font><font | 
|  | COLOR="#000000"> org.eclipse.swt.widgets.*;</font><font COLOR="#000084"> | 
|  | import</font><font | 
|  | COLOR="#000000"> org.eclipse.swt.layout.*; | 
|  | </font><font COLOR="#000084"> | 
|  | public</font><font | 
|  | COLOR="#000000"> </font><font COLOR="#000084">class</font><font COLOR="#000000"> StyledTextExample { | 
|  | </font><font | 
|  | COLOR="#000084">public</font><font COLOR="#000000"> </font><font COLOR="#000084">static</font><font | 
|  | COLOR="#000000"> </font><font COLOR="#000084">void</font><font COLOR="#000000"> main(String [] args) { | 
|  | </font><font | 
|  | COLOR="#840000">// create the widget's shell</font><font COLOR="#000000"> | 
|  | Shell shell = </font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> Shell(); | 
|  | shell.setLayout(</font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> FillLayout()); | 
|  | shell.setSize(200, 100); | 
|  | Display display = shell.getDisplay(); | 
|  | </font><font | 
|  | COLOR="#840000">// create the styled text widget</font><font COLOR="#000000"> | 
|  | StyledText widget = </font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> StyledText(shell, SWT.BORDER); | 
|  | widget.setText(</font><font | 
|  | COLOR="#008484">"This is the StyledText widget."</font><font COLOR="#000000">); | 
|  |  | 
|  | shell.open(); | 
|  | </font><font | 
|  | COLOR="#000084">while</font><font COLOR="#000000"> (!shell.isDisposed()) | 
|  | </font><font | 
|  | COLOR="#000084">if</font><font COLOR="#000000"> (!display.readAndDispatch()) display.sleep(); | 
|  | } | 
|  | }</font></pre> | 
|  |  | 
|  | <h3>Character, Line and Caret Offsets</h3> | 
|  |  | 
|  | <p>Within the <i>StyledText</i> widget, both character offsets and line indexes are zero | 
|  | based. For example, in the StyledText widget below, the line at index 0 is | 
|  | "abcde" and the character at offset 0 is "a".</p> | 
|  | <div align="center"><center> | 
|  |  | 
|  | <pre>widget.setText(<font color="#008080">"abcde\r\nfghij"</font>); | 
|  | </pre> | 
|  | </center></div><div align="center"><center> | 
|  |  | 
|  | <pre><img border="0" src="Image2.gif" width="200" height="100"></pre> | 
|  | </center></div> | 
|  |  | 
|  | <p>When specifying offsets within the <em>StyledText</em> widget, line delimiter | 
|  | characters are included.  In the above example, the line delimiter is CR/LF (i.e., | 
|  | "\r\n").  Therefore, the character at offset five is CR and the | 
|  | character at offset six is LF.  Similarly, <strong>getLineAtOffset(6)</strong> | 
|  | returns 0 and <strong>getLineAtOffset(7)</strong> returns 1. If there was another CR/LF | 
|  | line break at the end of the second line, <strong>getLineAtOffset(14)</strong> would | 
|  | return 2. </p> | 
|  |  | 
|  | <p>Caret offsets are also zero based.  Calling <strong>setCaretOffset(4) </strong>for | 
|  | the above widget places the caret between 'd' and 'e'.  And, like character offsets, | 
|  | caret offsets take line delimiters into account.  In order to place the caret at the | 
|  | beginning of the second line (i.e., in front of the 'f') you would call <strong>setCaretOffset(7)</strong>. | 
|  | Also note that <strong>setCaretOffset(12)</strong> is a valid call and places the caret at | 
|  | the end of the text, after the 'j'.  The range of valid caret offset values is one | 
|  | more than the range of valid character offset values.</p> | 
|  |  | 
|  | <h3>Text Ranges</h3> | 
|  |  | 
|  | <p>Generally, the <i>StyledText</i> widget uses the start offset and the length to specify | 
|  | a text range. Specifying the length of a text range, instead of the end offset, is less | 
|  | error prone because there is no doubt as to whether or not the end offset is included in | 
|  | the range. For example, a start offset of "0" and an end offset of "2" | 
|  | may or may not include the character at offset 2 (in SWT it doesn’t). Expressing the | 
|  | equivalent using a start offset and a length (i.e., 0 and 2 respectively) is unambiguous. | 
|  | It is clear that this describes the characters at offsets 0 and 1. </p> | 
|  |  | 
|  | <p>To maintain consistency with other SWT widgets, API methods that use the start offset | 
|  | and end offset semantics are also provided. For example, SWT uses "start" and | 
|  | "end" when selecting items in a <i>List</i>, <i>Tree</i> or <i>Table</i>. The | 
|  | table below shows the API that uses start offset and end offset (non-range based) and the | 
|  | equivalent API with start offset and length semantics (range based). </p> | 
|  | <div align="center"><center> | 
|  |  | 
|  | <table BORDER="1" CELLSPACING="2" CELLPADDING="7" WIDTH="560"> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP" align="center"><b><font size="2" face="Courier New">Start | 
|  | Offset, End Offset</font></b></td> | 
|  | <td WIDTH="285" VALIGN="TOP" align="center"><b><font size="2" face="Courier New">Start | 
|  | Offset, Length</font></b></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP"><font size="2" face="Courier New">getSelection()</font></td> | 
|  | <td WIDTH="285" VALIGN="TOP"><font size="2" face="Courier New">getSelectionRange()</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP"><font size="2" face="Courier New">getText(int, int)</font></td> | 
|  | <td WIDTH="285" VALIGN="TOP"><font size="2" face="Courier New">getTextRange(int, int)</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP"><font size="2" face="Courier New">n/a</font></td> | 
|  | <td WIDTH="285" VALIGN="TOP"><font size="2" face="Courier New">redrawRange(int, int)</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP"><font size="2" face="Courier New">n/a</font></td> | 
|  | <td WIDTH="285" VALIGN="TOP"><font size="2" face="Courier New">replaceTextRange(int, int, | 
|  | String)</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td WIDTH="235" VALIGN="TOP"><font size="2" face="Courier New">setSelection(int, int)</font></td> | 
|  | <td WIDTH="285" VALIGN="TOP"><font size="2" face="Courier New">setSelectionRange(int, int)</font></td> | 
|  | </tr> | 
|  | </table> | 
|  | </center></div> | 
|  |  | 
|  | <p ALIGN="left"><i>StyledText</i> API that uses a start offset and a length will always | 
|  | end with "Range". For example, <b>getSelectionRange </b>will return the | 
|  | selection as a start offset and a length. </p> | 
|  |  | 
|  | <p ALIGN="left">You can mix non-range based and range based <i>StyledText</i> API, as | 
|  | demonstrated by the code below.  The behavior is the same. However, for the sake of | 
|  | clarity you should decide which kind of API to use and then use it consistently. </p> | 
|  |  | 
|  | <pre><font COLOR="#000000">	widget.setText(</font><font COLOR="#008484">"This is the StyledText widget."</font><font | 
|  | COLOR="#000000">); | 
|  |  | 
|  | widget.getText(</font>5, 7<font COLOR="#000000">);		</font><font | 
|  | color="#800000">// returns "is"</font><font COLOR="#000000"> | 
|  | widget.getTextRange(</font>5, 2<font | 
|  | COLOR="#000000">);	</font><font color="#800000">// returns "is" | 
|  | </font><font | 
|  | COLOR="#000000"> | 
|  | widget.setSelection(</font>8, 11<font COLOR="#000000">);		</font><font | 
|  | color="#800000">// selects  "the"</font><font COLOR="#000000"> | 
|  | Point sel = widget.getSelectionRange(); </font><font | 
|  | color="#800000">// returns Point with x=8, y=3</font><font COLOR="#000000"> | 
|  | widget.setSelectionRange(</font>8, 3<font | 
|  | COLOR="#000000">);		</font><font color="#800000">// selects  "the"</font><font | 
|  | COLOR="#000000"> | 
|  | Point sel = widget.getSelection();	</font><font color="#800000">// returns Point with x=8, y=11</font><font | 
|  | COLOR="#000000"> | 
|  | </font><font SIZE="2" COLOR="#000000">				</font></pre> | 
|  |  | 
|  | <h3>Style Specification</h3> | 
|  |  | 
|  | <p>The <i>StyledText</i> widget uses <i>StyleRanges</i> to specify text styles. The fields | 
|  | of the <i>StyleRange</i> class are defined as follows:</p> | 
|  |  | 
|  | <pre>	<font COLOR="#00007f">public</font> <font COLOR="#00007f">int</font> start; 		<font | 
|  | COLOR="#7f0000">// start offset of the style, zero-based | 
|  | </font>	<font COLOR="#00007f">public</font> <font | 
|  | COLOR="#00007f">int</font> length; 		<font COLOR="#7f0000">// length of the style | 
|  | </font>	<font | 
|  | COLOR="#00007f">public</font> Color foreground;	<font COLOR="#7f0000">// text foreground color | 
|  | </font>	<font | 
|  | COLOR="#00007f">public</font> Color background;	<font COLOR="#7f0000">// test background color | 
|  | </font>	<font | 
|  | COLOR="#00007f">public int</font> fontStyle = SWT.NORMAL; <font | 
|  | COLOR="#7f0000">// may be SWT.NORMAL, SWT.BOLD or SWT.ITALIC</font></pre> | 
|  |  | 
|  |  | 
|  | <p>If the <b>foreground</b> and <b>background</b> fields for a <i>StyleRange</i> are null, | 
|  | the <i>StyledText</i> widget will use the default widget colors for these fields.</p> | 
|  |  | 
|  | <p>The <i>StyleRange</i> class also includes helper methods for managing and manipulating | 
|  | style ranges. For example, the <b>similarTo(StyleRange)</b> method will return whether or | 
|  | not two style ranges have the same style attributes and only differ in the start and | 
|  | length values.</p> | 
|  |  | 
|  | <p>You define style ranges for the <i>StyledText</i> widget by using the following | 
|  | methods:</p> | 
|  |  | 
|  | <pre> | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> setStyleRange(StyleRange range) | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> setStyleRanges(StyleRange[] ranges) | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> replaceStyleRanges(<font COLOR="#00007f">int</font> start, <font COLOR="#00007f">int</font> length, StyleRange[] ranges) | 
|  | </pre> | 
|  |  | 
|  | <p>The <b>setStyleRange</b> API applies the specified style to the text range specified in the | 
|  | <b>StyleRange</b>. If the new style overlaps existing styles, the text outside the new style range | 
|  | will keep its existing style information.</p> | 
|  | <p>The <b>setStyleRanges</b> API simply replaces all styles in the widget with the new ones. | 
|  | </p> | 
|  | <p>The <b>replaceStyleRanges</b> API is provided to improve performance. | 
|  | It replaces any styles in the given range with the specified new styles. All | 
|  | existing styles in the range will be deleted, so the new styles need not cover | 
|  | the entire replaced range. Note that <b>replaceStyleRanges</b> could be implemented | 
|  | by calling <b>setStyleRange</b> multiple times to cover the entire replace range. StyleRanges | 
|  | with null colors would delete existing styles that have no replacement. However, | 
|  | the new API makes this task a lot easier and more efficient. </p> | 
|  |  | 
|  | <p>When text changes occur in the <i>StyledText</i> widget, styles that are set using any of the above | 
|  | API are updated to reflect the text changes. Styles are always maintained relative to the text to which they | 
|  | are assigned and not to a fixed position. If text is inserted in front of a style, the style ranges after the inserted | 
|  | text are updated to move with their associated text. If text is inserted at a location that is within a style range, the | 
|  | style range is split to accommodate the new text. If new text replaces existing text and some or all of the existing | 
|  | text has a style assigned to it, only the non-replaced text will maintain its styles. In short, new text will never | 
|  | be automatically styled. | 
|  | </p> | 
|  |  | 
|  | <p>The following is a simple example of how to use style ranges in the StyledText widget.</p> | 
|  |  | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <blockquote> | 
|  | <font size="2"><dl> | 
|  | <div align="center"><center> | 
|  | <dt><img SRC="Image1.gif" width="200" height="100"></dt> | 
|  | </center></div> | 
|  | <dd> </dd> | 
|  | </dl></font> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  | </blockquote> | 
|  |  | 
|  | <pre><font COLOR="#000000">	widget.setText(</font><font COLOR="#008484">"This is the StyledText widget."</font><font | 
|  | COLOR="#000000">); | 
|  | </font>	StyleRange styleRange = <font COLOR="#00007f">new</font> StyleRange(); | 
|  | styleRange.start = 0; | 
|  | styleRange.length = text.length(); | 
|  | styleRange.fontStyle = SWT.BOLD; | 
|  | styleRange.foreground = display.getSystemColor(SWT.COLOR_BLUE); | 
|  | widget.setStyleRange(styleRange);</pre> | 
|  |  | 
|  | <p>In addition to styles, the <b>setLineBackground (int,int,Color)</b> API can be used to customize the display of the text in the <i>StyledText</i> | 
|  | widget.  The color specified when using this API will be applied to the display area of the given lines (e.g., line background colors extend the | 
|  | width of the StyledText widget).  If line background colors and styles with background colors are used in conjunction with each other, the | 
|  | style background colors will be displayed after the line background colors are displayed (i.e., the style background color will take precedence for | 
|  | its given text range).</p> | 
|  |  | 
|  | <p>When text changes occur in the <i>StyledText</i> widget, line background colors that are specified via the <b>setLineBackground</b> | 
|  | API are maintained relative to the text lines to which they are assigned and not to a fixed position.  Line background colors are updated in | 
|  | a fashion similar to style ranges.  New lines of text will never be assigned line background colors and if an existing text line has an associated | 
|  | line background color, the association will be maintained. | 
|  | </p> | 
|  |  | 
|  | <h3>Resource Life Cycle</h3> | 
|  |  | 
|  | <p>SWT <i>Color</i> objects are used to specify styles for the <i>StyledText</i> widget. | 
|  | It is your responsibility to manage the life cycle of these objects. The colors must be | 
|  | disposed when they are no longer used by the widget. </p> | 
|  |  | 
|  | <p>The <i>StyledText</i> widget references colors that are set using the <b>replaceStyleRanges</b>, | 
|  | <b>setLineBackground</b>, <b>setStyleRange</b> and <b>setStyleRanges</b> | 
|  | API methods.  Since the widget does not | 
|  | copy <em>Color</em> objects, a color set using these API methods can only be considered | 
|  | unused when all the character ranges and line ranges that use the color have been reset to | 
|  | use the default widget colors. The same is true for the <b>setBackground</b> and <b>setForeground</b> API. | 
|  | Colors set using this API are referenced by StyledText and can only be disposed when no longer set in the | 
|  | widget or when the widget has been disposed. | 
|  | </p> | 
|  |  | 
|  | <p>The following code example illustrates the correct way to manage <em>Color</em> | 
|  | objects.  Two <em>Colors</em>, lime and orange, are created and used by the widget.. </p> | 
|  |  | 
|  | <p align="center"><img border="0" src="Image3.gif" width="200" height="100"> </p> | 
|  |  | 
|  | <pre><font COLOR="#000000">	widget.setText(</font><font COLOR="#008484">"This is the StyledText widget."</font><font | 
|  | COLOR="#000000">); | 
|  | </font><font color="#800000">	// create the Colors</font><font | 
|  | COLOR="#000000"> | 
|  | </font>	<font COLOR="#000000">Color orange = </font><font COLOR="#000084">new</font><font | 
|  | COLOR="#000000"> Color(display, 255, 127, 0); | 
|  | </font>	<font COLOR="#000000">Color lime = </font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> Color(display, 127, 255, 127); | 
|  |  | 
|  | </font><font | 
|  | color="#800000">	// make "This" bold and orange</font><font COLOR="#000000"> | 
|  | </font>	<font | 
|  | COLOR="#000000">StyleRange styleRange = </font><font COLOR="#000084">new</font><font | 
|  | COLOR="#000000"> StyleRange(); | 
|  | </font>	<font COLOR="#000000">styleRange.start = 0 | 
|  | styleRange.length = 4; | 
|  | </font>	<font | 
|  | COLOR="#000000">styleRange.fontStyle = SWT.BOLD; | 
|  | </font>	<font COLOR="#000000">styleRange.foreground = orange; | 
|  | widget.setStyleRange(styleRange); | 
|  |  | 
|  | </font><font | 
|  | color="#800000">	// make "StyledText" bold and lime | 
|  | </font><font COLOR="#000000">	styleRange = </font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> StyleRange(); | 
|  | styleRange.start = 12; | 
|  | </font>	<font | 
|  | COLOR="#000000">styleRange.length = 10; | 
|  | styleRange.fontStyle = SWT.BOLD; | 
|  | </font>	<font | 
|  | COLOR="#000000">styleRange.foreground = lime; | 
|  | </font>	<font COLOR="#000000">widget.setStyleRange(styleRange); | 
|  |  | 
|  | </font><font | 
|  | color="#800000">//	styleRange = new StyleRange(12, 10, null, null, SWT.NORMAL); | 
|  | //	widget.setStyleRange(styleRange);	// set the bold, lime colored text back to normal | 
|  | //	lime.dispose();				// lime is no longer used by the widget so it can be disposed | 
|  | </font><font | 
|  | COLOR="#000000"> | 
|  | shell.open(); | 
|  | </font><font COLOR="#000084">while</font><font | 
|  | COLOR="#000000"> (!shell.isDisposed()) | 
|  | </font><font COLOR="#000084">if</font><font | 
|  | COLOR="#000000"> (!display.readAndDispatch()) display.sleep(); | 
|  |  | 
|  | orange.dispose(); | 
|  | lime.dispose();				</font><font | 
|  | color="#800000">// make sure you comment out this line if you dispose lime above</font><font | 
|  | COLOR="#000000"> | 
|  | </font></pre> | 
|  |  | 
|  | <p><font COLOR="#000000">If you decide that the lime colored text looks ugly, you can use | 
|  | the code that is commented out to reset that text to the widget's default foreground | 
|  | color. The example would then look like this:</font></p> | 
|  |  | 
|  | <p align="center"><img border="0" src="Image4.gif" width="200" height="100"></p> | 
|  |  | 
|  | <p><font COLOR="#000000">Since you reset the only style range that uses the lime color, | 
|  | the lime <i>Color</i> object can be disposed. The orange color can only be disposed when | 
|  | the application terminates because it is still used by the first style range that was set. | 
|  | Note that we use a different <i>StyleRange</i> constructor for resetting the lime style to | 
|  | simplify the style range creation.</font></p> | 
|  |  | 
|  | <p><font COLOR="#000000">The following code resets all style ranges to the widget's | 
|  | default colors.</font></p> | 
|  |  | 
|  | <pre>	<font COLOR="#000000">widget.setStyleRange(</font><font color="#000080">null</font><font | 
|  | COLOR="#000000">); | 
|  | orange.dispose(); | 
|  | lime.dispose();</font></pre> | 
|  |  | 
|  | <p><font COLOR="#000000">Once you have called <b>setStyleRange(null)</b> all colors can be | 
|  | disposed of safely.</font></p> | 
|  |  | 
|  | <p><font COLOR="#000000">The <b>setLineBackground</b> API works exactly like the <b>setStyleRange</b> | 
|  | API. You can only dispose <i>Color</i> objects after you have reset the line backgrounds | 
|  | that use the colors or after you dispose the <i>StyledText</i> widget. For example:</font></p> | 
|  |  | 
|  | <p align="center"><img border="0" src="Image5.gif" width="200" height="100"></p> | 
|  |  | 
|  | <pre><font COLOR="#000000">	widget.setText(</font><font COLOR="#008484">"This is the StyledText widget."</font><font | 
|  | COLOR="#000000">); | 
|  | </font>	<font COLOR="#000000">Color orange = </font><font | 
|  | COLOR="#000084">new</font><font COLOR="#000000"> Color(display, 255, 127, 0); | 
|  | widget.</font>setLineBackground<font | 
|  | COLOR="#000000">(0, 1, orange);</font></pre> | 
|  |  | 
|  | <p><font COLOR="#000000">You can dispose the orange color only after you have reset the | 
|  | line background color of the first line by calling:</font></p> | 
|  |  | 
|  | <pre><font COLOR="#000000">	widget.</font>setLineBackground<font COLOR="#000000">(0, 1, </font><font | 
|  | color="#000080">null</font><font COLOR="#000000">); | 
|  | orange.dispose();</font></pre> | 
|  |  | 
|  | <p>It is advisable for you to cache <i>Color</i> objects and dispose them when | 
|  | you dispose the <i>StyledText</i> widget. Caching colors will improve performance | 
|  | and minimize the number of allocated resources. An in-depth discussion of SWT | 
|  | color resources can be found in the <a | 
|  | href="../SWT%20Color%20Model/swt-color-model.htm">SWT Color Model</a> article.</p> | 
|  |  | 
|  | <h3><a NAME="TextChange"></a>Text Change Notification</h3> | 
|  |  | 
|  | <p>Text changes within the <i>StyledText</i> widget can occur via user input or | 
|  | programmatically. User input changes occur when keyboard input is received. Programmatic | 
|  | changes occur when the <i>StyledText</i> API is executed. Four API methods exist for | 
|  | performing programmatic changes:</p> | 
|  | <pre> | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> append(String text) | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> insert(String text) | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> replaceTextRange(<font | 
|  | COLOR="#00007f">int</font> start, <font COLOR="#00007f">int</font> length, String text) | 
|  | <font COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> setText(String text)</pre> | 
|  |  | 
|  | <p>When text changes occur, the <i>StyledText</i> widget generates four kinds of | 
|  | notification events:<dfn> | 
|  |  | 
|  | <dl> | 
|  | <dd>verify key event</dd> | 
|  | <dd>verify event</dd> | 
|  | <dd>modify event</dd> | 
|  | <dd>extended modify event </dd> | 
|  | </dl> | 
|  | </dfn> | 
|  |  | 
|  | <h4><a name="VerifyKeyEvent"></a>Verify Key Event</h4> | 
|  |  | 
|  | <p>The <b>verify key event </b>is sent immediately after a key has been pressed.  The | 
|  | fields of the <i>VerifyEvent</i> that are used when sending the <strong>verify key event</strong> | 
|  | are defined as follows: </p> | 
|  |  | 
|  | <pre><font COLOR="#000084">	public boolean</font> doit;	<font color="#800000">// flag indicating whether the keystroke should be processed</font><font | 
|  | COLOR="#000084"> | 
|  | public</font> <font COLOR="#000084">char</font> character;	<font | 
|  | color="#800000">// characte</font><font COLOR="#840000">r represented by the key that was typed | 
|  | </font><font | 
|  | COLOR="#000084">public</font> <font COLOR="#000084">int</font> keyCode;	<font | 
|  | color="#800000">// key code</font><font COLOR="#840000"> of the key that was typed. Used for special keys (e.g., CTRL). | 
|  | </font>	<font | 
|  | COLOR="#000084">public</font> <font COLOR="#000084">int</font> stateMask;	<font | 
|  | color="#800000">// sta</font><font COLOR="#840000">te of the keyboard modifier keys (e.g., SHIFT) </font><font | 
|  | color="#800000">at the tim</font><font COLOR="#840000">e the | 
|  | </font>				<font | 
|  | color="#800000">// </font><font COLOR="#840000">event was generated</font></pre> | 
|  |  | 
|  | <p>You can use the <strong>verify key event </strong>to filter out a key stroke before it | 
|  | is processed by the <i>StyledText</i> widget. To do so, you would set the <b>doit </b>field | 
|  | of the <i>VerifyEvent</i> to false. </p> | 
|  |  | 
|  | <p>To listen to verify key events add a <i>VerifyKeyListener</i> to the <i>StyledText</i> | 
|  | widget and implement the <b>verifyKey(VerifyEvent) </b>method in the listener. Following | 
|  | is an example of a <i>VerifyKeyListener</i> that prevents the user from deleting text by | 
|  | filtering out the backspace and delete keystrokes.</p> | 
|  |  | 
|  |  | 
|  | <pre><font COLOR="#7f0000">	// This handler will filter out the backspace and delete keys to prevent deleting characters. | 
|  | </font>	<font | 
|  | COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> verifyKey(VerifyEvent event) { | 
|  | <font | 
|  | COLOR="#00007f">if</font> ((event.character == <font COLOR="#007f7f">'\u0008'</font>) || (event.character == <font | 
|  | COLOR="#007f7f">'\u007F'</font>)) { | 
|  | event.doit = <font COLOR="#00007f">false</font>; | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <h4>Verify Event</h4> | 
|  |  | 
|  | <p>The<b> verify event<font COLOR="#00007f"> </font></b>is sent when a text change is | 
|  | about to occur because of user input. It is sent before the text content change is made | 
|  | and before the change is reflected in the widget.  The fields of the <i>VerifyEvent</i> | 
|  | that are used when sending the <strong>verify event</strong> are defined as follows: </p> | 
|  |  | 
|  | <pre><font COLOR="#000084"> | 
|  | public int</font> start, end;	<font | 
|  | color="#800000">// range of text being modified</font><font COLOR="#000084"> | 
|  | public</font> String text;	<font color="#800000">// new text that will be inserted or empty string</font><font COLOR="#000084"> | 
|  | public boolean</font> doit;  <font color="#800000">// flag indicating whether the text change should be processed</font></pre> | 
|  |  | 
|  | <p>The <i>VerifyEvent </i>contains the start offset and end offset of the replaced text as | 
|  | well as the new text. You should register a <i>VerifyListener</i> when you want to make | 
|  | changes to the replace range or to the new text before the widget is updated. You can | 
|  | force the widget to ignore the text change altogether by setting the <b>doit </b>field of | 
|  | the <i>VerifyEvent</i> to false. </p> | 
|  |  | 
|  | <p>You can use the <b>verify event</b> to perform operations such as automatic word | 
|  | completion. Following is an example of a <i>VerifyListener</i> that performs word | 
|  | completion. When you listen for <b>verify events</b>, you must implement the <b>verifyText(VerifyEvent)</b> | 
|  | method.</p> | 
|  |  | 
|  |  | 
|  | <pre>	<font COLOR="#7f0000">// This handler will automatically expand the character "S" to "StyledText".</font> | 
|  | <font | 
|  | COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> verifyText(VerifyEvent event) { | 
|  | <font | 
|  | COLOR="#7f0000">		// Only expand when text is inserted. | 
|  | </font>		<font COLOR="#00007f">if</font> (event.end - event.start == 0) { | 
|  | <font | 
|  | COLOR="#00007f">if</font> (event.text.equals(<font COLOR="#007f7f">"S"</font>)) { | 
|  | event.text = <font | 
|  | COLOR="#007f7f">"StyledText"</font>; | 
|  | } | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <p>Note that the <b>verify event</b> that is sent by the <i>StyledText</i> widget is the | 
|  | same event that is sent by the SWT <i>Text</i> and <i>Combo</i> widgets.</p> | 
|  |  | 
|  | <h4>Modify Event</h4> | 
|  |  | 
|  | <p>The <b>modify event</b><font COLOR="#00007f"> </font>is sent after the widget's text | 
|  | content has been updated. It does not contain any information about the text change. It | 
|  | serves as a light weight notification that a text change of some sort has occurred. Use it | 
|  | if all you want to know is if the widget text has been modified. For example, to determine | 
|  | whether or not to display a "Save Changes?" prompter when an edited file is | 
|  | closed. To listen to modify events add a <i>ModifyListener</i> to the <i>StyledText</i> | 
|  | widget.</p> | 
|  |  | 
|  | <p>The <b>modify event</b> that is sent by the <i>StyledText</i> widget is the same event | 
|  | that is sent by the SWT <i>Text</i> and <i>Combo</i> widgets.</p> | 
|  |  | 
|  | <h4>Extended Modify Event</h4> | 
|  |  | 
|  | <p>The <b>extended modify event</b>, which is sent after the modify event, contains the | 
|  | start offset and length of the new text as well as the replaced text. It is the mirror | 
|  | image of the <b>verify event</b>.  The <b>extended modify event</b> is sent after the | 
|  | widget has changed and when the text model reflects the actual text change. It, therefore, | 
|  | does not have a <b>doit</b> field like the <b>verify key event</b> and <b>verify event</b> | 
|  | do.<b> </b></p> | 
|  |  | 
|  | <p>Register an <i>ExtendedModifyListener</i> if you need to update data after a text | 
|  | change occurred and when you need to know the actual text change. For example, if you are | 
|  | developing an editor for word processing that supports text styles, when a user types a | 
|  | character you will probably want that character to take on the styles of the characters | 
|  | around it. In order to implement this behavior, you will need to know where the text | 
|  | change occurred, so that you can: | 
|  |  | 
|  | <ol> | 
|  | <li>query the styles of the characters around the new character</li> | 
|  | <li>change the style of the new character</li> | 
|  | </ol> | 
|  |  | 
|  | <p>The <b>extended modify event</b> will give you this information. Note that you cannot | 
|  | use the <b>verify event</b> to implement the above scenario since the text content change | 
|  | has not occurred yet when the <b>verify event</b> event is sent, so changing the style of | 
|  | the new character will be impossible. Similarly, you cannot use the <b>modify event</b> to | 
|  | implement the above scenario because it does not contain information about the text change | 
|  | (e.g., where the text change occurred). </p> | 
|  |  | 
|  | <p>Note that a new event was introduced instead of enhancing the existing<b> modify event </b>in | 
|  | order to maintain compatibility with SWT. Not all SWT widgets that send a <b>modify event</b> | 
|  | can get the data that is necessary to send an <b>extended modify event</b>. </p> | 
|  |  | 
|  | <h4>Flow of Text Change Notifications  </h4> | 
|  |  | 
|  | <p>The following diagram depicts when the events described above occur within the <i>StyledText</i> | 
|  | widget. The "Process Input?" and "Process Change?" decisions are | 
|  | determined by the value of the boolean <b>VerifyEvent.doit</b> field as described above. | 
|  | The key binding processing shown in gray in the diagram is described in more detail <a | 
|  | href="#KeyBindings">below</a>. </p> | 
|  |  | 
|  | <p>As shown in the diagram by the "Key Bound?" decision, if a key action is | 
|  | defined for user input, text change processing will stop and the key action will be | 
|  | processed instead. In the <strong>verify key event</strong> example above, the backspace | 
|  | and delete keys are editing actions.  So you must use a <em>VerifyKeyListener</em> | 
|  | vs. a <em>VerifyListener</em> to filter out these keystrokes.  <em>VerifyListeners</em> | 
|  | are only notified about content changes, not editing actions.</p> | 
|  |  | 
|  | <p>The Text Content/Styles Update process is also shown in gray.  This portion of the | 
|  | diagram will be discussed in depth in our second article, <b>Into the Deep End of the | 
|  | StyledText Widget</b>. For this article, knowing that the widget applies the text | 
|  | change and updates its styles during this step is sufficient. </p> | 
|  |  | 
|  | <p align="center"><img border="0" src="TextChanges.gif" width="519" height="995"> </p> | 
|  |  | 
|  | <h4>Text Notification Examples for User Input </h4> | 
|  |  | 
|  | <p>The following table shows the event data that is sent when you type a character, when | 
|  | you delete a character and when you replace two characters with another character. | 
|  |   There is one column for each event object that is sent. The column header shows the | 
|  | event object class and the Step number shown in the flow chart above. </p> | 
|  |  | 
|  | <p>When text changes occur, the <i>VerifyEvent</i> will contain the location of the | 
|  | replaced text (as a start and end offset) and the new text, while the <i>ExtendedModifyEvent</i> | 
|  | will contain the location of the new text (as start and length) and the replaced text. The | 
|  | <i>ModifyEvent</i> is not shown since it does not have any data. </p> | 
|  |  | 
|  | <p>Note that when the <strong>verify key event</strong> is sent in Step 1, the <b>start</b>, | 
|  | <b>end</b> and <b>text </b>fields of its <i>VerifyEvent</i> are not used and are, | 
|  | therefore, not shown in the table. Likewise the <b>character</b>, <b>keyCode</b> and <b>stateMask</b> | 
|  | fields are not used in the <em>VerifyEvent</em> that is created for Step 3. </p> | 
|  |  | 
|  | <p>The second scenario demonstrates that the <i>VerifyKeyListener</i> receives raw | 
|  | keyboard input in the <i>VerifyEvent</i>. The <b>VerifyEvent.character</b> field is set to | 
|  | \u0008, which is the Unicode value of the backspace key. </p> | 
|  |  | 
|  | <table BORDER="1" CELLSPACING="2" CELLPADDING="7" width="801"> | 
|  | <tr> | 
|  | <td WIDTH="149" VALIGN="TOP"><p align="center"><font face="Courier New, Courier, mono"><b>Scenario</b></font></td> | 
|  | <td WIDTH="267" VALIGN="TOP"><p align="center"><font face="Courier New, Courier, mono"><b>VerifyEvent | 
|  | Data (1)<br> | 
|  | sent to VerifyKeyListener</b></font></td> | 
|  | <td WIDTH="247" VALIGN="TOP"><p align="center"><font face="Courier New, Courier, mono"><b>VerifyEvent | 
|  | Data (3)<br> | 
|  | sent to VerifyListener</b></font></td> | 
|  | <td WIDTH="311" VALIGN="TOP"><p align="center"><font face="Courier New, Courier, mono"><b>ExtendedModifyEvent | 
|  | Data (6)</b></font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="149"><font face="Courier New, Courier, mono">User | 
|  | types <br> | 
|  | character 'A' </font> </td> | 
|  | <td WIDTH="267" VALIGN="TOP"><font face="Courier New, Courier, mono">doit | 
|  | = true<br> | 
|  | character = 'A'<br> | 
|  | keyCode = 0<br> | 
|  | stateMask = 0</font> </td> | 
|  | <td WIDTH="247" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | end = 0<br> | 
|  | text = "A"<br> | 
|  | doit = true</font></td> | 
|  | <td WIDTH="311" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | length = 1<br> | 
|  | replacedText = ""</font> </td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="149"><font face="Courier New, Courier, mono">User | 
|  | deletes <br> | 
|  | character 'A' </font> </td> | 
|  | <td WIDTH="267" VALIGN="TOP"><font face="Courier New, Courier, mono">doit | 
|  | = true<br> | 
|  | character = \u0008 (backspace)<br> | 
|  | keyCode = 0<br> | 
|  | stateMask = 0</font> </td> | 
|  | <td WIDTH="247" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | end = 1<br> | 
|  | text = ""<br> | 
|  | doit = true</font></td> | 
|  | <td WIDTH="311" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | length = 0<br> | 
|  | replacedText = "A"</font> </td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="149"><font face="Courier New, Courier, mono">User | 
|  | replaces <br> | 
|  | "AA"<br> | 
|  | with 'B' <br> | 
|  | </font></td> | 
|  | <td WIDTH="267" VALIGN="TOP"><font face="Courier New, Courier, mono">doit | 
|  | = true<br> | 
|  | character = 'B'<br> | 
|  | keyCode = 0<br> | 
|  | stateMask = 0</font> </td> | 
|  | <td WIDTH="247" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | end = 2<br> | 
|  | text = "B"<br> | 
|  | doit = true</font></td> | 
|  | <td WIDTH="311" VALIGN="TOP"><font face="Courier New, Courier, mono">start | 
|  | = 0<br> | 
|  | length = 1<br> | 
|  | replacedText = "AA"</font> </td> | 
|  | </tr> | 
|  | </table> | 
|  |  | 
|  | <h4><a NAME="TextRendering"></a>Text Notification Examples for API Text Changes</h4> | 
|  |  | 
|  | <p>The following table illustrates the data for the change notification events under | 
|  | various API text change scenarios. The Initial Text column shows the text before the | 
|  | change is made. The initial text of one scenario is the changed text of the previous | 
|  | scenario. There is one column for each event object that is sent. The column header for | 
|  | these columns shows the event object class and the Step number shown in the flow chart | 
|  | above.   A ^ character shows the insert point for new text, if any. The text replace | 
|  | range, if any, is highlighted using white text on a blue background.</p> | 
|  |  | 
|  | <p>When text changes occur, the <i>VerifyEvent</i> will contain the location of the | 
|  | replaced text (as a start and end offset) and the new text, while the <i>ExtendedModifyEvent</i> | 
|  | will contain the location of the new text (as start and length) and the replaced text. The | 
|  | <i>ModifyEvent</i> is not shown since it does not have any data.</p> | 
|  | <div align="center"><center> | 
|  |  | 
|  | <table BORDER="1" CELLSPACING="2" CELLPADDING="7" width="856"> | 
|  | <tr> | 
|  | <td WIDTH="192" VALIGN="TOP"><p align="center"><b><font face="Courier New">Scenario</font></b></td> | 
|  | <td WIDTH="243" VALIGN="TOP"><p align="center"><b><font face="Courier New">Initial | 
|  | Text</font></b></td> | 
|  | <td WIDTH="202" VALIGN="TOP"> <p align="center"><b><font face="Courier New">VerifyEvent | 
|  | Data (3)</font></b></td> | 
|  | <td WIDTH="272" VALIGN="TOP"> <p align="center"><b><font face="Courier New">ExtendedModifyEvent | 
|  | Data (6)</font></b></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="192"><font face="Courier New">Insert "sopping | 
|  | " <br> | 
|  | before "wet" </font> </td> | 
|  | <td WIDTH="243" VALIGN="TOP"><pre><font face="Courier New">Getting your feet wet | 
|  | ^</font></pre></td> | 
|  | <td WIDTH="202" VALIGN="TOP"><font face="Courier New">start = 18<br> | 
|  | end = 18<br> | 
|  | text = "sopping "</font></td> | 
|  | <td WIDTH="272" VALIGN="TOP"><font face="Courier New">start = 18<br> | 
|  | length = 8<br> | 
|  | replacedText = ""</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="192"><font face="Courier New">Delete "y"</font></td> | 
|  | <td WIDTH="243" VALIGN="TOP"><font face="Courier New">Getting <span | 
|  | style="background-color: #000080"><font color="#FFFFFF">y</font></span>our | 
|  | feet sopping wet<br> | 
|  | </font></td> | 
|  | <td WIDTH="202" VALIGN="TOP"><font face="Courier New">start = 8<br> | 
|  | end = 9<br> | 
|  | text = ""</font></td> | 
|  | <td WIDTH="272" VALIGN="TOP"><font face="Courier New">start = 8<br> | 
|  | length = 0<br> | 
|  | replacedText = "y"</font></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td VALIGN="top" width="192"><font face="Courier New">Replace "our" <br> | 
|  | with "my"</font></td> | 
|  | <td WIDTH="243" VALIGN="TOP"><pre><font face="Courier New">Getting <font | 
|  | color="#FFFFFF"><span style="background-color: #000080">our</span></font> feet sopping wet | 
|  | ^</font></pre></td> | 
|  | <td WIDTH="202" VALIGN="TOP"><font face="Courier New">start = 8<br> | 
|  | end = 11<br> | 
|  | text = "my"</font></td> | 
|  | <td WIDTH="272" VALIGN="TOP"><font face="Courier New">start = 8<br> | 
|  | length = 2<br> | 
|  | replacedText = "our"</font></td> | 
|  | </tr> | 
|  | </table> | 
|  | </center></div> | 
|  |  | 
|  | <p>Note that, as discussed above, you could change the replace range and the new text that | 
|  | are passed in the <i>Veri</i><em>fyE</em><i>vent</i>. For example, in the first scenario | 
|  | you could change the end offset of the replace range to 21 in order to replace the word | 
|  | "wet" and change the new text to "damp". The result would be | 
|  | "Getting your feet damp". </p> | 
|  |  | 
|  | <pre><font COLOR="#7f0000">	// This handler will change feet that are about to get "sopping" wet to "damp" feet. | 
|  | </font>	<font | 
|  | COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> verifyText(VerifyEvent event) { | 
|  | <font | 
|  | COLOR="#00007f">if</font> ((event.start == 18) && (event.end == 18) && (event.text.equals(<font | 
|  | COLOR="#007f7f">"sopping")</font>)) { | 
|  | event.end = 21; | 
|  | event.text = <font | 
|  | color="#008080">"damp"</font>; | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <p>You could also set the <b>VerifyEvent.doit</b> field to false if you don't want to get | 
|  | sopping feet at all.</p> | 
|  |  | 
|  | <pre>	// This handler will prevent attempts to insert the word "sopping". | 
|  | <font | 
|  | COLOR="#00007f">public</font> <font COLOR="#00007f">void</font> verifyText(VerifyEvent event) { | 
|  | <font | 
|  | COLOR="#00007f">if</font> (event.text.equals(<font COLOR="#007f7f">"sopping"</font>)) { | 
|  | event.doit = <font | 
|  | color="#000080">false</font>; | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <h3>Text Refresh</h3> | 
|  |  | 
|  | <p>Whenever the same text is redrawn at the same location in the <i>StyledText</i> widget, | 
|  | you will see flashing. Flash occurs because the <i>StyledText</i> widget first clears the | 
|  | area to be drawn and then draws the text and its styles. Since nothing has changed, the | 
|  | redraw operation is perceived as a flash.</p> | 
|  |  | 
|  | <p>In order to avoid flash, you should minimize the amount of redrawing that occurs in the | 
|  | widget. Unnecessary redrawing can occur when you use the <b>setStyleRange</b> API if the | 
|  | style you specify overlaps existing styles with the same colors and font style. The <em>StyledText</em> | 
|  | widget does not check for duplicate styles, so the entire style range will be redrawn and | 
|  | unchanged text will be refreshed. For the same reason you should also avoid replacing existing styles | 
|  | with the same styles when using the <b>replaceStyleRanges</b> API.</p> | 
|  |  | 
|  | <p>For efficiency reasons, the <i>StyledText</i> widget does not perform duplicate style | 
|  | optimizations.  Users of the <em>StyledText</em> widget will most likely set styles | 
|  | in the <i>ExtendedModifyListener</i>.  Since this listener is time-sensitive (i.e., | 
|  | it is called every time a keystroke is entered), the <em>StyledText</em> widget avoids | 
|  | superfluous processing when styles are specified. Duplicate style optimizations could also | 
|  | mask application problems.  If an application is creating duplicate styles, this | 
|  | could be a symptom of a larger problem with the application’s logic. </p> | 
|  |  | 
|  | <p>Similar refresh rules apply to the <b>setLineBackground</b> API. If you specify line | 
|  | background colors that already exist, you will see flash when unnecessary redrawing | 
|  | occurs. Besides reducing flash, avoiding unnecessary redrawing will also improve | 
|  | performance since less text will be rendered.</p> | 
|  |  | 
|  | <h3><a name="KeyBindings"></a>Key Bindings</h3> | 
|  |  | 
|  | <p>You can change and query the default key bindings using the <b>setKeyBinding</b>(<b>int | 
|  | key, int action) </b>and<b> getKeyBinding(int key)</b> methods. The <b>setKeyBinding</b> | 
|  | method takes a key code or character ORed with one or more of the modifiers <b>SWT.CTRL</b>, | 
|  | <b>SWT.SHIFT</b> or <b>SWT.ALT</b> as the first argument. SWT.java defines constants for | 
|  | some of the frequently used key codes (e.g., <b>SWT.BS</b> for the backspace key). The | 
|  | second argument is one of the actions defined in ST.java (e.g., <dfn><b>ST. | 
|  | DELETE_PREVIOUS</b></dfn>). Thus, to map <CTRL>+<b> to work like the backspace | 
|  | key and delete the character in front of the caret you would use </p> | 
|  |  | 
|  | <pre>	widget.setKeyBinding(SWT.CTRL | <font color="#008080">‘b’</font>, ST.DELETE_PREVIOUS)</pre> | 
|  |  | 
|  | <p>You can map more than one  key to a single action, but one key can never trigger | 
|  | more than one action. If you use an already bound key combination to trigger a different | 
|  | action, the existing binding will be removed. </p> | 
|  |  | 
|  | <p>To remove a key binding you specify <b>SWT.NULL</b> as the action. For example, if you | 
|  | want to remove the default key binding for <CTRL>+<PAGE UP>, which by default | 
|  | moves the caret in front of the first character of the current page, you would use </p> | 
|  |  | 
|  | <pre>	widget.setKeyBinding(SWT.CTRL | SWT.PAGE_UP, SWT.NULL)</pre> | 
|  |  | 
|  | <p>To find out which action is triggered by default when <CTRL>+<HOME> is | 
|  | pressed you would use </p> | 
|  |  | 
|  | <pre>	widget.getKeyBinding(SWT.CTRL | SWT.HOME)</pre> | 
|  |  | 
|  | <p>which returns ST.TEXT_START (sets the caret in front of the first character of the | 
|  | text). </p> | 
|  |  | 
|  | <p>In addition to the <b>setKeyBinding</b> API, you can use the <b>invokeAction </b>method | 
|  | with one of the actions defined in <em>ST.java</em> to invoke an action independent of | 
|  | keyboard input or to handle multi-key actions. For example, to implement Emacs style | 
|  | multi-key actions you could use a <i>VerifyKeyListener</i> to listen for a key sequence | 
|  | and call <b>invokeAction</b> to perform the desired action. Multi-key actions are actions | 
|  | that require two separate keystrokes, where the first keystroke establishes the context | 
|  | for the second keystroke. The following code snippet demonstrates how to implement a | 
|  | multi-key action. We assume that there is a boolean class variable called<strong> | 
|  | previousCtrlX</strong> that we use to store whether the most recent keystroke was a | 
|  | <CTRL>+<X>.</p> | 
|  |  | 
|  | <pre><font color="#840000">	// </font><font color="#7f0000">This </font><font | 
|  | color="#800000">VerifyKeyListener </font><font color="#7f0000">implements multi-keystrokes using <CTRL>+<X> as the | 
|  | </font><font | 
|  | color="#840000">	// first keystroke and <P> as the second</font><font | 
|  | color="#7f0000"> keystroke. These keystroke are ignore | 
|  | </font><font color="#840000">	<font | 
|  | color="#7f0000">// by the StyledText widget</font> since we set the VerifyEvent.doit field to false. | 
|  | </font><font | 
|  | color="#7f0000"><font COLOR="#000000">widget.addVerifyKeyListener(</font><font | 
|  | COLOR="#000084">new</font> VerifyKeyListener() { | 
|  | </font><font COLOR="#000000">		</font><font | 
|  | color="#7f0000"><font COLOR="#000084">public</font> <font COLOR="#000084">void</font> </font>verifyKey(VerifyEvent event) { | 
|  | <font | 
|  | color="#800000">			// check whether the current keystroke is a <CTRL>+<X></font> | 
|  | <font | 
|  | COLOR="#000084">boolean</font><font COLOR="#000000"> isCtrlX = (event.stateMask == SWT.CTRL) && (event.character == </font><font | 
|  | COLOR="#008484">'\u0018'</font>)<font COLOR="#000000">; | 
|  | </font> | 
|  | <font COLOR="#7f0000">   </font>     		<font | 
|  | COLOR="#840000">// select one page if the previous keystroke was <CTRL>+<X> and | 
|  | // the current keystroke is 'P' | 
|  | </font><font | 
|  | COLOR="#7f0000"><font COLOR="#000084">if</font><font COLOR="#000000"> (</font></font>previousCtrlX<font | 
|  | COLOR="#7f0000"><font COLOR="#000000"> && Character.toUpperCase(event.character) == </font><font | 
|  | COLOR="#008484">'P'</font>) { | 
|  | </font><font COLOR="#000000">				widget.invokeAction(ST.SELECT_PAGE_DOWN); | 
|  | </font><font | 
|  | COLOR="#7f0000">// ignore the second key of a multi-keystroke</font><font COLOR="#000000"> | 
|  | </font><font | 
|  | COLOR="#7f0000">				<font COLOR="#000000">event.doit = </font><font COLOR="#000084">false</font>;</font> | 
|  | <font | 
|  | COLOR="#7f0000">			</font>} <font color="#000080">else</font><font COLOR="#000084"> if</font><font | 
|  | COLOR="#7f0000"> (</font><font COLOR="#000000">isCtrlX) { | 
|  | </font><font COLOR="#840000"><font | 
|  | COLOR="#7f0000">// ignore </font><CTRL>+<X> <font COLOR="#7f0000">key stroke</font>s</font><font | 
|  | color="#000000"> | 
|  | <font COLOR="#7f0000">   </font></font>     		<font COLOR="#7f0000"><font | 
|  | color="#000000">event.doit = </font><font COLOR="#000084">false</font>; </font><font | 
|  | color="#000000">		</font><font COLOR="#7f0000"><font COLOR="#840000"> | 
|  | </font><font | 
|  | color="#000000">   </font></font>     		<font color="#000000">} | 
|  | previousCtrlX = isCtrlX; | 
|  | </font>		} | 
|  | });</pre> | 
|  |  | 
|  | <p>When pressing <CTRL>+<X> followed by hitting <P> the example | 
|  | application looks like this</p> | 
|  |  | 
|  | <p align="center"><img border="0" src="Image6.gif" width="200" height="100"></p> | 
|  |  | 
|  | <p align="left">Any other <CTRL>+<X> multi-keystroke will result in the second | 
|  | key being inserted in the widget since we only filter out the <P> key combination.</p> | 
|  |  | 
|  | <h3><a name="KeyBindings"></a>Conclusion</h3> | 
|  |  | 
|  | <p>In this article we've covered how to do the following within the <em>StyledText</em> | 
|  | widget: | 
|  |  | 
|  | <ul> | 
|  | <li>create the widget</li> | 
|  | <li>define and set text styles</li> | 
|  | <li>handle text changes</li> | 
|  | <li>manage <em>Color</em> objects</li> | 
|  | <li>define key bindings</li> | 
|  | </ul> | 
|  |  | 
|  | <p>These functions cover basic text editing and rendering behavior.  However, if your | 
|  | application has specialized editing or rendering needs, the <em>StyledText</em> widget can | 
|  | be customized.  In our next article, we will go into depth about why you may want to | 
|  | customize the <em>StyledText</em> widget and how you would do this.</p> | 
|  | </body> | 
|  | </html> |