TWaver局部自动布局及嵌套Group处理

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);
            }
        });
    }
}
 代码和思路都很简单,希望能抛砖引玉,大家有建议或好的想法也可以交流一下

相关推荐