Posted on 2010-11-24 09:49
TWaver 閱讀(3559)
評論(1) 編輯 收藏
linkUML圖大家都看過,可能大家也比較熟悉,有時候也希望能通過UML圖形的方式展示一些網管業務邏輯,比如以下邏輯

下面通過一系列的功能點講解,教大家如何使用TWaver實現UML效果,最終效果圖如下

Step1, 如何實現UML圖形的節點,效果如下:

功能點介紹
Step1.1 如何實現文字換行居中
TWaver中網元的Label默認就已經提供了對于html的支持,所以可以通過如下代碼實現文字換行居中效果
1
node.putLabelPosition(TWaverConst.POSITION_CENTER);
2
node.setDisplayName("<html><center>網絡資源<br>(Resource)</center></html>");
Step1.2 如何讓網元顯示成UML流程節點形狀
這個主要有兩個功能點
a:平時開發過程中,一般的網元都顯示成圖標的形式以代表業務邏輯,其實TWaver默認提供了一組CustomDraw的圖形,可以將網元顯示成不同的形狀,如下圖所示:

通過設置CustomDraw的屬性就可以達到矩形的效果
Step1.3 如何在節點下面繪制幾條分割線,這個功能很好的體現了TWaver中MVC的架構,對Swing熟悉一些的開發人員都知道,像JButton,JTextField等Swing組件都會有一些對應的UI類,比如ButtonUI,TextFieldUI進行繪制,開發人員可以很方便的通過LookAndFeel切換UI進行換膚操作。TWaver中網元渲染原理類似,像Node,Link都有對應的UI,NodeUI、LinkUI進行渲染,通過很方便的重載這些UI實現效果定制,比如TWaveDemo中的Custom Link Demo和Instrument Demo,如下圖所示

UMLNode的實現也類似,首先定義了一個UMLNode類,在里面設置了一些列的CustomDraw屬性(參考Step1.2),然后繼承ResizableNodeUI實現了一個UMLNodeUI,在里面繪制了幾條分割線,代碼如下
1
public class UmlNode extends ResizableNode
{
2
3
public UmlNode()
{
4
super();
5
initNode();
6
}
7
8
public UmlNode(Object id)
{
9
super(id);
10
initNode();
11
}
12
13
private void initNode()
{
14
this.putCustomDraw(true);
15
this.putCustomDrawGradient(true);
16
this.putCustomDrawGradientFactory(TWaverConst.GRADIENT_LINE_N);
17
this.putCustomDrawFillColor(new Color(255, 200, 100, 150));
18
this.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
19
this.putCustomDrawOutlineColor(new Color(200, 0, 200));
20
21
this.putLabelPosition(TWaverConst.POSITION_CENTER);
22
this.putLabelFont(TUIManager.getDefaultPlainFont());
23
this.setSize(220, 60);
24
}
25
26
//重載UI
27
public String getUIClassID()
{
28
return UmlNodeUI.class.getName();
29
}
30
31
}
32
33
public class UmlNodeUI extends ResizableNodeUI
{
34
35
public UmlNodeUI(TNetwork network, ResizableNode node)
{
36
super(network, node);
37
}
38
39
//想怎么畫就怎么畫
40
protected void paintCustomDraw(Graphics2D g2d)
{
41
super.paintCustomDraw(g2d);
42
Rectangle bounds = this.getUIBounds();
43
44
g2d.drawLine(bounds.x+2, bounds.y+bounds.height-6, bounds.x+bounds.width-2, bounds.y+bounds.height-6);
45
g2d.drawLine(bounds.x+2, bounds.y+bounds.height-12, bounds.x+bounds.width-2, bounds.y+bounds.height-12);
46
}
47
}
通過以上處理,就可以達到UML節點的效果了
Step2,如何實現UML的折線子環效果
TWaver中的Link默認有自環環效果,效果如下

但這個顯然不是我們想要的,因為它默認只有圓形效果,這個時候我們就想到了另外一種Link,ShapeLink,顧名思義,這個Link是由一個Shape形狀來表示的,那么我們能不能通過ShapeLink來實現折線子環的效果呢,答案是肯定的,只需要小小的定制即可,代碼如下
1
public class LoopLink extends ShapeLink
{
2
3
public LoopLink(Node node)
{
4
super();
5
initLink();
6
}
7
8
public LoopLink(Object id, Node node)
{
9
super(id);
10
this.setFrom(node);
11
this.setTo(node);
12
initLink();
13
}
14
15
private double wExtend = 0.5;
16
private double hExtend = 0.5;
17
18
private void initLink()
{
19
this.putLinkFromPosition(TWaverConst.POSITION_RIGHT);
20
this.putLinkToPosition(TWaverConst.POSITION_BOTTOM);
21
this.setLinkType(TWaverConst.LINK_TYPE_YSPLIT);
22
this.putLinkOutlineWidth(0);
23
this.putLinkWidth(1);
24
this.putRenderColor(Color.BLUE);
25
this.putLinkToArrow(true);
26
this.putLinkToArrowStyle(TWaverConst.ARROW_DELTA_GREAT);
27
this.putLinkToArrowOutlineColor(Color.RED);
28
this.putLinkToArrowColor(Color.WHITE);
29
30
Node node = this.getFrom();
31
//注意此處,因為默認ShapeLink上的點是不會跟隨Node移動的,所以為了實現跟隨效果,這里通過監聽Node的屬性變化進行了更新處理
32
node.addPropertyChangeListener(new PropertyChangeListener()
{
33
public void propertyChange(PropertyChangeEvent evt)
{
34
if (TWaverConst.PROPERTYNAME_LOCATION.equals(evt.getPropertyName()))
{
35
validatePoints();
36
}
37
}
38
});
39
validatePoints();
40
}
41
42
private void validatePoints()
{
43
this.clear();
44
Node node = this.getFrom();
45
Rectangle bounds = node.getBounds();
46
Point2D p1 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2, bounds.getCenterY());
47
this.addPoint(p1);
48
Point2D p2 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2 + bounds.getWidth() * wExtend, bounds.getCenterY());
49
this.addPoint(p2);
50
Point2D p3 = new Point2D.Double(bounds.getCenterX() + bounds.getWidth() / 2 + bounds.getWidth() * wExtend, bounds.getCenterY() + bounds.getHeight() / 2
51
+ bounds.getHeight() * hExtend);
52
this.addPoint(p3);
53
Point2D p4 = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY() + bounds.getHeight() / 2 + bounds.getHeight() * hExtend);
54
this.addPoint(p4);
55
}
56
57
}
通過這樣就可以達到折線自環的效果了,效果圖如下

Step3 如何實現Link折線效果和From/To端文字標注
Step 3.1 如何實現Link折線效果,其實這個很簡單,不過可能大多數人都會忽略TWaver默認提供的這個功能,通過設置不同的LinkType,Link可以顯示成各種樣式,如下圖所示

通過如下代碼即可達到UML圖中的連線效果
1
private void initLink()
{
2
this.setLinkType(TWaverConst.LINK_TYPE_YSPLIT);
3
this.putLinkOutlineWidth(0);
4
this.putLinkWidth(1);
5
this.putRenderColor(Color.BLUE);
6
this.putLinkToArrow(true);
7
this.putLinkToArrowStyle(TWaverConst.ARROW_DELTA_GREAT);
8
this.putLinkToArrowOutlineColor(Color.RED);
9
this.putLinkToArrowColor(Color.WHITE);
10
}
Step3.2 如何在Link的From/To端進行標注
效果如下

實現原理:這個借助了TWaver中Attachment的概念,顧名思義,Attachment即附件,它的主要功能就是附加一些信息到網元上,Attachment有很多種,簡單點的可以顯示一串文字,復雜點的可以顯示一些組件在界面上,想TWaverDemo的AttachmentDemo,如下圖所示

文字標注也可以通過這種方式進行處理,TWaver內部對于Link的From和To兩個位置都有對應的定義
1
TWaverConst.POSITION_LINK_FROM_ANCHOR
2
TWaverConst.POSITION_LINK_TO_ANCHOR
既然有了這個實現起來就很簡單了,我們只需要自定義一個Label的Attachment,然后將其放到From或To的Postion既可以了,見如下代碼
1
public class LinkLabelAttachment extends ComponentAttachment
{
2
3
public final static String LINKFROMLABEL = "linklabelattachment.linkfromlabel";
4
5
public LinkLabelAttachment(String name, ElementUI ui)
{
6
super(name, ui);
7
initLabel();
8
}
9
10
public LinkLabelAttachment(String name, ElementUI ui, boolean minimized, boolean shrinked)
{
11
super(name, ui, minimized, shrinked);
12
initLabel();
13
}
14
15
private JLabel label = new JLabel()
{
16
{
17
this.setHorizontalAlignment(SwingConstants.CENTER);
18
this.setDoubleBuffered(false);
19
}
20
};
21
22
private void initLabel()
{
23
label.setFont(LinkLabelDemo.USECUSTOMERFONT);
24
label.setForeground(LinkLabelDemo.LABELCOLOR);
25
26
setLabelText();
27
this.setPosition(TWaverConst.POSITION_LINK_FROM_ANCHOR);
28
this.setComponent(label);
29
}
30
31
private void setLabelText()
{
32
Object obj = element.getClientProperty(LINKFROMLABEL);
33
if (obj != null)
{
34
label.setText(obj.toString());
35
}
36
else
{
37
label.setText("");
38
}
39
//可以調整此參數設置文字的偏移
40
this.setXOffset(30);
41
this.setWidth(label.getPreferredSize().width + 2);
42
this.setHeight(label.getPreferredSize().height + 2);
43
}
44
45
public void elementPropertyChange(PropertyChangeEvent evt)
{
46
super.elementPropertyChange(evt);
47
if (LINKFROMLABEL.equals(TWaverUtil.getPropertyName(evt)))
{
48
setLabelText();
49
}
50
}
51
52
}
Link添加以上Attachment以后就會自動出現在Link的from端
至于另外一端的標簽,我們可以通過TWaver內置的一個Attachment,即Message來實現,代碼如下
1
public void setToLabel(String label)
{
2
this.putMessageContent(label);
3
if (!this.containsAttachment(TWaverConst.ATTACHMENT_MESSAGE))
{
4
this.addAttachment(TWaverConst.ATTACHMENT_MESSAGE);
5
this.putMessageStyle(TWaverConst.MESSAGE_COMPONENT_LABEL);
6
this.putMessageBorderVisible(false);
7
this.putMessageOpaque(false);
8
this.putMessagePosition(TWaverConst.POSITION_LINK_TO_ANCHOR);
9
this.putMessageShadowVisible(false);
10
this.putMessageFont(LinkLabelDemo.USECUSTOMERFONT);
11
this.putMessageForeground(LinkLabelDemo.LABELCOLOR);
12
JLabel label2 = new JLabel();
13
label2.setText(this.getMessageContent());
14
label2.setFont(LinkLabelDemo.USECUSTOMERFONT);
15
//可以設置以下參數設置Message的偏移
16
this.putMessageXOffset(30);
17
}
18
}
通過以上代碼就可以實現在Link兩端添加標簽的效果了
源碼請到此處下載:twaver.servasoft.com