nighty

          折騰的年華
          posts - 37, comments - 143, trackbacks - 0, articles - 0

          保存你的RCP視圖狀態(tài)

          Posted on 2007-10-30 15:51 寒武紀 閱讀(8685) 評論(0)  編輯  收藏 所屬分類: Eclipse

              每當做開發(fā)的時候,你有可能在一次調(diào)試程序的過程中打開很多個編輯器,或是對Eclipse默認的視圖布局不滿意,手工作了一些調(diào)整。如果在工作的過程你因為有事離開或是不小心把Eclipse關掉了,不用擔心,在你下次打開的時候,Eclipse仍然會為您記住上次的工作場景。下面是一個例子場景:
              
                Eclipse會記住“包資源管理器”的當前展開元素、被選中元素、視圖大小、位置、過濾、排序等狀態(tài)。不止于視圖和編輯器,Eclipse還提供了對全局狀態(tài)的持久化機制。包括向?qū)В珹ction等
                GUI狀態(tài)持久化不是必須的,只是一種可選的增強功能。一個完整的復雜的產(chǎn)品,特別是針對IDE類型的RCP,這個特征就顯得比較人性化。
                下面介紹一些個人的實踐心得,愿大家有所收獲,主要是針對視圖(IViewPart)。
                 一般視圖都是繼承自ViewPart類或是實現(xiàn)IViewPart接口,在ViewPart中可以發(fā)現(xiàn)有
                  

          /**
               * Initializes this view with the given view site.  A memento is passed to
               * the view which contains a snapshot of the views state from a previous
               * session.  Where possible, the view should try to recreate that state
               * within the part controls.
               * <p>
               * This method is automatically called by the workbench shortly after the part 
               * is instantiated.  It marks the start of the views's lifecycle. Clients must 
               * not call this method.
               * </p>
               *
               * 
          @param site the view site
               * 
          @param memento the IViewPart state or null if there is no previous saved state
               * 
          @exception PartInitException if this view was not initialized successfully
               
          */

              
          public void init(IViewSite site, IMemento memento) throws PartInitException;

              
          /**
               * Saves the object state within a memento.
               *
               * 
          @param memento a memento to receive the object state
               
          */

              
          public void saveState(IMemento memento);

              這二個方法就是實現(xiàn)界面狀態(tài)持久化的關鍵,注意saveState方法是在IPersistable接口中定義的。這些我們暫時忽略,主要是看如何使用這些機制。
              如果去看JDT的實現(xiàn)或是org.eclipse.ui.ide一些視圖的實現(xiàn),你可以發(fā)現(xiàn)一些比較常用的實現(xiàn)形式。下面先看一段示例

              private IMemento fmemento;
              
              
          /* 視圖持久化狀態(tài)標識 */
              
          private static final String TAG_SELECTION = "selection"//$NON-NLS-1$
              private static final String TAG_EXPANDED = "expanded"//$NON-NLS-1$
              private static final String TAG_ELEMENT = "element";//$NON-NLS-1$
              private static final String TAG_PATH = "path"//$NON-NLS-1$
              
              
          public void init(IViewSite site, IMemento memento) throws PartInitException {
                  
          super.init(site, memento);
                  
          this.fmemento = memento;
              }

              這是重寫你自定義視圖的init方法,定義一個全局的IMemento對象,初始化的時候為它賦值。并定義一系列的標識常量,用來表示你要保存的數(shù)據(jù)的標識。這一點與IDialogSettings是一致的。
              下面是保存視圖實現(xiàn)代碼,如果你第一次接觸可能有點暈,不過沒關系,熟悉了以后你會發(fā)現(xiàn)Eclipse的內(nèi)部實現(xiàn)也是類似的。下面的代碼就是從Eclipse里面改過來的。

          /**
               * 保存視圖狀態(tài)
               * <p>在此沒有過濾和排序功能,所以只要保存展開節(jié)點的狀態(tài)和選中節(jié)點的狀態(tài)就夠了</p>
               
          */

              
          public void saveState(IMemento memento) {
                  System.out.println(
          "保存視圖");
                   
          //save visible expanded elements
                  Object expandedElements[] = viewer.getVisibleExpandedElements();
                  
          if (expandedElements.length > 0{
                      IMemento expandedMem 
          = memento.createChild(TAG_EXPANDED);
                      
          for (int i = 0; i < expandedElements.length; i++{
                          
          if (expandedElements[i] instanceof ITestNode) {
                              System.out.println(
          "展開元素 " +((ITestNode)expandedElements[i]).getPath());
                              IMemento elementMem 
          = expandedMem
                                      .createChild(TAG_ELEMENT);
                              elementMem.putString(TAG_PATH,
                                      ((ITestNode) expandedElements[i]).getPath());
                          }

                      }

                  }

                  
          //save selection
                  Object elements[] = ((IStructuredSelection) viewer.getSelection())
                          .toArray();
                  
          if (elements.length > 0{
                      IMemento selectionMem 
          = memento.createChild(TAG_SELECTION);
                      
          for (int i = 0; i < elements.length; i++{
                          
          if (elements[i] instanceof ITestNode) {
                              System.out.println(
          "選中元素 " +((ITestNode)elements[i]).getPath());
                              IMemento elementMem 
          = selectionMem
                                      .createChild(TAG_ELEMENT);
                              elementMem.putString(TAG_PATH,
                                      ((ITestNode) elements[i]).getPath());
                          }

                      }

                  }

                  System.out.println(
          "保存視圖完成");
              }

              要保存的數(shù)據(jù)是key--value形式,可以定義Boolean Integer Float String等基本類型對應的值,這些值就以key--value形式持久化到文件中。
              上面的實現(xiàn)內(nèi)容其實就是把視圖中的樹組件中的二部分狀態(tài)轉(zhuǎn)換成數(shù)據(jù):展開元素和被選中元素。通過把它們轉(zhuǎn)換成String類型(其實就是樹路徑)保存起來。IMemento的具體用法請查找Eclipse幫助文檔。
              完成了保存,下面我們看如何重新把數(shù)據(jù)取出來,使得打開的時候還原之前關閉時的狀態(tài)。
              init()方法調(diào)用的時候界面控件是還沒有被創(chuàng)建的,所以不能在init()方法中添加還原的方法,應用在控件都創(chuàng)建完成后還原。
              

          /**
               * 創(chuàng)建視圖的內(nèi)容面板
               
          */

              
          public void createPartControl(Composite parent) {
           ..
           
          if (fmemento != null{
                      System.out.println(
          "開始還原");
                      restoreState(fmemento);
                  }

                  fmemento 
          = null;
           ..
          }

              完成控件創(chuàng)建后就調(diào)用restoreState方法,這是我們自定義的用于還原視圖狀態(tài)的方法。下面看一下,內(nèi)容基本上就是saveState方法的逆向。

              /**
               * 還原視圖的狀態(tài)
               * 
          @param memento
               
          */

              
          private void restoreState(IMemento memento) {
                  System.out.println(
          "還原視圖");
                  WorkSpaceNode wsn 
          = (WorkSpaceNode)viewer.getInput();
                  IMemento childMem 
          = memento.getChild(TAG_EXPANDED);
                  
          if (childMem != null{
                      ArrayList elements 
          = new ArrayList();
                      IMemento[] elementMem 
          = childMem.getChildren(TAG_ELEMENT);
                      
          for (int i = 0; i < elementMem.length; i++{
                          System.out.println(
          "還原展開路徑 " + elementMem[i].getString(TAG_PATH));
                          Object element 
          = NodeUtil.findNodeByPath(elementMem[i]
                                  .getString(TAG_PATH), wsn);
                          System.out.println(
          "還原展開節(jié)點 " + element);
                          
          if (element != null{
                              elements.add(element);
                          }

                      }

                      viewer.setExpandedElements(elements.toArray());
                  }

                  childMem 
          = memento.getChild(TAG_SELECTION);
                  
          if (childMem != null{
                      ArrayList list 
          = new ArrayList();
                      IMemento[] elementMem 
          = childMem.getChildren(TAG_ELEMENT);
                      
          for (int i = 0; i < elementMem.length; i++{
                          Object element 
          = NodeUtil.findNodeByPath(elementMem[i]
                                  .getString(TAG_PATH), wsn);
                          
          if (element != null{
                              list.add(element);
                          }

                      }

                      viewer.setSelection(
          new StructuredSelection(list));
                  }

                  System.out.println(
          "還原視圖完成");
              }

              這些工作就可以完成視圖狀態(tài)的保存與還原,還有一個特別要注意的地方,你必須對插件的WorkbenchAdvisor類的public void initialize(IWorkbenchConfigurer configurer)方法進行重寫,添加configurer.setSaveAndRestore(true);這個方法就可以打開保存機制。如果沒有這個步驟,上面的工作不會起任何效果。
              GUI狀態(tài)的持久化都保存在運行時生成的.metadata\.plugins目錄下的xml文件,你可以手動去打開這些文件查看數(shù)據(jù)結(jié)果是否跟你預期的一樣。IEditorPart以及Perspective和其它的全局信息持久化的也是同樣的原理。只是復雜度不一樣。建議可以查看org.eclipse.ui.ide中的實現(xiàn)原理。

           



          剛進場的時候戲就落幕
          主站蜘蛛池模板: 阿坝县| 镇沅| 安仁县| 白玉县| 福泉市| 南宫市| 米林县| 尼勒克县| 仙居县| 太湖县| 宁乡县| 瑞金市| 茌平县| 勃利县| 巢湖市| 托克逊县| 拉孜县| 巨野县| 霍州市| 遂平县| 呼和浩特市| 全椒县| 邛崃市| 阿拉尔市| 靖安县| 洛隆县| 佛学| 安达市| 永泰县| 孟州市| 广安市| 贵南县| 申扎县| 南投市| 镇远县| 普定县| 金湖县| 阿拉善右旗| 成安县| 重庆市| 胶州市|