2012/10/18

Partial AutoLayout and Layout in Nested Groups in TWaver

TWaver has provided some layout algorithms to help us quickly set the positions for elements. They are enough for us to use in many cases, but in some complicated ones we need to make some operations ourselves. Please look at the following example:
Screenshot:
Under this circumstance, it is not so agreeable to use TNetwork#doLayout directly, for doLayout will use the same layout algorithm to all elements in the network. But the several sub-groups under the group in the screenshot have their own layout. My solution is that we can first arrange the layout wholly to the group at the outermost layer and then recurse and go through the sub-groups, namely, arrange the layout to them separately.

Code Implementation:
There are two ways available to use the partial layout in TWaver:
  • Add the Element to be in the layout into a new TNetwork, and arrange the layout with the new TNetwork.
  • TWaver only arranges the layout to the selected element as default, so the element to be in the layout can be put in to the SelectionModel.
In this demo, at first, use the first way above to arrange the layout to the outermost group:
//layoutNetwork is a temporary network which is used to arrange a layout.
//The layout has been saved in ClientProperty when generating the group.
layoutDatabox.addElementWithDescendant(group1);
layoutNetwork.doLayout((Integer)group1.getClientProperty("layout"),false);
Then recurse and go through the sub-groups to arrange the layout to them.
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);//If there are sub-groups, the recursion will be continued.
//to combine the two ways together and add the sub-group to be in a layout into the SelectonModel of layoutNetwork
                layoutDatabox.getSelectionModel().clearSelection();
                layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren());
                layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false);
                layoutDatabox.getSelectionModel().clearSelection();
            }
        }
    }
All codes:
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 is a temporary network which is used to arrange the layout.
//The layout has been saved in ClientProperty when generating the group.
        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);
    }

    /**
     * arrange the layout:to recurse the nested 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);//If there are sub-groups, the recursion will be continued.
//to combine the two ways together and add the sub-group to be in a layout into the SelectonModel of layoutNetwork
                layoutDatabox.getSelectionModel().clearSelection();
                layoutDatabox.getSelectionModel().appendSelection(childGroup.getChildren());
                layoutNetwork.doLayout((Integer) ((Group) element).getClientProperty("layout"), false);
                layoutDatabox.getSelectionModel().clearSelection();
            }
        }
    }
    /**
     * to generate the test group and 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;
    }

    /**
     * to set the style of the 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("layout");
                frame.setSize(1000,700);
                frame.setContentPane(new LayoutTest());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

No comments:

Post a Comment