<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en" xmlns="http://www.w3.org/2005/Atom"><title>Recent posts to blog</title><link href="https://sourceforge.net/p/etinyplugins/blog/" rel="alternate"/><link href="https://sourceforge.net/p/etinyplugins/blog/feed.atom" rel="self"/><id>https://sourceforge.net/p/etinyplugins/blog/</id><updated>2016-11-25T20:56:38.817000Z</updated><subtitle>Recent posts to blog</subtitle><entry><title>Add Undo/Redo Support to your SWT StyledText-s discussion</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2016-11-25T20:56:38.817000Z</published><updated>2016-11-25T20:56:38.817000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net9b55a67f7f32f46e94992e37a3fd1ee9f908d0ee</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Hi Günther, thanks for sharing your thoughts. The extension you propose seems like a pretty nice challenge, but probably doable - one "only" needs to pick up the applied StyleRange-s from inside the text change listener and reapply them on undo/redo. Have you managed to implement some reasonable solution?&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>Add Undo/Redo Support to your SWT StyledText-s discussion</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2016-11-25T20:55:51.094000Z</published><updated>2016-11-25T20:55:51.094000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net085b94d852cc1950bf62c6a76526c2afa1422fd0</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Hi Günther, thanks for sharing your thoughts. The extension you propose seems like a pretty nice challenge, but probably doable - one "only" needs to pick up the applied StyleRange-s from inside the text change listener and reapply them on undo/redo. Have you managed to implement some reasonable solution?&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>Add Undo/Redo Support to your SWT StyledText-s discussion</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2016-03-27T11:21:48.020000Z</published><updated>2016-03-27T11:21:48.020000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net3cfeb03f03dd364bf078636ff91a3f2310caa373</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Hi, thanks for this discussion which I only found out about now.&lt;/p&gt;
&lt;p&gt;I'm currently working on a rich text editor for swt that should even include hyperlink ability. &lt;/p&gt;
&lt;p&gt;The problem that I see with either of the proposed solutions is that neither of them takes into account the styled ranges. They only replace the text but if I for example had a removed text in bold and then I undo my removal the text will be reappear normal not bold. &lt;/p&gt;
&lt;p&gt;This is something that for example Microsoft Word can do: restore the rich text attributes and a good solution should be able to do that as well. &lt;/p&gt;
&lt;p&gt;I'm not sure yet which way to go but probably both of the mentioned possibilies could work: either write one's own solution or use the TextViewerUndoManager and register a listener there. Any way cache the style ranges at undo and reinsert them at redo into the StyledText.&lt;/p&gt;
&lt;p&gt;Günther&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>In Short: TextTools 2.3.0 is out</title><link href="https://sourceforge.net/p/etinyplugins/blog/2015/06/in-short-texttools-230-is-out/" rel="alternate"/><published>2015-06-27T13:05:34.262000Z</published><updated>2015-06-27T13:05:34.262000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net7465a4b2f69f67085b9da30a6429e7aad77b5480</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;New in version 2.3.0 (2015-06-27):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add: &lt;a class="" href="https://sourceforge.net/p/etinyplugins/tickets/1"&gt;ticket #1&lt;/a&gt; Sum Hours To Add Field also for JIRA tasks.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</summary></entry><entry><title>In Short: TextTools 2.2.0 is out</title><link href="https://sourceforge.net/p/etinyplugins/blog/2014/05/in-short-texttools-220-is-out/" rel="alternate"/><published>2014-05-24T20:58:33.198000Z</published><updated>2014-05-24T20:58:33.198000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net670a7da10b3eea5c42d06b656f8f63e2e14701c7</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;New in version 2.2.0 (2014-05-24):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;update: Sum Hours command - consider also 'en dash' like time separator in evaluated text.&lt;/li&gt;
&lt;li&gt;add: changes.xml - insert current date into generated  element (previous alternative without date remains available too).&lt;/li&gt;
&lt;li&gt;update: changes.xml - don't escape quotes in the  element content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks colleagues for their feedback :)&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>Add Undo/Redo Support to your SWT StyledText-s discussion</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2014-05-23T08:32:41.183000Z</published><updated>2014-05-23T08:32:41.183000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net60f709d182e185f38a3c2d2c3a70e6953a293aaf</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Jan, thanks for the tip, it looks viable. One should only be aware that "Clients are supposed to instantiate a text viewer and subsequently to communicate with it exclusively using the ITextViewer interface or any of the implemented extension interfaces." (taken from javadoc).&lt;/p&gt;
&lt;p&gt;And sorry for the late approval of your comment, just noticed now the need to approve comments... :)&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>Add Undo/Redo Support to your SWT StyledText-s discussion</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2014-01-07T12:00:48.242000Z</published><updated>2014-01-07T12:00:48.242000Z</updated><author><name>Anonymous</name><uri>https://sourceforge.net/u/userid-None/</uri></author><id>https://sourceforge.netdbdeaf028de196f787c063adf6b820418ecb995c</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Nice code. An alternative is to wrap it with a TextViewer and use the JFace TextViewerUndoManager.&lt;/p&gt;
&lt;p&gt;Jan&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>In short: Update site available</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/09/in-short-update-site-available/" rel="alternate"/><published>2013-09-08T21:20:03.588000Z</published><updated>2013-09-08T21:20:03.588000Z</updated><author><name>Petr Bodnár</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.net459b3f5d5f9b3dca1652355b7fe6b85ef32a6e1a</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;p&gt;Good news :) Manual download of the individual Eclipse Tiny Plugins into the Eclipse &lt;code&gt;dropins&lt;/code&gt; (or &lt;code&gt;plugins&lt;/code&gt; if you are courageous) folder is no longer necessary. From now on you can use the standard Eclipse &lt;strong&gt;update site&lt;/strong&gt; functionality for installing the plugins. The update site is to be found at this URL: &lt;code&gt;http://sourceforge.net/projects/etinyplugins/files/update-site/&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;</summary></entry><entry><title>Add Undo/Redo Support to your SWT StyledText-s</title><link href="https://sourceforge.net/p/etinyplugins/blog/2013/02/add-undoredo-support-to-your-swt-styledtext-s/" rel="alternate"/><published>2013-02-04T11:10:16.103000Z</published><updated>2013-02-04T11:10:16.103000Z</updated><author><name>Petr Bodnar</name><uri>https://sourceforge.net/u/userid-2130456/</uri></author><id>https://sourceforge.netc182dfb45d55884d1731cd0b26db3ab7a424b140</id><summary type="html">&lt;div class="markdown_content"&gt;&lt;h1 id="motivation"&gt;Motivation&lt;/h1&gt;
&lt;p&gt;Once again, I found a nice tool (namely the &lt;a class="" href="https://sourceforge.net/projects/regex-util/"&gt;Regex Util&lt;/a&gt; plug-in, thanks for sharing! :)) for Eclipse, which is working well but is missing one fundamental feature...&lt;/p&gt;
&lt;p&gt;For me, this feature is the wide-spread &lt;strong&gt;Undo-Redo functionality in text fields&lt;/strong&gt; and areas. The fact that this functionality is missing is not really a bug of the plug-in, it's just that the SWT &lt;a class="" href="http://www.eclipse.org/swt/widgets/"&gt;StyledText&lt;/a&gt; component which the plug-in utilizes simply &lt;a class="" href="http://stackoverflow.com/questions/7179464/swt-how-to-recreate-a-default-context-menu-for-text-fields"&gt;doesn't support Undo-Redo&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="path-to-solution"&gt;Path to solution&lt;/h1&gt;
&lt;p&gt;And once again, I have found it surprisingly easy to implement this feature. The solution doesn't integrate with the Eclipse's editing history (the 'Edit' menu) and it doesn't provide pop-up menu contributions. But this is not really necessary when you just want to have &lt;strong&gt;Ctrl+Z&lt;/strong&gt; and &lt;strong&gt;Ctrl+Y&lt;/strong&gt; functioning in particular text fields of a plug-in view.&lt;/p&gt;
&lt;p&gt;After lots of googling, I found only one example code (&lt;a class="" href="http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTUndoRedo.htm"&gt;SWT Undo Redo&lt;/a&gt;) on how to implement it. And after several "WTF"-s, I concluded that it is really just an example - a concept which the reader himself is expected to make functional. So I did...&lt;/p&gt;
&lt;h1 id="enough-theory-show-me-the-code"&gt;Enough theory, show me the code&lt;/h1&gt;
&lt;p&gt;Together with a little abstraction of the Undo-Redo stack (later, we could e. g. extend it with a logic of limiting maximum Undo steps count), we can put all the logic in just one class like this:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="n"&gt;etinyplugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;swt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Stack&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.SWT&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.custom.ExtendedModifyEvent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.custom.ExtendedModifyListener&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.custom.StyledText&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.events.KeyEvent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.swt.events.KeyListener&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt; * Adds the Undo-Redo functionality (working Ctrl+Z and Ctrl+Y) to an instance&lt;/span&gt;
&lt;span class="cm"&gt; * of {@link StyledText}.&lt;/span&gt;
&lt;span class="cm"&gt; * &lt;/span&gt;
&lt;span class="cm"&gt; * @author Petr Bodnar&lt;/span&gt;
&lt;span class="cm"&gt; * @see {@linkplain http&lt;/span&gt;
&lt;span class="cm"&gt; *      ://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTUndoRedo.htm} -&lt;/span&gt;
&lt;span class="cm"&gt; *      inspiration for this code, though not really functioning - it mainly&lt;/span&gt;
&lt;span class="cm"&gt; *      shows which listeners to use...&lt;/span&gt;
&lt;span class="cm"&gt; * @see {@linkplain http&lt;/span&gt;
&lt;span class="cm"&gt; *      ://stackoverflow.com/questions/7179464/swt-how-to-recreate&lt;/span&gt;
&lt;span class="cm"&gt; *      -a-default-context-menu-for-text-fields} -&lt;/span&gt;
&lt;span class="cm"&gt; *      &amp;quot;SWT's StyledText doesn't support Undo-Redo out-of-the-box&amp;quot;&lt;/span&gt;
&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UndoRedoImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;KeyListener&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExtendedModifyListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Encapsulation of the Undo and Redo stack(s), where each Undo/Redo step is&lt;/span&gt;
&lt;span class="cm"&gt;     * recorded as a delta from the previous state (a counterpart class, if ever&lt;/span&gt;
&lt;span class="cm"&gt;     * needed, could be called SnapshotUndoRedo - with more logic like&lt;/span&gt;
&lt;span class="cm"&gt;     * 'automatically push snapshot to Redo stack after popping Undo'&lt;/span&gt;
&lt;span class="cm"&gt;     * integrated).&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DeltaUndoRedo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DeltaUndoRedo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;undo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;redo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pushUndo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pushRedo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;popUndo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;popRedo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;clearRedo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;hasUndo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;hasRedo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;StyledText&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;DeltaUndoRedo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ExtendedModifyEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isUndo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isRedo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Creates a new instance of this class. Automatically starts listening to&lt;/span&gt;
&lt;span class="cm"&gt;     * corresponding key and modify events coming from the given&lt;/span&gt;
&lt;span class="cm"&gt;     * &amp;lt;var&amp;gt;editor&amp;lt;/var&amp;gt;.&lt;/span&gt;
&lt;span class="cm"&gt;     * &lt;/span&gt;
&lt;span class="cm"&gt;     * @param editor&lt;/span&gt;
&lt;span class="cm"&gt;     *            the text field to which the Undo-Redo functionality should be&lt;/span&gt;
&lt;span class="cm"&gt;     *            added&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UndoRedoImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StyledText&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addExtendedModifyListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addKeyListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeltaUndoRedo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ExtendedModifyEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;     * (non-Javadoc)&lt;/span&gt;
&lt;span class="cm"&gt;     * &lt;/span&gt;
&lt;span class="cm"&gt;     * @see&lt;/span&gt;
&lt;span class="cm"&gt;     * org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.&lt;/span&gt;
&lt;span class="cm"&gt;     * KeyEvent)&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;keyPressed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyEvent&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Listen to CTRL+Z for Undo, to CTRL+Y or CTRL+SHIFT+Z for Redo&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isCtrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stateMask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SWT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CTRL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isAlt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stateMask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SWT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ALT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isCtrl&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isAlt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isShift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stateMask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SWT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SHIFT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;isShift&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'z'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;isShift&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'y'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;isShift&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'z'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;     * (non-Javadoc)&lt;/span&gt;
&lt;span class="cm"&gt;     * &lt;/span&gt;
&lt;span class="cm"&gt;     * @see&lt;/span&gt;
&lt;span class="cm"&gt;     * org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events&lt;/span&gt;
&lt;span class="cm"&gt;     * .KeyEvent)&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;keyReleased&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyEvent&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ignore&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Creates a corresponding Undo or Redo step from the given event and pushes&lt;/span&gt;
&lt;span class="cm"&gt;     * it to the stack. The Redo stack is, logically, emptied if the event comes&lt;/span&gt;
&lt;span class="cm"&gt;     * from a normal user action.&lt;/span&gt;
&lt;span class="cm"&gt;     * &lt;/span&gt;
&lt;span class="cm"&gt;     * @param event&lt;/span&gt;
&lt;span class="cm"&gt;     * @see org.eclipse.swt.custom.ExtendedModifyListener#modifyText(org.eclipse.&lt;/span&gt;
&lt;span class="cm"&gt;     *      swt.custom.ExtendedModifyEvent)&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;modifyText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExtendedModifyEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isUndo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pushRedo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// is Redo or a normal user action&lt;/span&gt;
            &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pushUndo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;isRedo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clearRedo&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="c1"&gt;// TODO Switch to treat consecutive characters as one event?&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Performs the Undo action. A new corresponding Redo step is automatically&lt;/span&gt;
&lt;span class="cm"&gt;     * pushed to the stack.&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasUndo&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;isUndo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;revertEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;popUndo&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;isUndo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Performs the Redo action. A new corresponding Undo step is automatically&lt;/span&gt;
&lt;span class="cm"&gt;     * pushed to the stack.&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;redo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasRedo&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;isRedo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;revertEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;popRedo&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;isRedo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;     * Reverts the given modify event, in the way as the Eclipse text editor&lt;/span&gt;
&lt;span class="cm"&gt;     * does it.&lt;/span&gt;
&lt;span class="cm"&gt;     * &lt;/span&gt;
&lt;span class="cm"&gt;     * @param event&lt;/span&gt;
&lt;span class="cm"&gt;     */&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;revertEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExtendedModifyEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceTextRange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replacedText&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// (causes the modifyText() listener method to be called)&lt;/span&gt;

        &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSelectionRange&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replacedText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And all one needs to change in an existing code base is to add a call to the constructor of &lt;code&gt;UndoRedoImpl&lt;/code&gt;, passing it the instance of the to-be-extended editor (text):&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UndoRedoImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="cm"&gt;/* instance of StyledText */&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Yes, it really is that simple. The SWT API-s for the modify event and for text manipulations go together nicely.&lt;/p&gt;
&lt;p&gt;And what do YOU think? Can't there be any hidden gotchas in this solution?&lt;/p&gt;&lt;/div&gt;</summary></entry></feed>