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

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

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

    sharky的點滴積累

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      56 隨筆 :: 104 文章 :: 10 評論 :: 0 Trackbacks

    在目前的GEF版本(3.1M6)里,可用的LayoutManager還不是很多,在新聞組里經常會看到要求增加更多布局的帖子,有人也提供了自己的實現,例如這個GridLayout,相當于SWT中GridLayout的Draw2D實現,等等。雖然可以肯定GEF的未來版本里會增加更多的布局供開發者使用(可能需要很長時間),然而目前要用GEF實現表格的操作還沒有很直接的辦法,這里說說我的做法,僅供參考。

    實現表格的方法決定于模型的設計,初看來我們似乎應該有這些類:表格(Table)、行(Row)、列(Column)和單元格(Cell),每個模型對象對應一個EditPart,以及一個Figure,TablePart應該包含RowPart和ColumnPart,問題是RowFigure和ColumnFigure會產生交叉,想象一下你的表格該使用什么樣的布局才能容納它們?使用這樣的模型并非不能實現(例如使用StackLayout),但我認為這樣的模型需要做的額外工作會很多,所以我使用基于列的模型。

    在我的表格模型里,只有三種對象:Table、Column和Cell,但Column有一個子類HeaderColumn表示第一列,同時Cell有一個子類HeaderCell表示位于第一列里的單元格,后面這兩個類的作用主要是模擬實現對行的操作--把對行的操作都轉換為對HeaderCell的操作。例如,創建一個新行轉換為在第一列中增加一個新的單元格,當然在這同時我們要讓程序給其余每一列同樣增加一個單元格。

    geftable.gif
    圖1 表格編輯器

    現在的問題就是怎樣讓用戶察覺不到我們是在對單元格而不是對行操作。需要修改的地方有這么幾處:一是創建新行或改變行位置時顯示與行寬一致的插入提示線,二是在用戶點擊位于第一列中的單元格(HeaderCell)時顯示為整個行被選中,三是允許用戶通過鼠標拖動改變行高度,最后是在改變行所在位置或大小的時候顯示正確的回顯(Feedback)圖形。下面依次介紹它們的實現方法。

    調整插入線的寬度

    在我們的調色板里有一個Row工具項,代表表格中的一個行,它的作用是創建新的行。注意這個工具項的名字雖然叫Row,實際上用它創建的是一個HeaderCell對象,創建它的代碼如下:

    tool = new CombinedTemplateCreationEntry("Row", "Create a new Row", HeaderCell.class, new SimpleFactory(HeaderCell.class), CbmPlugin.getImageDescriptor(IConstants.IMG_ROW), null);

    創建新行的方式是從調色板里拖動它到想要的位置。在拖動過程中,隨著鼠標所在位置的變化,編輯器應該能顯示一條直線,用來表示如果此時放開鼠標新行將插入的位置。由于這個工具代表的是一個單元格,所以缺省情況下GEF會顯示一條與單元格長度相同的插入線,為了讓用戶感覺到是在插入行,我們必須改變插入線的寬度。具體的方法是在HeaderColumnPart的負責Layout的那個EditPolicy(繼承FlowLayoutEditPolicy)中覆蓋showLayoutTargetFeedback()方法,修改后的代碼如下:

    protected void showLayoutTargetFeedback(Request request) {
        super.showLayoutTargetFeedback(request);
        
    // Expand feedback line's width
        Diagram diagram = (Diagram) getHost().getParent().getModel();
        Column column 
    = (Column) getHost().getModel();
        Point p2 
    = getLineFeedback().getPoints().getPoint(1);
        p2.x 
    = p2.x + (diagram.getColumns().size() - 1* (column.getWidth() + IConstants.COLUMN_SPACING);
        getLineFeedback().setPoint(p2, 
    1);
    }

    其中p2代表插入線中右邊的那個點,我們將它的橫坐標加上一個量即可增加這條線的長度,這個量和表格當前列的數目有關,和列間距也有關,計算的方法看上面的代碼很清楚。這樣修改后的效果如下圖所示,拖動行到新的位置時也會使用同樣的插入線。

    insertline.gif
    圖2 與表格同寬的插入線

    選中整個行

    缺省情況下,鼠標點擊一個單元格會在這個單元格四周產生一個黑色的邊框,用來表示被選中的狀態。為了讓用戶能選中整個行,要修改HeaderCell上的EditPolicy。在前面一篇帖子里已經專門講過,單元格作為列的子元素,要修改它的EditPolicy就要在ColumnPart的EditPolicy的createChildEditPolicy()方法里返回自定義的EditPolicy,這里我返回的是自己實現的DragRowEditPolicy,它繼承自GEF內置的ResizableEditPolicy類,它將被HeaderColumnPart加到子元素HeaderCellPart的EditPolicy列表。現在就來修改DragRowEditPolicy以實現整個行的選中。

    首先要說明,在GEF里一個圖形被選中時出現的黑邊和控制點稱為Handle,其中黑邊稱為MoveHandle,用于移動圖形;而那些控制點稱為ResizeHandle,用于改變圖形的尺寸。要改變黑邊的尺寸(由單元格的寬度擴展為整個表格的寬度),我們得繼承MoveHandle并覆蓋它的getLocator()方法,下面的代碼是我的實現:

    public class RowMoveHandle extends MoveHandle {
        
    public RowMoveHandle(GraphicalEditPart owner, Locator loc) {
            super(owner, loc);
        }

        
    public RowMoveHandle(GraphicalEditPart owner) {
            super(owner);
        }

        
    //計算得到選中行所占的位置,傳給MoveHandleLocator作為參考
        public Locator getLocator() {
            IFigure refFigure 
    = new Figure();
            Rectangle rect
    =((HeaderCellPart) getOwner()).getRowBound();
            translateToAbsolute(rect);
            refFigure.setBounds(rect);
            
    return new MoveHandleLocator(refFigure);
        }

    }

    在getLocator()方法里,我們調用了HeaderCellPart的getRowBound()方法用于得到選中行的位置和尺寸,這個方法的代碼如下(放在HeaderCellPart里是因為在Handle里通過getOwner()可以很容易得到EditPart對象),行尺寸的計算方法與前面插入線的情況類似:

    public Rectangle getRowBound(){
        Rectangle rect 
    = getFigure().getBounds().getCopy();
        Diagram diagram 
    = (Diagram) getParent().getParent().getModel();
        Column column 
    = (Column) getParent().getModel();
        rect.setSize(diagram.getColumns().size() 
    * column.getWidth() + (diagram.getColumns().size() - 1* IConstants.COLUMN_SPACING, rect.getSize().height);
        
    return rect;
    }

    有了這個RowMoveHandle,只要把它代替原來缺省的MoveHandle加到HeaderColumnCell上即可,具體的方法就是覆蓋DragRowEditPolicy的createSelectionHandles()方法,ResizableEditPolicy對這個方法的缺省實現是加一個黑框和八個控制點,而我們要改成下面這樣:

    protected List createSelectionHandles() {
        List l 
    = new ArrayList();
        
    //四周的黑色邊框
        l.add(new RowMoveHandle((GraphicalEditPart) getHost()));
        
    //下方的控制點
        l.add(new RowResizeHandle((GraphicalEditPart) getHost(), PositionConstants.SOUTH));
        
    return l;
    }

    代碼里用到的RowResizeHandle類是控制點的自定義實現,在下面很快會講到。現在,用戶可以看到整個行被選中的效果了。

    rowselection.gif
    圖3 選中整個行

    改變行的高度

    改變行高度比較自然的方式是讓用戶選中行后自由拖動下面的邊。前面說過,GEF里的ResizeHandle具有調整圖形尺寸的功能,美中不足的是ResizeHandle表現為黑色(或白色,非主選擇時)的小方塊,而我們希望它是一條線就好了,這樣鼠標指針只要放在選中行的下邊上就會變成改變尺寸的樣子。這就需要我們實現剛才提到的RowResizeHandle類了,它是ResizeHandle的子類,代碼如下:

    public class RowResizeHandle extends ResizeHandle {
        
    public RowResizeHandle(GraphicalEditPart owner, int direction) {
            super(owner, direction);
            
    //改變控制點的尺寸,使之變成一條線
            setPreferredSize(new Dimension(((HeaderCellPart) owner).getRowBound().width, 2));
        }

        
    public RowResizeHandle(GraphicalEditPart owner, Locator loc, Cursor c) {
            super(owner, loc, c);
        }

        
    //缺省實現里控制點有描邊,我們不需要,所以覆蓋這個方法
        public void paintFigure(Graphics g) {
            Rectangle r 
    = getBounds();
            g.setBackgroundColor(getFillColor());
            g.fillRectangle(r.x, r.y, r.width, r.height);
        }

        
    //與前面RowMoveHandle類似,但返回RelativeHandleLocator以使線顯示在圖形下方
        public Locator getLocator() {
            IFigure refFigure 
    = new Figure();
            Rectangle rect
    =((HeaderCellPart) getOwner()).getRowBound();
            translateToAbsolute(rect);
            refFigure.setBounds(rect);
            
    return new RelativeHandleLocator(refFigure, PositionConstants.SOUTH);
        }

        
    //不論是否為主選擇,都使用黑色填充
        protected Color getFillColor() {
            
    return ColorConstants.black;
        }

    }

    這樣,我們就把控制點拉成了控制線,因為它的位置與選擇框(RowMoveHandle)的一部分重合,所以在界面上感覺不到它的存在,但用戶可以通過它控制行的高度,見下圖。

    rowresize.gif
    圖4 改變行高的提示

    正確的回顯圖形

    我們知道,在拖動圖形和改變圖形尺寸的時候,GEF會顯示一個"影圖"(Ghost Shape)作為回顯,也就是顯示圖形的新位置和尺寸信息。因為操作行時目標對象實際是單元格,所以在缺省情況下回顯也是單元格的樣子(寬度與列寬相同)。為此,在DragRowEditPolicy里要覆蓋getInitialFeedbackBounds()方法,這個方法返回的Rectangle決定了鼠標開始拖動時回顯圖形的初始狀態,見以下代碼:

    protected Rectangle getInitialFeedbackBounds() {
        
    return ((HeaderCellPart) getHost()).getRowBound();
    }

    這時的回顯見下圖,在拖動行時也使用同樣的回顯。

    rowfeedback.gif
    圖5 改變行高時的回顯

    經過上面的修改,對HeaderCell的操作在界面上已經完全表現為對表格行的操作了。這些操作的結果會轉換為一些Command,包括CreateHeaderCellCommand(創建新行,你也可以命名為CreateRowCommand)、MoveHeaderCellCommand(移動行)、DeleteHeaderCellCommand(刪除行)和ChangeHeaderCellHeightCommand(改變行高)等,在這些類里要對所有列執行同樣的操作(例如改變HeaderCell的高度的同時改變同一行中其他單元格的高度),這樣在界面上才能保持表格的外觀,詳細的代碼沒有必要貼在這里了。

    P.S.曾經考慮過另一種實現表格的方法,就是模型里只有Table和Cell兩種對象,然后自己寫一個TableLayout負責單元格的布局。同樣是因為修改的工作量相對比較大而沒有采用,因為那樣的話行和列都要使用自定義方式處理,而這篇貼子介紹的方法只關心行的處理就可以了。當然,這里說的也不是什么標準實現,不過效果還是不錯的,而且確實可以實現,如果你有類似的需求可以作為參考。

    posted on 2005-05-20 10:14 八進制 閱讀(1535) 評論(12)  編輯 收藏 收藏至365Key 所屬分類: Eclipse

    評論

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-20 17:09 pwb
    八進制你好,我寫了個RCP+GEF的程序,GEF是拷貝的eclipse網站上的ShapesDiagram代碼,我實現了自己的IEditorInput--ShapesEditorInput。下面是ShapesEditor的SetInput方法:
    protected void setInput(IEditorInput input) {
    super.setInput(input);
    ShapesEditorInput in = (ShapesEditorInput)input;
    diagram = in.getModel();
    }
    和OpenEidtor
    ShapesEditorInput shapesIn = new ShapesEditorInput();
    shapesIn.setModel(new ShapesDiagram());
    try {
    configurer.getWindow().getActivePage().openEditor(shapesIn, ShapesEditor.ID);
    }
    其它我也將ide和ui的相關依賴項去掉了,但出現這個錯誤
    java.lang.NoClassDefFoundError: org/eclipse/gef/ui/parts/GraphicalEditorWithFlyoutPalette
    和 Unable to instantiate editor,unable to load class。

    能給點建議么?謝謝了。
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-20 18:03 八進制
    找不到GraphicalEditorWithFlyoutPalette類,應該是plugin.xml里對依賴的定義缺少了<import plugin="org.eclipse.gef"/>,或者是GEF版本太舊,需要3.0以上。
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-22 18:44 pwb
    謝謝解答,這是將RCP+GEF(ShapesDiagram)結合的例子的代碼,貼在這里希望和我遇到相同問題的兄弟看到,用火狐瀏覽器打開https://bugs.eclipse.org/bugs/show_bug.cgi?id=91472

      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-24 20:19 freegoldlu
    我現在需要在palette 里面 放置2個 元素 對應一個model但是要根據條件顯示2個不同的figure
    EClass eClass = null;
    eClass = ACMPackage.eINSTANCE.getApplicationComponent();
    combined = new CombinedTemplateCreationEntry(
    "ApplicationComponent",
    "Create a new ApplicationComponent",
    eClass,
    new EObjectTemplateCreationFactory(eClass),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")));
    entries.add(combined);
    eClass = ACMPackage.eINSTANCE.getApplicationComponent();
    combined = new CombinedTemplateCreationEntry(
    "ApplicationComponentGroup",
    "Create a new ApplicationComponentGroup",
    eClass,
    new EObjectTemplateCreationFactory(eClass),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")));
    entries.add(combined);
    只是顯示的label不同,我想在editpart 或policy中得到不同的label名字 (ApplicationComponent, applicationComponentGroup)我應該怎么寫 ,謝謝高手幫我解答
    今天debug了一天 頭都大了 。。。

      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-24 21:06 八進制
    我覺得有兩個辦法:
    一個是建兩個類都繼承你現在的這個ApplicationComponent,對應兩個editpart,問題就簡單多了;
    另一個是通過你的EObjectTemplateCreationFactory把label名字傳給模型,比如給它的構造方法增加一個String類型的參數,在getNewObject()方法里把參數的值賦給模型實例。
      

    # 感謝 2005-05-25 09:57 freegoldlu
    按照第2種方法 ,解決問題 非常感謝 :) 如果在policy 或 editpart中 想獲得當前palette 中 被選中項的 label ,就是"ApplicationComponentGroup"

    "ApplicationComponent" 這兩個字符串 應該怎么寫?
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-05-25 13:09 八進制
    試試EditPart.getViewer().getEditDomain().getActiveTool()
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-07-11 17:08 陳哲
    我的0Eclipse里邊的程序的字體全是黑的,不知道再么回事,

    特來請教高手 希望給于指導 謝謝
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-07-11 22:08 八進制
    不知道你用的是哪個版本的eclipse,到preferences的General->Appearence->Colors and Fonts里設置一下看看?
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-08-01 16:21 Px
    浩哥這篇文章寫得好,很透徹
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-08-17 11:03 新手
    eclipse上的VE palette插件面板老是消失了看不到,在哪里可以再次打開顯示它?希望能夠得到樓上大俠們的幫助,謝謝!
      

    # re: [Eclipse]GEF入門系列(十、表格的一個實現) 2005-08-17 12:51 八進制
    是否縮成一個豎條了,如果是按一下豎條上方的黑色三角就可以打開;另一種情況是在選項里隱藏了,試試window-show view里打開palette視圖。我沒用過VE,說的是一般GEF程序的情況。
      
    posted on 2005-08-26 17:15 sharky的點滴積累 閱讀(414) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 蜜桃AV无码免费看永久| 国产美女精品久久久久久久免费 | 日韩一区二区三区免费体验| 无遮挡国产高潮视频免费观看| 亚洲日本va在线视频观看| 99国产精品永久免费视频| 一级全免费视频播放| 亚洲理论片在线观看| 国产一卡二卡≡卡四卡免费乱码| 久久精品视频免费| 亚洲Av无码国产一区二区| 亚洲首页在线观看| 亚洲国产成人久久综合一区77| 91精品国产免费入口| 日产久久强奸免费的看| 亚洲精品美女久久久久| 亚洲美女在线国产| 无码国产精品久久一区免费| 久久免费香蕉视频| 亚洲爆乳大丰满无码专区| 久久亚洲中文字幕精品有坂深雪 | 97亚洲熟妇自偷自拍另类图片| 国产成人免费高清在线观看| 日韩精品人妻系列无码专区免费| 日本亚洲中午字幕乱码| 亚洲激情黄色小说| 亚洲成AV人片在WWW色猫咪 | 久久亚洲精品中文字幕| 国产亚洲老熟女视频| 四虎影院在线免费播放| 91精品成人免费国产片| 免费无码又爽又刺激网站| 春暖花开亚洲性无区一区二区| 亚洲啪啪免费视频| 亚洲A∨无码无在线观看| 国产午夜亚洲精品理论片不卡| 日韩精品免费电影| 在线观看特色大片免费视频| 99热精品在线免费观看| 国产午夜免费高清久久影院| 一区二区三区免费在线观看|