邋遢居

我的Java天堂

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  61 Posts :: 2 Stories :: 90 Comments :: 0 Trackbacks

#

 

gef项目中连线一直扮演这个不可或缺的角色。碰巧前段时间有个机会好好的看了这个部分的内容。下面就把我的一点点认识和大家分享。

首先要在模型上支持,能够保存连接的信息。对于不同的项目有不同的要求。我们通过两个例子就可以看出这一点来。

1http://www13.plala.or.jp/observe/GEF/示例中的GEF6.zip (下面称这个例子为HelloWold

运行的结果入下图所示:

hellwoui.jpg

它的模型可以使用如下的类图来表示:

LineConnectionModel-i.jpg

用来描述Connection的分别是LineConnectionModelArrowConnectionModel这两个类。这两个类的父类和图形模型(HellowModel)相关。

2IBM红皮书中的GEF范例(下面称这个例子为workflow)

运行效果如下图:

gefrun.jpg

他的模型可用下面的类图描述:

gefredbook.jpg

其实连接的模型应该很简单,他只要能保存他的两端的对象就好了。图形模型(如HelloWold中的HelloModel)能够保持与他相关连的连接(HelloWold中的LineConnectionModelArrowConnectionModel)。

看完了Model,我们下面就可以看看EditPart部分了。

要看EditPart当然是要看最关键的了。也就是和连接直接关联的EditPart了。分别察看了和连接相关的EditPart,发现他们都会实现一个叫org.eclipse.gef.NodeEditPart的接口。如下图所示:

ShapeEditPart-a.jpg

nodeEditPart中有四个方法需要实现。通过这个四个方法的名字就可以看出他们和Anchor2密切相关。下面就来看看这几个方法的具体功能:

ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection);

当需要画连接的时候,通过这个方法获取连接的源锚点。不管这个锚点在什么位置,他取得以后直接就用它作为源点了。

ConnectionAnchor getSourceConnectionAnchor(Request request);

当在准备创建连接的时候,通过Request来获取新连接的源锚点。

另外的两个就不再啰嗦了。是为了获得目标的锚点。


但是我们肯定看到了HelloWoldWorkflow中的连接有点不一样。HelloWold中直接是图元上的,而workflow是通过连接基本图元上面的一个子图元而连接的。简单来说就是他们连接的anchor有点不一样,这样就会出现执行结果的不同。

下面来看看他们到底是怎么实现的。根据上面提到的。锚点的获取是通过getSourceConnectionAnchorgetTargetConnectionAnchor方法来获取的。我们只需要好好比对一下他们这几个方法的不同就可以了。

HelloWold中的getSourceConnectionAnchor

public ConnectionAnchor getSourceConnectionAnchor(Request request) {

returnnew ChopboxAnchor(getFigure());

}

这里就简单的创建一个 ChopboxAnchor 就好了。这个就可以直接连到该Figure上了。

workflow中这个情况稍微有一点复杂了。先不说,还是看看他的 getSourceConnectionAnchor 是怎么实现的。

public ConnectionAnchor getSourceConnectionAnchor(

ConnectionEditPart connection) {

Connection edge = (Connection) connection.getModel();

return getNodeFigure().getConnectionAnchor(edge.getSource().getName());

}


/**

*returnsananchorgivenitsname

*

*@paramportNamenameoftheanchor

*@returntheanchorwiththename<code>portName</code>

*/

public ConnectionAnchor getConnectionAnchor(String portName) {

return (ConnectionAnchor)connectionAnchors.get( portName );

}


protected Hashtable connectionAnchors = new Hashtable(7);


/**

*Addaninputportanditsanchor

*

*@paramportName

*uniquenametorefertotheport

*/

publicvoid addInput(String portName) {

InputPortFigure inputPort = new InputPortFigure();

add(inputPort);


PortConnectionAnchor anchor = new PortConnectionAnchor(inputPort);

getTargetConnectionAnchors().add(anchor);

connectionAnchors.put(portName, anchor);

}


通过这几个方法可以看出它是在添加Input时候就创建好了一个和PortFigure 相关Anchor并把它保存起来。在要用的时候就把它取出来。这样就搞定了。

具体的可以参考这两个例子的代码。好了,打完收工。


参考文档

IBM 红皮书

1荒野困兽(老脸归来)’blog

2GEF 进阶,第一部分: Anchor


posted @ 2007-01-08 17:09 Jet Geng 阅读(2823) | 评论 (1)编辑 收藏

 

我想在我的EditPartViewer中获取一个图形元素把它拖放到一个swt控件中。实现在<<图形编辑器中拖拽对象到swt控件>>一文有提到了。不过我在处理的时候,并不是按照他的那个方式来做的。我是根据当前点DragSourceEvent的位置来查找该点下的对象。看是否是我需要的对象,如果是就允许拖动。否则就不可以。

问题在这里出来:当没有出现滚动条的时候一切都很正常,当一出现滚动条就死活没有办法拖动了。最后才发现DragSourceEvent中的坐标是按照屏幕来得,而EditPartViewer 中的坐标是按照他的那个viewer来得。这个地方需要转换一下。



这个转换的动作发现在jfireorg.nightlabs.editor2d.util.EditorUtil https://svn.jfire.org/svn/main/trunk/org.nightlabs.editor2d/src/org/nightlabs/editor2d/util/EditorUtil.java)中有现成的。不多说了,拿来用吧。

posted @ 2007-01-05 20:32 Jet Geng 阅读(554) | 评论 (0)编辑 收藏

 

近来看了点Ant的东西,想Ant真的很强。在使用的过程中发现,开发项目的过程中使用到的Ant其实并不多,只是有时候只是需要换一下其中的个别参数就可以重新用了。如果把这些重复的情况,写成不同的build.xml的模板。定制成不同的任务,通过快捷键来调出,最后自动的执行ant脚本。呵呵,想想就是一个很不错的主意。

说干就干了。定义一些Action,和快捷键帮定就不多说了。生成build.xml通过你自己喜欢的代码生成技术(个人喜欢用JET4)定义模板并生成代码。

下面在自动执行Ant脚本的时候卡了一会壳。看到《以编程方式调用 Apache Ant

2 觉得问题已经解决了。不过这种方式是在Eclipse 运行的VM中执行,也就是说会把Eclipse 挂住。我希望达到的效果是和org.eclipse.ant.ui插件达到的效果一样。最好是去调用他了。他是在eclipse默认集成的,直接依赖于他不会有什么问题。看了他plugin.xml发现了一个好东西“org.eclipse.debug.core.launchConfigurationTypes”,所以我就想我创建一个ILaunchConfigurationType 用它来实实例化一个ILaunchConfigurationWorkingCopy是不是就可以搞定了。上网google了一下有个兄弟写完了这个部分的工作1。把他的代码放到一个插件里面简单的跑了一下,果然可行。爽!

 

参考文档:


  1. Eclipse 3.1 Update to “How to run ANT files programmatically”

  2. 以编程方式调用 Apache Anthttp://www.ibm.com/developerworks/cn/websphere/library/techarticles/0502_gawor/0502_gawor.html

  3. 代码范例http://dev.eclipse.org/mhonarc/lists/platform-ant-dev/msg01053.html

  4. http://www.eclipse.org/articles/Article-JET/jet_tutorial1.html

posted @ 2006-12-30 16:13 Jet Geng 阅读(2664) | 评论 (1)编辑 收藏

大家肯定都知道在Eclipse中获得当前活动的workbenchWindow可以采用如下的方式来完成。

PlatformUI.getWorkbench().getActiveWorkbenchWindow()

Plugin类中) getDefault().getWorkbench().getActiveWorkbenchWindow() 。一般情况下这两个方式能够很好的工作。但是突然有一天发现他不能工作了。郁闷我都不行了。察看了一下变量如下图display.jpg

这个activatedWindow明明有啊,怎么就取不到呢。

打开代码一看,看到 org.eclipse.ui.internal.Workbench 类中的 getActiveWorkbenchWindow 方法。

public  IWorkbenchWindow getActiveWorkbenchWindow() {
        
//  Return null if called from a non-UI thread.
        
//  This is not spec'ed behaviour and is misleading, however this is how
        
//  it
        
//  worked in 2.1 and we cannot change it now.
        
//  For more details, see [Bug 57384] [RCP] Main window not active on
        
//  startup
         if  (Display.getCurrent()  ==   null ) {
            
return   null ;
        }

        
//  Look at the current shell and up its parent
        
//  hierarchy for a workbench window.
        Control shell  =  display.getActiveShell();
        
while  (shell  !=   null ) {
            Object data 
=  shell.getData();
            
if  (data  instanceof  IWorkbenchWindow) {
                
return  (IWorkbenchWindow) data;
            }
            shell 
=  shell.getParent();
        }

        
//  Look for the window that was last known being
        
//  the active one
        WorkbenchWindow win  =  getActivatedWindow();
        
if  (win  !=   null ) {
            
return  win;
        }

        
//  Look at all the shells and pick the first one
        
//  that is a workbench window.
        Shell shells[]  =  display.getShells();
        
for  ( int  i  =   0 ; i  <  shells.length; i ++ ) {
            Object data 
=  shells[i].getData();
            
if  (data  instanceof  IWorkbenchWindow) {
                
return  (IWorkbenchWindow) data;
            }
        }

        
//  Can't find anything!
         return   null ;
    }

程序跑到 Display.getCurrent() 这一绝句就给我掉链子(返回了一个 null )。就是他,就是他了!到网上 google 了一下。看看在什么状况下他会返回一个 null. http://wiki.eclipse.org/index.php/FAQ_How_do_I_get_a_Display_instance%3F 找到了。

他说, Display 永远和创建他的线程联系在一起,并且一个线程拥有一个活动的 Display 。在创立 Display 的线程中可可以通过 Display.getCurrent() 获得当前活动的 Display 。如果出了这个线程就看不到这个 Display 了。如果有的线程不拥有 Display ,那它的 Display.getCurrent() 就只能得到 null 了。

回头看了一下我的代码,我是在新建的线程中启动了调用了这个方法。难怪他不给面子呢!


参考文献:

http://wiki.eclipse.org/index.php/FAQ_How_do_I_get_a_Display_instance%3F

http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/Display.html

posted @ 2006-12-04 15:01 Jet Geng 阅读(2653) | 评论 (0)编辑 收藏

以前不知道有Ocl这个东西,前几天有幸看到。深深被他吸引了。抛开其他的不说,就他的查询功能的就让人激动不已了:)

现在只是看了

oclQueryExmaple

Querying EMF Models with OCL


在项目中简单的使用了一下他作为查询的工具。感觉他真的很不错,在下一段时间将会重点去了解他。

posted @ 2006-11-11 20:30 Jet Geng 阅读(732) | 评论 (0)编辑 收藏

    前面一段时间有一个需求就是从swt控件中拖拽对象到图形编辑器中(就是class org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor 的儿子们)编辑器。

后来就想假如我需要从图形编辑器中拖拽对象到swt控件中又该怎么做。
经过一段时间的探索,终于搞定了。

记下如下过程,希望对需要的朋友有点帮助。

首先有了《从SWT控件中托拽对象到GEF编辑器中》文中对addDropTargetListener方法使用的经历,很快就确定我需要对GraphicalViewer添加一个DragSourceListener

想着到这个地方我应该可以很快收工了。但是添加完了以后发现原来的拖动功能都没有了,这个怎么回事。谁在后面搞鬼。

经过一段时间的狂搜滥索终于找到了问题的关键。因为GEF不允许同时有两个活动 DragSource

它本身已经拥有一个DragSource了(编辑器内部的托拽),我们这时候添加一个就会存在多

DragSource了。当我添加一个新的DragSource时候我们新家的DragSource就会被认为是默认的DragSource

他以前的DragSource就失效了。这不是我像看到的。

怎么处理。看到了一个牛人的解决方案。


What I made to fix the problem was to only allow my DragSource to act under certain 
conditions (in my application this happens when you click and drag the mouse AND
 the SHIFT key is pressed). So when the SHIFT key is not pressed my DragSource does
nothing and the editor's internal drag and drop works fine。

public void dragStart(DragSourceEvent event)
{
...

if (!condition.isValid())
event.doit = false;

...
}

我尝试了一下这种状况,一下就搞定了。
在我的项目中,由于还有一些数据需要转化。呵呵,感觉不错。

参考文档:
http://dev.eclipse.org/newslists/news.eclipse.tools.gef/msg15754.html
posted @ 2006-11-11 19:56 Jet Geng 阅读(2961) | 评论 (1)编辑 收藏

前一段日子荒废了很多。现在该是重整旗鼓的时候了。不要在想,不要犹豫,直接做就好了。
嗯,我回来了。
posted @ 2006-11-09 21:53 Jet Geng 阅读(476) | 评论 (0)编辑 收藏

茶艺学习笔记

前两天拜了一个茶艺师父。今天师父正式给我上了一下午的课,感觉收获很多。其实我师父已经给我上过很多课了,不过弟子不怎么好学没有加以整理。今天就把学习到的东西稍微整理一下吧。防止以后会忘了。

先来说说砌茶的三要素吧!

1、水温

水温是指砌茶,水的温度。不同种类的茶对温度的要求不一样。一般来说绿茶类的温度控制在80C90C(不同的茶可能要求有些差别)。红茶、花茶、普洱茶要求水温控制在90C向上。我的理解是从不发酵到发酵的茶,要求的水温是逐步上升的。

砌绿茶的时候如果水温过高,会在短时间内把茶叶烫熟。特别是嫩芽(碧螺春就是一个典型代表)更是如此。

2、茶量

茶量就是放入茶叶的多少。这个师父没有强调太多,这是说不同的茶的要求不一样。一般的用小盖碗砌茶的话8克~10(不同的茶有不同要求)。然后师父留了一句话说,这个要多实践。

3、时间

这个时间是指茶叶在茶汤里浸泡的时间。原则上是第一道在一分钟左右,第二道和第三道的时间在第一道的时间上递减。到了一定的程度以后时间要适当的加长。

具体的趋势可以下面的图表表示:


tea.jpg

横坐标表示茶的道数,纵坐标表示砌茶的时间。这个只是一个趋势,其实里面的数据是不准确的。对于黑茶系(普洱为代表的)的茶冲泡的道数可能会多一点。但是绿茶冲泡的次数就要少一点(34道)。

这张表,表示的只是在说明第一道时候时间茶没有泡开需要的时间要长一点,等第二道,第三道的时候茶泡开了,时间就要相对短一点。但是随着道数的增加,茶会越来越淡。这个时候就需要通过加长时间来弥补这个带来的影响。直到这次茶叶不能再用为止。


posted @ 2006-09-17 23:47 Jet Geng 阅读(1087) | 评论 (0)编辑 收藏

SWT控件中托拽对象到GEF编辑器中

一般情况下GEF程序都是采用如下的界面:


gef.jpg

新建对象的操作时通过拖拽Palette中元素到编辑而获得。但是有时候可能需要从SWT,操作系统拖一些元素到GEF编辑器中来。

下面我就把创建这样的拖拽过程大概的描述一下:

1、定义拖拽源(DragSource)。

2、定义拖拽目标的监听(DropTarget)。

到这里对于一般的拖拽其实是可以完工了。

这个部分可以参考weidagang2046的专栏的《DND入门学习

但是要能让GraphicalViewer这个对象扮演起DropTarget我们还需要做点其他的工作。GraphicalViewer这个类本身提供了一个addDropTargetListener方法。看到这个方法是不是一阵狂喜啊。如果有也是应该的,因为这个方法就是我们解决前面提出问题的关键。

好了看看他的声明吧!

				
						
								public void addDropTargetListener(TransferDropTargetListener listener)
						
				
		

他这个参数居然不是 DropTargetListener 。这个 TransferDropTargetListener 是一个什么玩意啊!

help 中查到:

public interface TransferDropTargetListener
extends TransferDropTargetListener

A DropTragetListener that handles one type of SWT Transfer. The purpose of a TransferDropTargetListener is to:

  • Determine enablement for a Drop operation. Enablement is often a function drop location, and/or criteria.

  • When enabled, optionally showing feedback on the DropTarget.

  • Performing the actualy Drop

DelegatingDropAdapter allows these functions to be implemented separately for unrelated types of Drags. DelegatingDropAdapter then combines the function of each TransferDropTargetListener, while allowing them to be implemented as if they were the only DragSourceListener.

偷下懒,就不翻译了。

创建如下类来实现这个接口:

public class TreeNodeTransferDropTargetListener extends

AbstractTransferDropTargetListener {


public TreeNodeTransferDropTargetListener(EditPartViewer editPartViewer) {

// 改类默认是处理 TextTransfer 类型的拖拽事件

super (editPartViewer,TextTransfer.getInstance());

// TODO Auto-generated constructor stub

}


@Override

protected void updateTargetRequest() {

}


}

我们这个拖拽想是让他执行一个 create 命令。所以下面就是要重载他的 createTargetRequest() 用来处理 create 对象的请求( CreateRequestion )。 CreateRequetion 需要使用到一个类,帮助我们创建对象的工厂类。 GEF 给了我们这样的一个接口 CreationFactory 。下面我们取实现他就好了。


package org.eclipse.gef.examples.shapes.rcp.views;


import org.eclipse.gef.examples.shapes.model.EllipticalShape;

import org.eclipse.gef.requests.CreationFactory;


public class TypeCreationFactory implements CreationFactory {


public Object getNewObject() {

// TODO Auto-generated method stub

EllipticalShape label = new EllipticalShape();

return label;

}


public Object getObjectType() {

return EllipticalShape. class ;

}


}


注意:这里的 getNewObject 是返回要创建类的一个对象实例。 GetObjectType 需要返回需要创建对象的类。这个可不要搞反了。

这样我们就可以把我们的 TreeNodeTransferDropTargetListener 类中的 createTargetRequest 方法加上了。


private TypeCreationFactory factory = new TypeCreationFactory();

protected Request createTargetRequest() {

CreateRequest request = new CreateRequest();

request.setFactory( factory );

return request;

}


好了这个时候不要客气了,加上

protected void handleDragOver() {

getCurrentEvent(). detail = DND. DROP_MOVE |DND. DROP_COPY ;

super .handleDragOver();

}


@Override

protected void handleDrop() {

//String s = (String)getCurrentEvent().data;

//factory.setText(s);

super .handleDrop();

}

这样的方法吧。

这样这个功能就完成了。


参考文献:

http://www.blogjava.net/weidagang2046/archive/2006/09/05/67707.html

http://www.eclipse.org/articles/Article-GEF-dnd/GEF-dnd.html


posted @ 2006-09-12 17:16 Jet Geng 阅读(3494) | 评论 (7)编辑 收藏

在开发过程中经常需要把一些配置文件进行合并。一般情况下这些配置文件都是使用xml格式进行存储的。对配置文件进行合并,说到底就变成了对xml的合并。

有了这样的需求就的好好想想有那些方案了。稍微的想了想(肯定不完整了)合并xml可行方案:

1、使用dom4jsaxxml解析工具对需要合并的xml代码进行分析、比较并合并。

<<Java中合并XML文档的设计与实现>>(http://fanqiang.chinaunix.net/program/html/2005-06-16/3313.shtml)一文就是采用的这种方式实现了。

2、采用xsltxml进行合并。

在这两个技术中,我是重点的看了一下第二种。原因是以前对xslt有一点了解,而且不用我自己去控制递规循环这样比较容易出错的环节。

还有就是使用 xslt 有很多很不错的调试环境可以使用如 xmlspy,stylus studio 等。可以直接看到调试过程。最后有幸在网上看到了一个老外写的一个用于合并 xml xslt http://www2.informatik.hu-berlin.de/~obecker/XSLT/#merge )。用 xmlspy 跑了一下,当时感觉就是一个“爽”了得。狂喜过后,就开始思考想想如何用 java 实现这个 xslt 的转换过程了。其实这也是一个很简单的过程。使用 dom4j 用下面的代码就可以实现:

public  Document styleDocument(

Document document,

String stylesheet

throws  Exception {

//  load the transformer using JAXP

TransformerFactory factory 
=  TransformerFactory.newInstance();

Transformer transformer 
=  factory.newTransformer(

new  StreamSource( stylesheet )

);

//  now lets style the given document

DocumentSource source 
=   new  DocumentSource( document );

DocumentResult result 
=   new  DocumentResult();

transformer.transform( source, result );

//  return the transformed document

Document transformedDoc 
=  result.getDocument();

return  transformedDoc;

}

就用这样的代码一跑,他居然,居然没有得到我想要的结果。郁闷啊!直接想去找块豆腐,一头撞死算了。但是在死前还是要把这个问题解决掉。要不死也不甘心。简单的分析一下,在xmlspy中可以使用,说明xslt肯定没有问题。那有问题的肯定是xslt 处理器有问题。你有问题我换不就的了吗。最后我换成了如下的情况:

< dependency >
      
< groupId > dom4j </ groupId >
      
< artifactId > dom4j </ artifactId >
      
< version > 1.6.1 </ version >
    
</ dependency >
    
< dependency >
      
< groupId > net.sf.saxon </ groupId >
      
< artifactId > saxon </ artifactId >
      
< version > 8.5.1 </ version >
    
</ dependency >
  
</ dependencies >

重新跑了一下,ok了。没有问题了。

下面的任务就是对这个功能进行简单的封装一下。然需要xml合并的地方能够很容易的调用他。



posted @ 2006-08-23 17:21 Jet Geng 阅读(2258) | 评论 (0)编辑 收藏

仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页