本節教程在第二節的基礎上繼續完善工作流流程設計器,本節的主要内容有:
- 自定義節點圖示
- 自定義形狀
1.自定義節點圖示
通過GMF向導生成的節點都是矩形,為了使圖形更加美觀、更好的使用者UI,我們需要自定義圖形節點。下面以開始和結束活的為例,介紹如何使用自定義圖示。
- 我們繼續在第二節基礎上,打開com.mjt.flow.diagram項目,在icons建立檔案夾custom,将之前準備好的的圖示放入該目錄,這裡使用的是start.png和end.png,圖檔大小32*32。
- 由于需要使用自定義圖示,是以需要在flow.gmfgraph檔案進行圖形設定,需要将形狀設定成自定義形狀。
a) 選擇Canvas Gallery Default->Figure Descriptor StartActivityFigure,将子節點Retangle StartActivityFigure删除,右鍵點選Figure Descriptor StartActivityFigure,New Child->Custom Figure, 輸入名稱StartActivityFigure, 在Qualified Class Name填寫自定義的類名,這個類一般繼承org.eclipse.draw2d.Figure,在這裡填寫類 名:com.mjt.flow.diagram.figure.StartActivityFigure,按照同樣方法,在 EndActivityFigure建立Custom Figure;建立完畢後如下圖:

b)開始和結束活動使用圖檔大小固定,在這裡我們把它改成不可變大小,設定Node StartActivity和Node EndActivity的Resize Constraint為NONE,如下圖:
c)在圖形檔案flow.gmfgraph定義了自定義類,現在需要建立這個兩個類,首先建立開始活動Figure類,該類繼承org.eclipse.draw2d.Figure這個類,如下:
d)類向導建立com.mjt.flow.diagram.figure.StartActivityFigure這個類後,這個類是個空白的類,什麼都沒有,現在我們覆寫基類的paintFigure(Graphics graphics)方法,輸入以下代碼:
package com.mjt.flow.diagram.figure; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.Graphics; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; import com.mjt.flow.diagram.part.FlowDiagramEditorPlugin; public class StartActivityFigure extends Figure { @Override protected void paintFigure(Graphics graphics) { setFigureImage(graphics, "icons/custom/start.png",32,3); //$NON-NLS-1$ } protected void setFigureImage(Graphics graphics, String imagePath, int width, int height){ super.paintFigure(graphics); ImageDescriptor descriptor = FlowDiagramEditorPlugin.findImageDescriptor(imagePath); Image image = descriptor.createImage();//建立圖形 graphics.drawImage(image, getLocation());//繪制圖示 setPreferredSize(width, height); //設定首選(預設)大小 } } |
按 照同樣的方法,建立EndActivityFigure。兩個類代碼重複,可以将活動的Figure建立一個抽象類,如上述的 setFigureImage方法可以放到這個抽象類中,提高代碼的重用性,在此處隻是一個示範,建立兩個相似的類,不進行優化了,有興趣的話可以檢視源 代碼。
e)同時還需要設設定NodeFigure的DefaultSize,打開 com.mjt.flow.diagram.edit.parts.StartActivityEditPart這個類,在 createNodePlate()方法中建立DefaultSizeNodeFigure類時,需要設定DefaultSize為26、26,同時不要 忘記設定EndtActivityEditPart類,如下:
protected NodeFigure createNodePlate() { DefaultSizeNodeFigure result = new DefaultSizeNodeFigure(26,26); return result; } |
Tip:@generated NOT标注可以當GMF重新生成代碼的時候不會被覆寫,不會重新生成。
f)gmfgrap檔案改動過了,需要重新生成flow.gmfgen檔案,删除flow.gmfgen檔案,右鍵點選 flow.gmfmap檔案,Create Generator Model...,點選Generate Diagram Code...,重新生成diagram code。
g)運作一下如下圖:
h)細心的您是否發現,當在畫開始和結束活動時,如果拖動的比較大時,此時圖形有不能調整大小,怎麼辦呢?這時需要您添加另外的代碼控制圖形大小。
此 時需要覆寫com.mjt.flow.diagram.edit.parts.StartActivityEditPart中的 handleNotificationEvent(Notification notification)方法,在這裡進行控制圖形的大小,如下:
@Override protected void handleNotificationEvent(Notification notification) { setToPreferredSize(notification, getFigure(), (View) getModel(), getEditingDomain(), getDiagramEditDomain()); super.handleNotificationEvent(notification); } public static void setToPreferredSize(Notification notification, IFigure figure, View model, TransactionalEditingDomain editingDomain, IDiagramEditDomain diagramEditDomain){ if(notification.getEventType()==Notification.SET && !figure.getSize().equals(figure.getPreferredSize())){ SetBoundsCommand boundsCommand = new SetBoundsCommand(editingDomain,"", //$NON-NLS-1$ new EObjectAdapter(model),figure.getPreferredSize()); diagramEditDomain.getDiagramCommandStack().execute(new ICommandProxy(boundsCommand)); } } |
i)再仔細看一下下面的圖形,有沒有發現,當連接配接線成斜線的時候,由于裡面的圖形是圓形而外框是矩形,預設情況下,連接配接線的錨點是矩形的。如下:
如 何自定義錨點呢?這時候需要覆寫 com.supcon.workflow.xpdl.diagram.edit.parts.StartActivityEditPart#getSourceConnectionAnchor 和#getTargetConnectionAnchor方法,如下:
@Override public ConnectionAnchor getSourceConnectionAnchor( ConnectionEditPart connEditPart) { return new EllipseAnchor(getFigure()); } @Override public ConnectionAnchor getSourceConnectionAnchor(Request request) { return new EllipseAnchor(getFigure()); } @Override public ConnectionAnchor getTargetConnectionAnchor( ConnectionEditPart connEditPart) { return new EllipseAnchor(getFigure()); } @Override public ConnectionAnchor getTargetConnectionAnchor(Request request) { return new EllipseAnchor(getFigure()); } |
draw2d 為我們提供很多預設的Anchor,這裡使用的是橢圓的Anchor,實作的Anchor除了EllipseAnchor還有 DiamondConnectionAnchor、ChopboxAnchor、SlidableAnchor等,有興趣的話可以自己去研究一下,同時可 以自定義Anchor,隻要繼承抽象類org.eclipse.draw2d.AbstractConnectionAnchor來完成自定義的 ConnectionAnchor。
再看一下運作結果:
2.自定義形狀
這一塊内容我們将以AutoActivity活動為例,對其進行自定義形狀,采用漸變填充。
a)首先按照自定義節點圖示的方法,在flow.gmfgraph建立Custom Figure, 由于原來有子節點GridLayout和Label, 删除後重新加上去,如下圖:
b) 建立自定義形狀類com.mjt.flow.diagram.figure.AutoActivityFigure, 繼承org.eclipse.draw2d.Shape,由于Shape是抽象類,需要實作兩個方法fillShape(Graphics graphics)和outlineShape(Graphics graphics),前面主要用于圖形填充,後者用于形狀外邊框。
類代碼如下:
package com.mjt.flow.diagram.figure; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.Shape; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.RGB; public class AutoActivityFigure extends Shape { protected Dimension corner = new Dimension(20, 20); @Override protected void fillShape(Graphics graphics) { //通過路徑繪制圓角矩形 Path path = new Path(null); path.addArc(getBounds().x, getBounds().y, corner.width, corner.height, 180, -90); path.addArc(getBounds().x+getBounds().width-corner.width, getBounds().y, corner.width, corner.height, 90,-90); path.addArc(getBounds().x+getBounds().width-corner.width, getBounds().y+getBounds().height-corner.height, corner.width, corner.height, 0,-90); path.addArc(getBounds().x, getBounds().y+getBounds().height-corner.height, corner.width, corner.height, 270,-90); graphics.setClip(path); //漸變填充 graphics.setForegroundColor(ColorConstants.white); graphics.setBackgroundColor(new Color(null, new RGB(200,220,230))); graphics.fillGradient(getBounds(), true); } @Override protected void outlineShape(Graphics graphics) { float lineInset = Math.max(1.0f, getLineWidthFloat()) / 2.0f; int inset1 = (int) Math.floor(lineInset); int inset2 = (int) Math.ceil(lineInset); Rectangle r = Rectangle.SINGLETON.setBounds(getBounds()); r.x += inset1; r.y += inset1; r.width -= inset1 + inset2; r.height -= inset1 + inset2; graphics.setForegroundColor(new Color(null, new RGB(40,100,120))); graphics.drawRoundRectangle(r, Math.max(0, corner.width - (int) lineInset), Math .max(0, corner.height - (int) lineInset)); } } |
上面定義的圓角橢圓半徑為(20,20)。
c)重新生成flow.gmfgen檔案,并重新生成diagram代碼。
d)運作結果如下:
源代碼請看附件
這一節講完了,下一節的内容是如何擴充流程的自定義字段。
由于平時比較忙,可能寫的比較簡單,有些地方沒有詳細說明,一筆帶過,如果有什麼不明白之處,歡迎通過郵件聯系。
本系列教程盡量會在最短的時間内寫出來。