TWaver提供了一些布局算法帮助我们快速为网元设置位置,很多情况下已经够用了,但是对于一些复杂的布局还需要我们自己做一些处理,看下面这个例子:
运行截图:
这个时候直接使用TNetwork#doLayout就不好使了,因为doLayout会对network中所有网元使用同一种布局算法,但是截图中Group下多个子Group各有自己的布局方式,我的解决办法是,先对最外层的Group整个布局,然后递归遍历子Group,单独对他们进行布局
代码实现:
TWaver中实现局部布局可以通过两种方式:
- 将要布局的Element加入到一个新的TNetwork中,然后用新的TNetwork布局
- TWaver默认只对选中的Element布局,所以可以将要布局的Element加入到SelectionModel中
在这个demo中,首先用第一种方式对最外层的Group进行布局:
//layoutNetwork是用来布局的临时network
//生成Group时,已经将布局方式存入ClientProperty
layoutDatabox.addElementWithDescendant(group1);
layoutNetwork.doLayout((Integer)group1.getClientProperty("layout"),false);
然后递归遍历group,为子group布局
recursionChild(group1);
............................................
private void recursionChild(Group group){
for(int i=0;i<group.getChildren().size();i++){
Element element= (Element) group.getChildren().get(i);
if(element instanceof Group){
Group childGroup=((Group)element);
recursionChild(childGroup);//如果有子Group,会一直递归
//使用两种方式结合,将要布局的子group加入到layoutNetwork的SelectionModel
layoutDatabox.getSelectionModel().clearSelection();
layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren());
layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false);
layoutDatabox.getSelectionModel().clearSelection();
}
}
}
最后附上全部代码
public class LayoutTest extends JPanel {
TDataBox layoutDatabox=new TDataBox();
TNetwork layoutNetwork=new TNetwork(layoutDatabox);
public LayoutTest(){
TNetwork network=new TNetwork();
ResizableNode gatewayNode=new ResizableNode();
gatewayNode.putCustomDraw(true);
gatewayNode.putCustomDrawShapeFactory(TWaverConst.SHAPE_ROUND_RECTANGLE_HALF);
gatewayNode.putCustomDrawGradient(false);
gatewayNode.putCustomDrawFillColor(new Color(254, 254, 206));
gatewayNode.setSize(70, 30);
gatewayNode.setName("Gateway");
gatewayNode.putLabelPosition(TWaverConst.POSITION_CENTER);
Group group1=createGroup(4,TWaverConst.LAYOUT_TREE);
Group group1_1=createGroup(12,TWaverConst.LAYOUT_CIRCULAR);
Group group1_2=createGroup(5,TWaverConst.LAYOUT_EAST);
Link group1_2Link=new Link((Node)group1.getChildren().get(0),(Node)group1_2.getChildren().get(0));
setLinkStyle(group1_2Link);
group1.addChild(group1_2);
group1.addChild(group1_2Link);
Link group1_1Link=new Link((Node)group1.getChildren().get(0),(Node)group1_1.getChildren().get(0));
setLinkStyle(group1_1Link);
group1.addChild(group1_1);
group1.addChild(group1_1Link);
//layoutNetwork是用来布局的临时network
//生成Group时,已经将布局方式存入ClientProperty
layoutDatabox.addElementWithDescendant(group1);
layoutNetwork.doLayout((Integer)group1.getClientProperty("layout"),false);
recursionChild(group1);
TDataBox box=new TDataBox();
box.addElementWithDescendant(group1);
box.addElement(gatewayNode);
group1.putGroupOpaque(true);
group1.putGroupFillColor(new Color(154,206,254));
network.setDataBox(box);
this.setLayout(new GridLayout(1,3));
this.add(network);
Layer layer=new Layer();
box.getLayerModel().addLayer(layer);
box.getLayerModel().moveToTop(layer);
Link link1=new Link(group1,gatewayNode);
setLinkStyle(link1);
link1.setLinkType(TWaverConst.LINK_TYPE_ORTHOGONAL);
link1.setLayerID(layer.getID());
box.addElement(link1);
}
/**
* 递归Group设置布局
* @param group
*/
private void recursionChild(Group group){
for(int i=0;i<group.getChildren().size();i++){
Element element= (Element) group.getChildren().get(i);
if(element instanceof Group){
Group childGroup=((Group)element);
recursionChild(childGroup);//如果有子Group,会一直递归
//使用两种方式结合,将要布局的子group加入到layoutNetwork的SelectionModel
layoutDatabox.getSelectionModel().clearSelection();
layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren());
layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false);
layoutDatabox.getSelectionModel().clearSelection();
}
}
}
/**
* 产生测试Group及Node
* @param childCount
* @param layout
* @return
*/
private Group createGroup(int childCount,int layout){
Group group=new Group();
group.setExpand(true);
group.putClientProperty("layout",layout);
ResizableNode router=new ResizableNode();
router.putCustomDraw(true);
router.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
router.putCustomDrawGradient(false);
router.putCustomDrawFillColor(new Color(254, 254, 206));
router.setSize(60, 20);
router.setName("Router");
router.putLabelPosition(TWaverConst.POSITION_CENTER);
group.addChild(router);
for(int i=0;i<childCount;i++){
Node childNode=new Node();
Link link=new Link(router,childNode);
childNode.putCustomDraw(true);
childNode.putCustomDrawShapeFactory(TWaverConst.SHAPE_RECTANGLE);
childNode.putCustomDrawGradient(false);
childNode.putCustomDrawFillColor(new Color(254,202,2));
childNode.setName("C"+i);
childNode.putLabelPosition(TWaverConst.POSITION_CENTER);
setLinkStyle(link);
group.addChild(childNode);
group.addChild(link);
}
return group;
}
/**
* 设置link样式
* @param link
*/
public void setLinkStyle(Link link){
link.putLinkColor(Color.black);
link.putLinkOutlineWidth(0);
link.putLinkWidth(1);
link.putLinkAntialias(true);
link.putLinkToArrow(true);
link.putLinkToArrowOutline(false);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame=new JFrame("布局");
frame.setSize(1000,700);
frame.setContentPane(new LayoutTest());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
代码和思路都很简单,希望能抛砖引玉,大家有建议或好的想法也可以交流一下。