2012/12/27

Bundled Links in Java

Link-bundling is the way to solve the problems arising from links in TWaver: when there are several links between two nodes, we can double-click one of them to bundle them and represent them with only a link-agent, hence the simplification visually.
There will appear the number of the links once they are bundled together. However, in so much link- bundles, how can we know that a particular number is of which link-bundle?

In fact, if you make some adjustment, you will see clearly how many links every link-bundle has on the network. For example, the sentence link.putLinkLabelRotatable(true); is used to rotate the label to be paralleled to the link-agent and the label of links can also be set to be placed in the middle. What’s more, the content to be shown in the label can also be edited by labelgenerator. For instance:

Before:
After:

In this way, the label is directly shown on the link to clearly divide up the links in the image above. The code is quite simple:
network.setElementLabelGenerator(new Generator(){
   public Object generate(Object object) {
    if (object instanceof Link) {
     Link link = (Link)object;
     if(link.isLinkBundleExpand()){
      return link.getName();
     }else if(link.isBundleAgent()){
      return "spring will come ("+link.getLinkBundleSize()+")"//
     }else{
      return null;
     }
    } else {
     return ((Element) object).getName();
    }
   }
  });
The functions on link-bundle provided in TWaver Java are listed as below:
Link:
isLinkBundleExpand() //to judge whether the links are bundled or not

isBundleAgent() // to judge whether a link is the agent-link or not

getLinkBundleSize() // to obtain the number of the links bundled together

getLinkBundleIndex // to obtain the index of a link in a link-bundle

setBundleExpand(boolean bundleExpand) //to set whether a link-bundle is expanded or not

putLinkBundleExpand  //to set whether the links are expanded or not

putLinkBundleIndex  //to set the index of a link in a link-bundle

putLinkBundleSize  //to set the number of the links bundled together
The functions related to bundle are also provided in DataBox:

setLinkBundleFilter(VisibleFilter linkBundleFilter) //to set the filter which filters out the links to be bundled: to specify which links are to be bundled and which are not

setLinkBundleAgentGenerator //This method is used to set the generator of link-agent in a link-bundle to change the default that a random link is specified as the agent-link in TWaver.

getBundledLinks(Node node1, Node node2) //to obtain the bundled links between two nodes


2012/12/13

To Add Icons at Any Place on Elements in TWaver Flex

With the help of iconAttachment system provided in TWaver Java, we can be able to put any number of images, characters and figures on an element as you want. For example:

The following codes can also be called to show the icons on an element in TWaver Flex.


server1.setStyle(Styles.ICONS_NAMES, ["att5","att6", "att7","att8"]);
server1.setStyle(Styles.ICONS_POSITION, Consts.POSITION_BOTTOMRIGHT_TOPRIGHT);
server1.setStyle(Styles.ICONS_ORIENTATION, Consts.ORIENTATION_TOP);
server1.setStyle(Styles.ICONS_XOFFSET, 5);

The function to add icons at different positions on an element is not provided in TWaver Flex as default, but it can be realized through function-expansion, since the FlexMVC model is so flexible.
Several iconAttachments can be created to show icons at different places with the Attachment component in TWaver.

If you are interested in it, you can try to show attachments at different places and directions, mainly by changing the following two methods in CustomIconAttachment:
private function getIconsSize(names:Array, orientation:String, xgap:Number, ygap:Number):Size
and
override public function draw(graphics:Graphics):void

2012/12/02

Tree of files in JTree

In fact, what this article will say has nothing to do with the components in TWaver just because I find it quite interesting. Therefore, I would like to share it with you. The file tree is completely based on JTree of swing. Now let's first see the final effect:

Screenshot:



Introduction on Functions:
  • to show the structure of files in tree
  • the icon of files should be systematic ones
  • The background color of the current node will be changed when you mouse over it.(such as the bricky-red background of the text "Windows" in the image above)
First let' s see the class structure:
  • main program
  • file tree, which inherits from JTree
  • the encapsulated node, including the name and the icon of a file, the File class and other identity
  • The customized node renderer which inherits from DefaultTreeCellRenderer
  • the customized TreeModel which inherits from DefaultTreeModel
Considering that there will be quite a few system files, it is not reasonable to initialize the whole tree at starting a program. So we have taken measures to delay loading: to only initialize the child nodes of a node only when it is to be expanded. Now add a listener into the construction of FileTree:
addTreeWillExpandListener(new TreeWillExpandListener() {
            @Override
            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
                DefaultMutableTreeNode lastTreeNode =
(DefaultMutableTreeNode) event.getPath().getLastPathComponent();
                FileNode fileNode = (FileNode) lastTreeNode.getUserObject();
                if (!fileNode.isInit) {
                    File[] files;
                    if (fileNode.isDummyRoot) {
                        files = fileSystemView.getRoots();
                    } else {
                        files = fileSystemView.getFiles(
                                ((FileNode) lastTreeNode.getUserObject()).file,
                                false);
                    }
                    for (int i = 0; i < files.length; i++) {
                       //The name and the icon of the file is obtained through fileSystemView.
                        FileNode childFileNode = new FileNode(
                                fileSystemView.getSystemDisplayName(files[i]),
                                fileSystemView.getSystemIcon(files[i]), files[i],
                                false);
                        DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(childFileNode);
                        lastTreeNode.add(childTreeNode);
                    }
                    //To notify that a node has been changed
                    DefaultTreeModel treeModel1 = (DefaultTreeModel) getModel();
                    treeModel1.nodeStructureChanged(lastTreeNode);
                }
                //to change the identifier to avoid loading repeatedly
                fileNode.isInit = true;
            }
            @Override
            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {

            }
        });
Of course, this method must be combined with TableModel. I have reloaded DefaultTreeModel and initialized the root node in the construction. Then load the method isLeaf.

Now let's think how to change the background color of a node when you mouse over it.

Right at this time I recalled the mistake I made during the time when I first learned Renderer that every node has a Renderer and I even tend to add a listener to it! The thing I have to emphasize is that Renderer is just a renderer. JTree will call it to render nodes onto the screen to show them. But remember however nodes there are, there is only one Renderer in a JTree!

Since it is useless to add a listener to Renderer, we have to change our focus, that is, to add listener which listens to mouse-moves in JTree and then repaint the node on which the mouse is.

addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
//to obtain the TreePath of the mouse
                TreePath path=getPathForLocation(e.getX(), e.getY());

//to calculate the area to be reprinted and to repaint JTree
                if(path!=null){
                    if(mouseInPath!=null){
                        Rectangle oldRect=getPathBounds(mouseInPath);
                        mouseInPath=path;
                        repaint(getPathBounds(path).union(oldRect));
                    }else{
                        mouseInPath=path;
                        Rectangle bounds=getPathBounds(mouseInPath);
                        repaint(bounds);
                    }
                }else if(mouseInPath!=null){
                    Rectangle oldRect=getPathBounds(mouseInPath);
                    mouseInPath=null;
                    repaint(oldRect);
                }
            }
        });
The background color of mouseInPath can be changed in Renderer only when the TreePath(mouseInPath) of MouseOver is saved in JTree.
FileTree fileTree=(FileTree)tree;
        JLabel label= (JLabel) super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);

        DefaultMutableTreeNode node=(DefaultMutableTreeNode)value;
        FileNode fileNode=(FileNode)node.getUserObject();
        label.setText(fileNode.name);
        label.setIcon(fileNode.icon);

        label.setOpaque(false);
//to change the background color if the node in rendering now is the node under the mouse over
        if(fileTree.mouseInPath!=null&&
                fileTree.mouseInPath.getLastPathComponent().equals(value)){
            label.setOpaque(true);
            label.setBackground(new Color(255,0,0,90));
        }
        return label;
Now it is the end of the article. If you have interest in it, welcome for your communication and good ideas.