??xml version="1.0" encoding="utf-8" standalone="yes"?>
q三天来Q一直在Z个问题所困扰?br />
我做的项目是emf和gefl合的一个典型实例。其实我接触q些东西也才4Q?个月Q两个Eclipse工具都很熟?zhn)Q但是ƈ不能说是_N?br />
在项目制作的q程中,~辑器的布局问题q没有拿到桌面上来讨论。毕竟,功能没有实现Q编辑器作的再漂亮也不v作用?br />
现在Q所有的功能点全部按要求实现了,可是再看看编辑器Q就会觉得很外行Q呵c?br />
管老大不在公司Q但是我想他肯定支持我的q个xQ将界面作的professional一炏V?br />
于是Q我费?天时间来重新做布局?br />
搜烦icon
目l没有给我配备美工,所有的囄都是临时的,我就采用了一些qq表情图,所以编辑器很“可爱”。现在需要根据每个模型的实际含义来配备iconQ于是利用google & baidu搜了一些图片下来。好在我q会点psQ那二十多个图标q定了?br />
研究布局
q次的代码大攚w,需要严重的感谢一个hQreload_cn。非常感谢他能耐心的听我不停的发牢骚,q给于正的指导。这对后来的攚w成功v军_性作用。尽他社区里的帅照改成了黑猩?..... 最l得l果是改好了Q一切都跟flow那么?br />
好,转入正题。目前的~辑器功能已l实CQ但是ؓ什么要改布局呢?因ؓ现在~辑器采用的是xyLayoutQ创Z个对象之后,它的xywh保存在模型对象中Q然后再refreshVisual的时候设|Figure的Bound。这么做的问题是Q首先,没有很好的计坐标,所以坐标有点出入(有的时候坐标出入大的难以接受)Q其ơ,本工具定义的主要是流E,所以编辑器里的“内容”很多,每创Z个对象都需?u>手工拖拽到合适的位置上?br />
在reload_cn的提CZQ我研究了一下GEF的Flow例子。由于时间关p(元旦之后׃发布最l版本,要不加班Q要不加快脚步干z)Q我直接将flow里的GraphLayoutManager拿过来用?..
l果是,l常报些莫名其妙的错误?br />
所谓心急吃不了热豆腐?br />
l箋在reload_cn的提CZQ研I了他的sequnce diagram的例子。在q个例子中,他做了个很简单的布局处理?br />
从这里例子中Q我领?zhn)Z真谛Q?br /> 在EditPart中设|的Layout Policy其实主要处理的是创徏对象{等requestQƈ不处理真正的~辑器布局。又或者说它的布局是逻辑意义上的。真正处理布局Q来让我们看到效果的Q是Figure的布局。而这个正好是我常常忽略的?br />
Figure怎么布局Q?我一般用的就是xyLayout和ToolbarLayout。但是如果要作出漂亮的效果,q些q是不够的。八q制的blog中提Cdraw2d的tree example。我看过了,然后研究了一下,觉得太简单了Q不能符合本目的需求?br />
回头再看看flowQ觉得这个例子本w就是流E定义,q且跟我的项目在Figure上有很多共同炏V。?br />
仍然心有余?zhn)Q毕竟用flow的代码作的所有尝试(用了1天的旉Q全部失败了Q而且q|的莫名其妙?br />
开始尝?/strong>
不能因ؓp|Q所以放弃(但是可以有放弃的xQ呵呵)。我军_一点一点地来尝试?br />
首先Q我替换了所有的iconQ至图标看h已经舒服多了?br />
接着Q根据flow中figure的做法,更新了项目中的所有Figure。运行一下看看,呵呵Q至图标很象了?br />
我很喜欢flow中自动计Figure位置的功能和动态移动效果。怎么办?l箋改装代码?br />
GraphLayoutManager心翼的搬了过来。没有效果。但是至没有出错?br />
开始用GraphLayoutManager来进行坐标计。(q个q程漫长而痛苦,不停的报异常Q不停的Ҏ(gu)代码Q不停的跟踪Q不停的发牢?...Q?br />
最后出的问题最有意思,假如~辑器根模型的Figure采用flow中的figureQ那么编辑器中只昄q线。ؓ什么呢Q因为我的编辑器中用的是viewer.setRootEditPart(new ScalableFreeformRootEditPart());而flow中用的是getGraphicalViewer().setRootEditPart(new ScalableRootEditPart());所以在我这边,figure采用FreeformLayerno problem了?/p>
l果
l论
假如你和我一P在项目制作后期修改编辑器的布局Q这里有几个Q?br />
1 研究一下例子,从简单的开始,一直到隄Q让理论知识Ҏ(gu)蒂固?br />2 作个例子,或者将你已l作的小例子q行cM的改~,看看Z么问题,Z么出问题?br />3 例子没做出来没关p,q些跟头栽在例子上比栽在项目中让hƣ慰的多?br />4 先修改Figure。尽量接q你惌的效果?br />5 引入布局Q暂时不要用它Q只要他的流E走下来没有问题成功了一半?br />6 使用布局。会出现很多问题Q但是很Ҏ(gu)定位问题。调试吧?br />
暂时p么多吧,刚刚的改动导致了~辑器中的删除功能抛异常Q我得看看去
在参考了GEF?/SPAN>flow example之后Q对其代码作了部分重构,写了q片文章Q希望对遇到同样问题的同志能够有一定的帮助?/SPAN>
首先引入一个接口:
public interface GraphBuilder {
public void contributeNodesToGraph(DirectedGraph graph, Map map);
public void contributeEdgesToGraph(DirectedGraph graph, Map map);
public void applyGraphResults(DirectedGraph graph, Map map);
}
q个接口中定义了几个Ҏ(gu)Q其含义从其Ҏ(gu)名中可以猜出Q?/SPAN>
contributeNodesToGraphQ将当前对象作ؓ节点Q?/SPAN>NodeQ添加到DirectedGraph中?/SPAN>
contributeEdgesToGraphQ将当前对象所对应的连U作Q?/SPAN>EdgeQ添加到DirectedGraph中?/SPAN>
applyGraphResultsQ将图中生成的布局信息取出Q对本对象进行重新布局?/SPAN>
接口中的graph参数是保存的图的信息,map参数l持一个对象到节点/边的映射Q得每个对象能够方便的扑ֈ其对应的图中的节Ҏ(gu)者边。这个接口的使用Q在后面会有涉及。下面先看看昄囄容器是如何构建的?/SPAN>
囄容器定义?/SPAN>GraphDiagramEditPartQ这?/SPAN>EditPart对应于要昄的有向图的容器。它实现?/SPAN>GraphBuider接口Q这也是我们主要需要关注的接口Q?/SPAN>
public class GraphDiagramEditPart extends AbstractGraphicalEditPart implements
GraphBuilder.
contributeNodesToGraphҎ(gu)自w作Ҏ(gu)加到图中Q但是因?/SPAN>GraphDiagramEditPart对应的是容器Q因此它不需要向图中d信息Q只是调用其?/SPAN>EditPartQ将其添加到图中?/SPAN>
public void contributeNodesToGraph(DirectedGraph graph, Map map) {
for (int i = 0; i < getChildren().size(); i++) {
NodeEditPart activity = (NodeEditPart)getChildren().get(i);
activity.contributeNodesToGraph(graph, map);
}
}
contributeEdgesToGraphҎ(gu)这?/SPAN>EditPart的所有子EditPart取出Q调用其contributeEdgesToGraphҎ(gu)Q通过q个Ҏ(gu)Q就可以所有的Ҏ(gu)加到图中了:
public void contributeEdgesToGraph(DirectedGraph graph, Map map) {
for (int i = 0; i < getChildren().size(); i++) {
NodeEditPart child = (NodeEditPart)children.get(i);
child.contributeEdgesToGraph(graph, map);
}
}
applyGraphResultsҎ(gu)所有取出所有的?/SPAN>EditPartQƈ调用?/SPAN>applyGraphResultsQ得图中所生成的布局信息能够被应用到昄上?/SPAN>
public void applyGraphResults(DirectedGraph graph, Map map) {
applyChildrenResults(graph, map);
}
protected void applyChildrenResults(DirectedGraph graph, Map map) {
for (int i = 0; i < getChildren().size(); i++) {
GraphBuilder part = (GraphBuilder) getChildren().get(i);
part.applyGraphResults(graph, map);
}
}
下面要介l的?/SPAN>NodeEditPartQ它作图中所有节Ҏ(gu)对应?/SPAN>EditPart的抽象父c,也实CGraphBuilder接口。每一个要做ؓ节点d到图中的EditPartQ应该承这个类?/SPAN>
public abstract class NodeEditPart extends AbstractGraphicalEditPart implements
GraphBuilder{
public void contributeNodesToGraph(DirectedGraph graph,
Map map) {
Node n = new Node(this);
n.outgoingOffset = 7;
n.incomingOffset = 7;
n.width = getFigure().getPreferredSize().width;
n.height = getFigure().getPreferredSize().height;
n.setPadding(new Insets(10,8,10,12));
map.put(this, n);
graph.nodes.add(n);
}
public void contributeEdgesToGraph(DirectedGraph graph, Map map) {
List outgoing = getSourceConnections();
for (int i = 0; i < outgoing.size(); i++) {
EdgeEditPart part = (EdgeEditPart)getSourceConnections().get(i);
part.contributeEdgesToGraph(graph, map);
}
}
public void applyGraphResults(DirectedGraph graph, Map map) {
Node n = (Node)map.get(this);
getFigure().setBounds(new Rectangle(n.x, n.y, n.width, n.height));
for (int i = 0; i < getSourceConnections().size(); i++) {
EdgeEditPart trans = (EdgeEditPart) getSourceConnections().get(i);
trans.applyGraphResults(graph, map);
}
}
}
再就是边所对应EditPart的抽象类EdgeEditPart。每一个要作ؓҎ(gu)加到图中?/SPAN>EditPartQ需要承这个类。在上面NodeEditPart中对其所对应?/SPAN>Figure其实q没有什么要求,但是?/SPAN>EdgeEditPart所对应?/SPAN>FigureQ要求其Figure必须׃?/SPAN>BendpointConnectionRouterQ作为其ConnectionRouterQ?/SPAN>setConnectionRouter(new BendpointConnectionRouter())。这样图的边的\径信息才能够被显C出来?/SPAN>
public abstract class EdgeEditPart extends AbstractConnectionEditPart implements
GraphBuilder {
public void contributeEdgesToGraph(DirectedGraph graph, Map map) {
Node source = (Node)map.get(getSource());
Node target = (Node)map.get(getTarget());
Edge e = new Edge(this, source, target);
e.weight = 2;
graph.edges.add(e);
map.put(this, e);
}
public void applyGraphResults(DirectedGraph graph, Map map) {
Edge e = (Edge)map.get(this);
NodeList nodes = e.vNodes;
PolylineConnection conn = (PolylineConnection)getConnectionFigure();
conn.setTargetDecoration(new PolygonDecoration());
if (nodes != null) {
List bends = new ArrayList();
for (int i = 0; i < nodes.size(); i++) {
Node vn = nodes.getNode(i);
int x = vn.x;
int y = vn.y;
if (e.isFeedback) {
bends.add(new AbsoluteBendpoint(x, y + vn.height));
bends.add(new AbsoluteBendpoint(x, y));
} else {
bends.add(new AbsoluteBendpoint(x, y));
bends.add(new AbsoluteBendpoint(x, y + vn.height));
}
}
conn.setRoutingConstraint(bends);
} else {
conn.setRoutingConstraint(Collections.EMPTY_LIST);
}
}
}
最后的是一?/SPAN>LayoutManager来初始化囄创徏Q以及对囄信息q行解释了,生成最l布局了。这?/SPAN>GraphLayoutManager作ؓGraphDiagramEditPart所对应?/SPAN>GraphDiagram?/SPAN>LayoutManagerQ来昄囄内容?/SPAN>
public class GraphLayoutManager extends AbstractLayout {
private GraphBuilder diagram;
GraphLayoutManager(GraphBuilder diagram) {
this.diagram = diagram;
}
protected Dimension calculatePreferredSize(IFigure container, int wHint,
int hHint) {
container.validate();
List children = container.getChildren();
Rectangle result = new Rectangle().setLocation(container
.getClientArea().getLocation());
for (int i = 0; i < children.size(); i++)
result.union(((IFigure) children.get(i)).getBounds());
result.resize(container.getInsets().getWidth(), container.getInsets()
.getHeight());
return result.getSize();
}
public void layout(IFigure container) {
DirectedGraph graph = new DirectedGraph();
Map partsToNodes = new HashMap();
diagram.contributeNodesToGraph(graph, partsToNodes);
diagram.contributeEdgesToGraph(graph, partsToNodes);
new DirectedGraphLayout().visit(graph);
diagram.applyGraphResults(graph, partsToNodes);
}
}
可以看到?/SPAN>layoutҎ(gu)中,首先生成了一?/SPAN>DirectedGraphQƈ调用?/SPAN>contributeNodesToGraph以及contributeEdgesToGraphҎ(gu)Q将节点和边的信息添加到q个生成?/SPAN>DirectedGraphGraph中,然后使用布局法DirectedGraphLayout().visit(graph)来计生成图的信息(q里使用?/SPAN>visitor模式Q最后调?/SPAN>applyGraphResults图的信息应用到囑Ş的显CZ?/SPAN>
xQ所有框架的工作做完了,如果要将模型作ؓ一个有向图昄的话Q只需要将模型的容器对象对应于GraphDiagramEditPartQ在EditPartFactory中进行映)Qؓ每一个需要表CZؓ节点的对象,对应C个承于NodeEditPart?/SPAN>EditPartQؓ每一个需要表CZؓ边的模型对象Q对应到一个承于EdgeEditPart?/SPAN>EditPart。这Pp够将囄布局法Q应用到GEF框架中了?/SPAN>
q里写的比较单,使用h也会有一些具体的U束。例如在有向图中Q是不能够有孤立的节点的。如果?/SPAN>CompoundDirectedGraphQ就不会有这L(fng)问题Q?/SPAN>CompoundDirectedGraph可以包括子图Q可以支持更为复杂的囑Ş。在Flow Example中用的是CompoundDirectedGraph。在后面Q我或许会将q个框架q行改写Q以使其支持CompoundDirectedGraph来进行布局法。下面的图是一个生成的例子Q大家可以看一下效?
q是从OWL文g中读取内容之后生成的一个图的表C。可以看刎ͼOWL的节炚w过自动囄自动布局之后Q已l有了较好的视觉效果。如果没有这L(fng)布局的话Q因为单U的OWL文g中ƈ不会包含节点的图的信息,图显C出来会变得非常的ؕQ所有的节点都会堆在一赗?BR>
原文地址:http://www.aygfsteel.com/eclipshine/archive/2005/07/22/8195.aspx
9.22 SDO学习W记 |
今天_粗看了一眼SDOQ略有理解?/FONT>
SDO全称Service Data ObjectsQ是IBM提出的一个框架规范。SDO框架׃部分l成QDMSQData Mediator ServicesQ,Data Graph和DataObject。DMS负责生成Data GraphQData Graph包含一pd兌的Data Object。客户和DataGraph打交道,而DMS如何生成Data Graph又如何从Data Graph更新后面的数据则无需兛_。Data Graph是Disconnected Mode的数据处理方式,卛_其进行的修改操作Q将不会立刻体现Q需要将修改q的Data Graph由DMS来更新到数据源。Data Graph是通过log change summary来实现的?/FONT>
在Spec中说道,Data Graph被序列化为XML也能从XML中被反序列化。这使得在Services和其Caller之间传递DataGraph非常直接。同时也提出了系l内部、系l之间数据交互的一致方式——通过XML序列化过的Data Graph?/FONT>
Data Object可以被动态实玎ͼE序里将看不见具体的Data Objectc,比如Employeec,因此也无需定义XML SchemaQ,也可以被静态生成(例如预先建模后用工L(fng)成,目前IBMZEMF的RI可以使用EMF来生成)?/FONT>
DMS可以有许多实现方式,在IBm的SDO Specification中ƈ没有M关于DMS实现方式的规范。实际上QDMS在SDO Spec V2.0里面已经改称DASQData Access ServicesQ,我们发现q命名和DAOQData Access ObjectQ模式何其相伹{不q这里是Service。那么可以想象在SOA中,我们可以提供q样的DAS来提供数据ƈ作数据更新。难道与DAOcMq将会成ZUSOA模式Q?/FONT>
更重要的是,DAS可以在J2EE的各层都能被使用。你可以使用JDBC实现DAS用它做一个持久化服务层,你可以用EJB实现DASq且暴露成Web Service……你甚至可以使用Hibernate、JDOq样的持久化工具来实现DAS?/FONT>
所以我们不可能hSDO框架和Hibernate、JDO{工具——因为后者只是持久化工具存在于EIS之上Q也无需怀疑SDO的h(hun)值——SDO实可以为整个J2EE应用其是SOA提供一个一致的数据处理方式?/FONT>
明天l箋研究。希望能深化、纠正现在的理解?BR> |