<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Thinker

      - long way to go...

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      24 隨筆 :: 0 文章 :: 143 評論 :: 0 Trackbacks
        StyledText是SWT包中的一個基礎組件,就像它的名字定義的那樣,通過它可以顯示各式各樣的字體。但是StyledText沒有提供Undo/Redo的功能,很是讓人不爽,下面給一個簡單的例子,演示在StyledText增加Undo/Redo操作,同時在這個自定義的StyledText中增加了刪除選中文本、清除全部文本的動作支持。
        思路很簡單,就是監聽文本內容更改事件,然后根據更改的內容生成Undo操作存入Undo操作棧中,在Undo操作棧中維護了兩個列表UndoList和RedoList,當發出Undo操作命令的時候,從Undo操作列表中取出一個Undo操作,執行其undo()方法,然后將其放入Redo操作列表中。如果發出Redo操作命令,就從Redo操作列表中出一個Redo操作,執行其redo()方法,然后將其放入Undo操作列表中。
        本篇文章只是給出了一個簡單的演示示例,需要改進的地方是監聽文本更改時,應該采用一定的規則策略來生成Undo操作,否則每輸入或者刪除一個字符都會創建一個Undo操作,這樣就會產生非常多的Undo操作,并且也不符合日常使用習慣。日后有時間的話我會整理一下改進的版本發布出來。如果你有興趣也可以研究一下。
        另外由于StyledText的invokeAction()方法中Action的動作不夠充足,致使無法用setKeyBinding()方法方便的將快捷鍵與執行動作綁定,通過重寫StyledText中的invokeAction()方法可以定制某些自己的動作,完善StyledText的功能。

    下面是Undo操作管理器UndoManager的代碼:
      1 import org.eclipse.core.commands.ExecutionException;
      2 import org.eclipse.core.commands.operations.AbstractOperation;
      3 import org.eclipse.core.commands.operations.IOperationHistory;
      4 import org.eclipse.core.commands.operations.IUndoContext;
      5 import org.eclipse.core.commands.operations.ObjectUndoContext;
      6 import org.eclipse.core.commands.operations.OperationHistoryFactory;
      7 import org.eclipse.core.runtime.IAdaptable;
      8 import org.eclipse.core.runtime.IProgressMonitor;
      9 import org.eclipse.core.runtime.IStatus;
     10 import org.eclipse.core.runtime.Status;
     11 import org.eclipse.swt.custom.ExtendedModifyEvent;
     12 import org.eclipse.swt.custom.ExtendedModifyListener;
     13 import org.eclipse.swt.custom.StyledText;
     14 
     15 /**
     16  * 管理Undo操作,用于監聽文本域的文本改變事件,生成Undo操作并記錄。<br>
     17  * 
     18  * @author qujinlong
     19  */
     20 public class UndoManager
     21 {
     22   /*
     23    * 用于存儲歷史Undo操作,每改變一次文本內容,就將構造一個Undo操作存入OperationHistory中。
     24    */
     25   private final IOperationHistory opHistory;
     26 
     27   /*
     28    * Undo操作上下文,一般用于在OperationHistory中查找當前文本框的Undo操作。
     29    */
     30   private IUndoContext undoContext = null;
     31 
     32   /*
     33    * 所要監聽的需要實現Undo操作的文本框。
     34    */
     35   private StyledText styledText = null;
     36 
     37   private int undoLevel = 0;
     38 
     39   public UndoManager(int undoLevel)
     40   {
     41     opHistory = OperationHistoryFactory.getOperationHistory();
     42 
     43     setMaxUndoLevel(undoLevel);
     44   }
     45 
     46   public void setMaxUndoLevel(int undoLevel)
     47   {
     48     this.undoLevel = Math.max(0, undoLevel);
     49 
     50     if (isConnected())
     51       opHistory.setLimit(undoContext, this.undoLevel);
     52   }
     53 
     54   public boolean isConnected()
     55   {
     56     return styledText != null;
     57   }
     58 
     59   /*
     60    * 將Undo管理器與指定的StyledText文本框相關聯。
     61    */
     62   public void connect(StyledText styledText)
     63   {
     64     if (! isConnected() && styledText != null)
     65     {
     66       this.styledText = styledText;
     67 
     68       if (undoContext == null)
     69         undoContext = new ObjectUndoContext(this);
     70 
     71       opHistory.setLimit(undoContext, undoLevel);
     72       opHistory.dispose(undoContext, truetruefalse);
     73 
     74       addListeners();
     75     }
     76   }
     77 
     78   public void disconnect()
     79   {
     80     if (isConnected())
     81     {
     82       removeListeners();
     83 
     84       styledText = null;
     85 
     86       opHistory.dispose(undoContext, truetruetrue);
     87 
     88       undoContext = null;
     89     }
     90   }
     91 
     92   private ExtendedModifyListener extendedModifyListener = null;
     93 
     94   private boolean isUndoing = false;
     95 
     96   /*
     97    * 向Styled中注冊監聽文本改變的監聽器。
     98    * 
     99    * 如果文本改變,就構造一個Undo操作壓入Undo操作棧中。
    100    */
    101   private void addListeners()
    102   {
    103     if (styledText != null)
    104     {
    105       extendedModifyListener = new ExtendedModifyListener() {
    106         public void modifyText(ExtendedModifyEvent event)
    107         {
    108           if (isUndoing)
    109             return;
    110 
    111           String newText = styledText.getText().substring(event.start,
    112               event.start + event.length);
    113 
    114           UndoableOperation operation = new UndoableOperation(undoContext);
    115 
    116           operation.set(event.start, newText, event.replacedText);
    117 
    118           opHistory.add(operation);
    119         }
    120       };
    121 
    122       styledText.addExtendedModifyListener(extendedModifyListener);
    123     }
    124   }
    125 
    126   private void removeListeners()
    127   {
    128     if (styledText != null)
    129     {
    130       if (extendedModifyListener != null)
    131       {
    132         styledText.removeExtendedModifyListener(extendedModifyListener);
    133 
    134         extendedModifyListener = null;
    135       }
    136     }
    137   }
    138 
    139   public void redo()
    140   {
    141     if (isConnected())
    142     {
    143       try
    144       {
    145         opHistory.redo(undoContext, nullnull);
    146       }
    147       catch (ExecutionException ex)
    148       {
    149       }
    150     }
    151   }
    152 
    153   public void undo()
    154   {
    155     if (isConnected())
    156     {
    157       try
    158       {
    159         opHistory.undo(undoContext, nullnull);
    160       }
    161       catch (ExecutionException ex)
    162       {
    163       }
    164     }
    165   }
    166 
    167   /*
    168    * Undo操作用于記錄StyledText的文本被改變時的相關數據。
    169    * 
    170    * 比如文本框中本來的文本為111222333,如果此時選中222替換為444(用復制粘帖的方法),
    171    * 
    172    * 則Undo操作中記錄的相關數據為: startIndex = 3; newText = 444; replacedText = 222;
    173    */
    174   private class UndoableOperation extends AbstractOperation
    175   {
    176     // 記錄Undo操作時,被替換文本的開始索引
    177     protected int startIndex = - 1;
    178 
    179     // 新輸入的文本
    180     protected String newText = null;
    181 
    182     // 被替換掉的文本
    183     protected String replacedText = null;
    184 
    185     public UndoableOperation(IUndoContext context)
    186     {
    187       super("Undo-Redo");
    188 
    189       addContext(context);
    190     }
    191 
    192     /*
    193      * 設置Undo操作中要存儲的相關數據。
    194      */
    195     public void set(int startIndex, String newText, String replacedText)
    196     {
    197       this.startIndex = startIndex;
    198 
    199       this.newText = newText;
    200       this.replacedText = replacedText;
    201     }
    202 
    203     /*
    204      * (non-Javadoc)
    205      * 
    206      * @see org.eclipse.core.commands.operations.AbstractOperation#undo(org.eclipse.core.runtime.IProgressMonitor,
    207      *      org.eclipse.core.runtime.IAdaptable)
    208      */
    209     public IStatus undo(IProgressMonitor monitor, IAdaptable info)
    210         throws ExecutionException
    211     {
    212       isUndoing = true;
    213       styledText.replaceTextRange(startIndex, newText.length(), replacedText);
    214       isUndoing = false;
    215 
    216       return Status.OK_STATUS;
    217     }
    218 
    219     /*
    220      * (non-Javadoc)
    221      * 
    222      * @see org.eclipse.core.commands.operations.AbstractOperation#redo(org.eclipse.core.runtime.IProgressMonitor,
    223      *      org.eclipse.core.runtime.IAdaptable)
    224      */
    225     public IStatus redo(IProgressMonitor monitor, IAdaptable info)
    226         throws ExecutionException
    227     {
    228       isUndoing = true;
    229       styledText.replaceTextRange(startIndex, replacedText.length(), newText);
    230       isUndoing = false;
    231 
    232       return Status.OK_STATUS;
    233     }
    234 
    235     /*
    236      * (non-Javadoc)
    237      * 
    238      * @see org.eclipse.core.commands.operations.AbstractOperation#execute(org.eclipse.core.runtime.IProgressMonitor,
    239      *      org.eclipse.core.runtime.IAdaptable)
    240      */
    241     public IStatus execute(IProgressMonitor monitor, IAdaptable info)
    242         throws ExecutionException
    243     {
    244       return Status.OK_STATUS;
    245     }
    246   }
    247 }


    下面是擴展的StyledText類:
      1 import org.eclipse.swt.SWT;
      2 import org.eclipse.swt.custom.ST;
      3 import org.eclipse.swt.custom.StyledText;
      4 import org.eclipse.swt.layout.GridData;
      5 import org.eclipse.swt.layout.GridLayout;
      6 import org.eclipse.swt.widgets.Composite;
      7 import org.eclipse.swt.widgets.Display;
      8 import org.eclipse.swt.widgets.Shell;
      9 
     10 /**
     11  * 自定義的StyledText,增加了Undo、Redo和清除操作。<br>
     12  * 
     13  * @author qujinlong
     14  */
     15 public class MyStyledText extends StyledText
     16 {
     17   /**
     18    * @param parent
     19    * @param style
     20    */
     21   public MyStyledText(Composite parent, int style)
     22   {
     23     super(parent, style);
     24   }
     25 
     26   /*
     27    * (non-Javadoc)
     28    * 
     29    * @see org.eclipse.swt.custom.StyledText#invokeAction(int)
     30    */
     31   public void invokeAction(int action)
     32   {
     33     // 增加一個自定義的刪除操作,只有當選中文本的時候才將文本刪除。
     34     // 否則,ST.DELETE_NEXT會將光標所在位置的后一個字符刪除。
     35     if (action == ActionCode.DELETE && getSelectionCount() > 0)
     36       action = ST.DELETE_NEXT;
     37 
     38     super.invokeAction(action);
     39 
     40     switch (action)
     41     {
     42       case ActionCode.UNDO:
     43         undo();
     44         break;
     45       case ActionCode.REDO:
     46         redo();
     47         break;
     48       case ActionCode.CLEAR:
     49         clear();
     50         break;
     51     }
     52   }
     53 
     54   private void undo()
     55   {
     56     if (undoManager != null)
     57       undoManager.undo();
     58   }
     59 
     60   private void redo()
     61   {
     62     if (undoManager != null)
     63       undoManager.redo();
     64   }
     65 
     66   private void clear()
     67   {
     68     super.setText("");
     69   }
     70 
     71   private UndoManager undoManager = null;
     72 
     73   /**
     74    * @return Returns undoManager.
     75    */
     76   public UndoManager getUndoManager()
     77   {
     78     return undoManager;
     79   }
     80 
     81   /**
     82    * @param undoManager - The undoManager to set.
     83    */
     84   public void setUndoManager(UndoManager undoManager)
     85   {
     86     this.undoManager = undoManager;
     87   }
     88 
     89   /*
     90    * (non-Javadoc)
     91    * 
     92    * @see org.eclipse.swt.widgets.Widget#dispose()
     93    */
     94   public void dispose()
     95   {
     96     if (undoManager != null)
     97       undoManager.disconnect();
     98 
     99     super.dispose();
    100   }
    101 
    102   public static class ActionCode
    103   {
    104     public static final int UNDO = Integer.MAX_VALUE;
    105 
    106     public static final int REDO = UNDO - 1;
    107 
    108     public static final int CLEAR = UNDO - 2;
    109 
    110     public static final int DELETE = UNDO - 3;
    111   }
    112 
    113   public static void main(String[] args)
    114   {
    115     final Display display = Display.getDefault();
    116     final Shell shell = new Shell();
    117     shell.setLayout(new GridLayout());
    118     shell.setSize(420250);
    119     shell.setText("SWT Application");
    120 
    121     MyStyledText styledText = new MyStyledText(shell, SWT.BORDER);
    122     GridData gd_styledText = new GridData(SWT.FILL, SWT.CENTER, falsefalse);
    123     gd_styledText.heightHint = 200;
    124     gd_styledText.widthHint = 400;
    125     styledText.setLayoutData(gd_styledText);
    126 
    127     // Ctrl+C, Ctrl+X, Ctrl+V 都是StyledText的默認行為。
    128 
    129     // styledText.setKeyBinding('C' | SWT.CTRL, ST.COPY);
    130     // styledText.setKeyBinding('V' | SWT.CTRL, ST.PASTE);
    131     // styledText.setKeyBinding('X' | SWT.CTRL, ST.CUT);
    132 
    133     styledText.setKeyBinding('A' | SWT.CTRL, ST.SELECT_ALL);
    134 
    135     styledText.setKeyBinding('Z' | SWT.CTRL, ActionCode.UNDO);
    136     styledText.setKeyBinding('Y' | SWT.CTRL, ActionCode.REDO);
    137     styledText.setKeyBinding('F' | SWT.CTRL, ActionCode.CLEAR);
    138     styledText.setKeyBinding('D' | SWT.CTRL, ActionCode.DELETE);
    139 
    140     UndoManager undoManager = new UndoManager(50);
    141     undoManager.connect(styledText);
    142 
    143     styledText.setUndoManager(undoManager);
    144 
    145     shell.open();
    146 
    147     shell.layout();
    148 
    149     while (! shell.isDisposed())
    150     {
    151       if (! display.readAndDispatch())
    152         display.sleep();
    153     }
    154   }
    155 }
        本示例著重演示如何實現Undo/Redo操作,也可以參見JFace的TextViewer的Undo/Redo操作的實現。
    posted on 2007-06-07 10:25 Long 閱讀(4972) 評論(7)  編輯  收藏 所屬分類: Java

    評論

    # re: 為SWT的StyledText添加Undo、Redo操作 2007-06-07 10:39 Long
    如果想寫純SWT應用程序,可以自己實現一個OperationHistory,實際上就是維護Undo/Redo兩個操作列表/棧。  回復  更多評論
      

    # re: 為SWT的StyledText添加Undo、Redo操作 2007-06-07 12:17 BeanSoft
    貌似可以這里直接用 Swing 的 UNDO/REDO 機制.  回復  更多評論
      

    # re: 為SWT的StyledText添加Undo/Redo操作以及對快捷鍵動作綁定的支持 2007-06-11 12:00 Long
    上次看到網友說貼代碼時不要顯示列號。
    呵呵,顯示列號沒關系,只要用UltraEdit的列模式很容易就刪除掉了。  回復  更多評論
      

    # re: 為SWT的StyledText添加Undo/Redo操作以及對快捷鍵動作綁定的支持 2007-09-07 09:40 wang
    請教下,對小鍵盤回車 綁定快捷鍵 ,怎樣寫代碼呢,忘告知,謝謝  回復  更多評論
      

    # 為SWT的StyledText添加Undo/Redo操作以及對快捷鍵動作綁定的支持 2008-07-15 11:38 zheng1285
    如果還要實現 從網頁上復制過來的粘貼到StyledText中能不能帶它的屬性呢?
    比如它有鏈接、加粗等等。  回復  更多評論
      

    # 為SWT的StyledText添加Undo/Redo操作以及對快捷鍵動作綁定的支持 2008-07-15 11:39 zheng1285
    <B>如果還要實現 從網頁上復制過來的粘貼到StyledText中能不能帶它的屬性呢?
    比如它有鏈接、加粗等等。<B>  回復  更多評論
      

    # re: 為SWT的StyledText添加Undo/Redo操作以及對快捷鍵動作綁定的支持[未登錄] 2014-09-11 14:10 1
    jianren  回復  更多評論
      

    主站蜘蛛池模板: 久久www免费人成精品香蕉 | 亚洲中文字幕在线第六区| 最近免费中文字幕大全免费| 乱爱性全过程免费视频| 亚洲色精品三区二区一区| 自怕偷自怕亚洲精品| 欧洲亚洲国产清在高| www国产亚洲精品久久久日本| 成年女人免费视频播放体验区| 99在线观看视频免费| 免费无码作爱视频| 免费无码婬片aaa直播表情| 久久亚洲精品专区蓝色区| 亚洲精品电影在线| 亚洲国产成人久久综合一 | 黄色免费在线观看网址| 亚洲色偷精品一区二区三区| 亚洲国产av一区二区三区丶| 亚洲韩国在线一卡二卡| 久久亚洲国产精品| 亚洲成A∨人片在线观看不卡| 久久久久噜噜噜亚洲熟女综合| www.亚洲精品| 亚洲男女内射在线播放| 四虎永久免费网站免费观看| 国产成人免费网站在线观看| 国产精品视频免费一区二区三区| 免费看美女让人桶尿口| 麻豆国产精品入口免费观看| 日韩一区二区三区免费体验| 日韩视频免费一区二区三区| 日本一道本高清免费| 国产三级电影免费观看| 国产伦精品一区二区三区免费下载 | 在线看片免费不卡人成视频 | 亚洲国产成人精品无码区在线网站 | 在线播放免费人成视频网站| 一级特级女人18毛片免费视频| h片在线播放免费高清| 久久高潮一级毛片免费| 丁香花在线视频观看免费|