| <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> |