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

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

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

    BaNg@taobao

    Just Do It!

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      20 Posts :: -1 Stories :: 202 Comments :: 0 Trackbacks
    在桌面系統中,拖拽是一個用戶很喜歡的功能。Eclipse主要由view和Editor組成,相互之間的拖拽需求很常見,一般主要是將view(tree/table)的東西拖到text/graphical editor。我寫一個簡單的例子,將一個view里的對象拖到text editor和graphical editor完成插入,其中text editor使用CDT提供的C++ Editor,而graphical editor使用shapes example(GEF SDK) 提供的shapes editor(為方便稍加改造)。

    第一步:建立domain model,這個model里只包含block,一個GenericBlock和它的兩個子類ConstantBlock和LoopBlock。在C++編輯器拖拽中,ConstantBlock用來插入const int XX = 0;之類的語句,LoopBlock用來插入for循環;圖形模式下,ConstantBlock插入一個矩形,而LoopBlock插入一個橢圓形,正好對應shaps example的兩種圖形。

    Generic Block

    public abstract class GenericBlock implements IAdaptable {
        
    protected String name;
        
    //
        abstract protected String getNativeStatement();

        
    public Object getAdapter(Class adapter) {
            
    return Platform.getAdapterManager().getAdapter(this, adapter);
        }
    }

     ConstantBlock常量塊:

    public class ConstantBlock extends GenericBlock {
         .
    //
        protected String getNativeStatement() {
            
    return "const int "+name+" = 999;";
        }

    }

    LoopBlock循環塊:

    public class LoopBlock extends GenericBlock {
        .
    //
        protected String getNativeStatement() {
            
    return "for (int i = 0; i < 100; i++) \n\t for (int j = i; j > 0; j--) \n\t\tprintf(\"i+j=%d\\n\",i*j);";
        }
    }


    第二步:通過Eclipse adapter factory,將block適配成text editor和graphica editor想要的對象,分別為string和產生shape對象的CreationFactory。

    Extension:

       <extension
             
    id="com.lifesting.scratch.blockadapter"
             name
    ="BLOCkAdapter"
             point
    ="org.eclipse.core.runtime.adapters">
          
    <factory
                
    adaptableType="com.lifesting.scratch.views.GenericBlock"
                class
    ="com.lifesting.scratch.ExtractCAdapterFactory">
             
    <adapter
                   
    type="com.lifesting.scratch.views.IRetriveCStructure">
             
    </adapter>
             
    <adapter
                   
    type="org.eclipse.gef.requests.CreationFactory">
             
    </adapter>
          
    </factory>
       
    </extension>

    Adapter Factory:

    public class ExtractCAdapterFactory implements IAdapterFactory {

        @Override
        
    public Object getAdapter(Object adaptableObject, Class adapterType) {
            
    if (adapterType == IRetriveCStructure.class)
                
    return new DspExtractAdapter((GenericBlock) adaptableObject);
            
    if (adapterType == CreationFactory.class)
                
    return new BlockCreationFactoryAdapter((GenericBlock)adaptableObject);
            
    return null;
        }

        @Override
        
    public Class[] getAdapterList() {
            
    return new Class[]{IRetriveCStructure.class,CreationFactory.class};
        }
    }

    DspExtractAdatper只是簡單調用block.getNativeStatement,而傳遞給GEF Editor的將是CreationFactory,它被TemplateTransferDropTargetListener用來完成模型插入/圖形更新。

    DspExtractAdatper

    //IRetriveCStructure只定義了一個getStructure操作,用來得到C代碼
    public class DspExtractAdapter implements IRetriveCStructure {
        
    private GenericBlock block;
        
        
    public DspExtractAdapter(GenericBlock block) {
            
    super();
            
    this.block = block;
        }

        @Override
        
    public String getStructure() {
            
    return block.getNativeStatement();
        }
    }


    BlockCreationFactoryAdatper:(常量塊--矩形,循環塊--橢圓形)

    public class BlockCreationFactoryAdapter implements CreationFactory {
        
    private GenericBlock block;

        
    public BlockCreationFactoryAdapter(GenericBlock adaptableObject) {
            block 
    = adaptableObject;
        }

        @Override
        
    public Object getNewObject() {
            Shape shape;
            
    if (block instanceof ConstantBlock)
                shape 
    = new RectangularShape();
            
    else
                shape 
    = new EllipticalShape();
            shape.setName(block.getName());
            
    return shape;
        }

        @Override
        
    public Object getObjectType() {
            
    if (block instanceof ConstantBlock)
                
    return RectangularShape.class;
            
    else
                
    return EllipticalShape.class;
        }
    }


    第三步:建一個view,完成拖拽的源,這個view里面包含一個tree viewer,使用的是一個簡單的tree input(見下效果圖)。首先是把它顯示出來:
        public void createPartControl(Composite parent) {
            viewer 
    = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
            viewer.setContentProvider(
    new TreeNodeContentProvider(){});
            viewer.setLabelProvider(
    new LabelProvider(){
                @Override
                
    public String getText(Object element) {
                    Object v 
    = ((TreeNode)element).getValue();
                    
    if (v instanceof String)
                        
    return (String) v;
                    
    return ((GenericBlock)v).getName();
                }
            });
            viewer.setInput(getTreeModel());
            hookDrag(viewer);   
        }
    在swt中,拖拽(drag-drop)有三要素 drag source, transfer, drop target,下面依次定義:

    drag(使用了兩個transfer,分別給text和graphics使用的,一般drag過程中應保持domain model即block的純潔性,然后根據不同目標適配):

        private void hookDrag(final TreeViewer viewer2) {
            viewer2.addDragSupport(DND.DROP_COPY 
    |DND.DROP_DEFAULT, new Transfer[]{BlockTransfer.getInstance(),TemplateTransfer.getInstance()}, new DragSourceListener(){
                @Override
                
    public void dragFinished(DragSourceEvent event) {
                }
                @Override
                
    public void dragSetData(DragSourceEvent event) {
                    TreeNode object 
    = (TreeNode) ((IStructuredSelection)viewer2.getSelection()).getFirstElement();
                    event.data 
    = object.getValue();
                }
                @Override
                
    public void dragStart(DragSourceEvent event) {
                    TreeNode object 
    = (TreeNode) ((IStructuredSelection)viewer2.getSelection()).getFirstElement();
                    
    boolean drag_block =  object.getValue() instanceof GenericBlock;
                    event.doit 
    = drag_block;
                }});
        }

    Transfer,沒有什么特殊的,所有Transfer的寫法都是一個套路。

    public class BlockTransfer extends ByteArrayTransfer {
        .
        @Override
        
    protected Object nativeToJava(TransferData transferData) {
            
    if (!isSupportedType(transferData)) return null;
            
    byte[] bts = (byte[]) super.nativeToJava(transferData);
                
    //略,將byte[]轉化為Java對象
        }
        @Override
        
    protected void javaToNative(Object object, TransferData transferData) {
            
    if (!(object instanceof GenericBlock))
                
    return;
            GenericBlock block 
    = (GenericBlock) object;
            
    //略,將block轉化為byte[]
            
        }
            .
    }
    要使用drop,首先必須得在target(text editor/graphical editor)上注冊才能使用。這兒使用Eclipse提供PartListener,每當一個編輯器打開或者激活是,判斷能不能成為drop target,能的話就把drop注冊上。

     1     private IPartListener listener = new IPartListener(){
     2         @Override
     3         public void partActivated(IWorkbenchPart part) {
     4             if (part instanceof ITextEditor)
     5             {
     6                 ITextEditor editor = (ITextEditor) part;
     7                 Control editor_control = (Control) editor.getAdapter(Control.class);
     8                 DropTarget dropTarget= (DropTarget)editor_control.getData(DND.DROP_TARGET_KEY);
     9                 if (dropTarget == null)
    10                     dropTarget= new DropTarget(editor_control, DND.DROP_DEFAULT | DND.DROP_COPY );
    11                 if (Boolean.TRUE != dropTarget.getData(KEY))
    12                         hookDrop(dropTarget);                
    13             }
    14         }
    15         @Override
    16         public void partBroughtToTop(IWorkbenchPart part) {}
    17         @Override
    18         public void partClosed(IWorkbenchPart part) {}
    19         @Override
    20         public void partDeactivated(IWorkbenchPart part) {}        
    21         void hookDrop(DropTarget dropTarget)
    22         {
    23             Transfer[] currentTransfers= dropTarget.getTransfer();
    24             int currentLength= currentTransfers.length;
    25             Transfer[] newTransfers= new Transfer[currentLength + 1];
    26             System.arraycopy(currentTransfers, 0, newTransfers, 0, currentLength);
    27             newTransfers[currentLength]= BlockTransfer.getInstance();
    28             dropTarget.setTransfer(newTransfers);
    29             dropTarget.addDropListener(drop_listener);
    30             dropTarget.setData(KEY, Boolean.TRUE);
    31         }
    32         @Override
    33         public void partOpened(IWorkbenchPart part) {
    34             if (part instanceof ITextEditor)
    35             {
    36                 ITextEditor editor = (ITextEditor) part;
    37                 Control editor_control = (Control) editor.getAdapter(Control.class);
    38                 DropTarget dropTarget= (DropTarget)editor_control.getData(DND.DROP_TARGET_KEY);
    39                 if (dropTarget == null)
    40                     dropTarget= new DropTarget(editor_control, DND.DROP_DEFAULT | DND.DROP_COPY );
    41                 hookDrop(dropTarget);                
    42             }
    43         }
    44     };

    29行加了一個drop listener,即target響應drop操作,最終實現拖拽效果。
     1     private DropTargetListener drop_listener =  new DropTargetAdapter(){
     2         @Override
     3         public void drop(DropTargetEvent event) {
     4             if (!BlockTransfer.getInstance().isSupportedType(event.currentDataType)) return;
     5             GenericBlock block = (GenericBlock) event.data;
     6             IRetriveCStructure cs = (IRetriveCStructure) block.getAdapter(IRetriveCStructure.class);
     7             if (cs != null)
     8             {
     9                 Control ctrl = ((DropTarget)event.widget).getControl();
    10                 if (ctrl instanceof StyledText)
    11                 {
    12                     ((StyledText)ctrl).insert(cs.getStructure());
    13                 }
    14             }
    15         }
    16         @Override
    17         public void dragOver(DropTargetEvent event) {
    18             event.feedback = DND.FEEDBACK_SELECT;
    19         }
    20     };
    注意18行的feedback,沒有它就不能完成在text editor的插入。
    等等,怎么drop listener里面沒有關于shapes edtior的東西,怎樣在shapes editor里面插入shapes呢?

    第四步:改造shapes example。GEF SDK里面提供了一個很好的drop listener-- TemplateTransferDropTargetListener,當從palette 往diragam拖拽得時候使用的就是它,而這里從自定義view往diagram拖拽還是要用到它,為了更形象,在shape里面加了一個屬性name,把name顯示在每個shape的中央。

    public abstract class Shape extends ModelElement {
        
    private static IPropertyDescriptor[] descriptors;
        
    //
        protected String name="Null";

        
    public String getName() {
            
    return name;
        }
        
    public void setName(String name) {
            
    this.name = name;
            }
        
    //
    }

    class ShapeEditPart extends AbstractGraphicalEditPart {
         
    //
        
    //修改這個方法,加入shape name
        private IFigure createFigureForModel() {
        IFigure figure;
        
    if (getModel() instanceof EllipticalShape) {
            figure 
    = new Ellipse();
        } 
    else if (getModel() instanceof RectangularShape) {
            figure 
    = new RectangleFigure();
            
        } 
    else {
            
    // if Shapes gets extended the conditions above must be updated
            throw new IllegalArgumentException();
        }
        figure.setLayoutManager(
    new BorderLayout());
        figure.add(
    new Label(((Shape)getModel()).getName()),BorderLayout.CENTER);
        
    return figure;
            
    //
    }

    為了讓shapes editor使用block適配的creation factory,還需要修改一下shapes editor。

    public class ShapesEditor 
        
    extends GraphicalEditorWithFlyoutPalette 
    {
         
    //
        private TransferDropTargetListener createTransferDropTargetListener() {
        
    return new TemplateTransferDropTargetListener(getGraphicalViewer()) {
            
    protected CreationFactory getFactory(Object template) {
                
    if (template instanceof IAdaptable)
                {
                    CreationFactory factory 
    = (CreationFactory) ((IAdaptable)template).getAdapter(CreationFactory.class);
                    
    if (factory != nullreturn factory;
                }
                
    return new SimpleFactory((Class) template);
            }
        };
        
    //
    }

    這樣一個非常完整的例子就完成了。效果圖如下,其中曲線表示由某一端拖拽而成,可以看出,自定義view并不影響palette拖拽。






    posted on 2008-11-22 01:27 Always BaNg. 閱讀(2536) 評論(3)  編輯  收藏 所屬分類: JavaEclipseC++

    Feedback

    # re: 插件開發: 將View里面的對象托拽到Editor步驟 2012-04-13 14:19 Kako
    您好
    因為本人最近也在研究這方面的開發
    不支能否和您要這個程式的source code參考一下?
    感激不盡
    我的email: kako0507@gmail.com  回復  更多評論
      

    # re: 插件開發: 將View里面的對象托拽到Editor步驟[未登錄] 2013-04-01 23:18 **
    IRetriveCStructure 沒有定義!!!!!!!!
      回復  更多評論
      

    # re: 插件開發: 將View里面的對象托拽到Editor步驟 2014-09-05 10:24 reader
    您好!
    我對這個功能很敢興趣,不知可否發份源碼給我?  回復  更多評論
      

    主站蜘蛛池模板: 综合一区自拍亚洲综合图区| 美女羞羞喷液视频免费| 成年人免费观看视频网站| 亚洲国产成人精品激情| 免费A级毛片无码A∨男男| 十八禁视频在线观看免费无码无遮挡骂过| 91情国产l精品国产亚洲区| 日本一道高清不卡免费| 免费成人高清在线视频| 亚洲av无码片vr一区二区三区| 亚洲日本va在线视频观看| 免费无码A片一区二三区| 中国内地毛片免费高清| 国产精品亚洲精品| 亚洲精品制服丝袜四区| 99久久免费精品国产72精品九九 | A毛片毛片看免费| 亚洲av永久无码精品三区在线4| 亚洲成av人片在线观看天堂无码| 国产激情免费视频在线观看| 激情无码亚洲一区二区三区| 亚洲av不卡一区二区三区| 中文字幕精品无码亚洲字 | 亚洲中文字幕久久精品无码A| 国产亚洲福利一区二区免费看| 亚洲一区免费观看| 美女一级毛片免费观看| 亚洲一区中文字幕在线观看| 亚洲色婷婷综合久久| 免费观看四虎精品国产永久| 日韩不卡免费视频| 久久久久成人片免费观看蜜芽| 国产偷国产偷亚洲高清人| 亚洲一本之道高清乱码| 亚洲成人激情在线| 亚洲一区二区三区无码中文字幕| 日韩免费福利视频| 成人免费无码大片a毛片| 1区2区3区产品乱码免费| 国色精品va在线观看免费视频| 粉色视频成年免费人15次|