content: /*
   * Copyright 2010 Aalto University, ComNet
   * Released under GPLv3. See LICENSE.txt for details.
   */
  package gui;
  
  import java.awt.BorderLayout;
  import java.awt.Container;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.Vector;
  
  import javax.swing.JButton;
  import javax.swing.JCheckBox;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.JTree;
  import javax.swing.Timer;
  import javax.swing.tree.DefaultMutableTreeNode;
  
  import routing.util.RoutingInfo;
  import core.DTNHost;
  import core.SimClock;
  
  /**
   * A window for displaying routing information
   */
  @SuppressWarnings("serial")
  public class RoutingInfoWindow extends JFrame implements ActionListener {
  	private DTNHost host;
  	private JButton refreshButton;
  	private JCheckBox autoRefresh;
  	private JScrollPane treePane;
  	private JTree tree;
  	private Timer refreshTimer;
  	/** how often auto refresh is performed */
  	private static final int AUTO_REFRESH_DELAY = 1000;
  
  	public RoutingInfoWindow(DTNHost host) {
  		Container cp = this.getContentPane();
  		JPanel refreshPanel = new JPanel();
  		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  		this.host = host;
  		this.setLayout(new BorderLayout());
  		refreshPanel.setLayout(new BorderLayout());
  		this.autoRefresh = new JCheckBox("Auto refresh");
  		this.autoRefresh.addActionListener(this);
  		this.treePane = new JScrollPane();
  		updateTree();
  
  		cp.add(treePane, BorderLayout.CENTER);
  		cp.add(refreshPanel, BorderLayout.SOUTH);
  
  		this.refreshButton = new JButton("refresh");
  		this.refreshButton.addActionListener(this);
  		refreshPanel.add(refreshButton, BorderLayout.EAST);
  		refreshPanel.add(autoRefresh, BorderLayout.WEST);
  
  		this.pack();
  		this.setVisible(true);
  	}
  
  
  	private void updateTree() {
  		super.setTitle("Routing Info of " + host + " at " +
  				SimClock.getFormattedTime(2));
  		RoutingInfo ri = host.getRoutingInfo();
  		DefaultMutableTreeNode top = new DefaultMutableTreeNode(ri);
  		Vector<Integer> expanded = new Vector<Integer>();
  
  		addChildren(top, ri);
  
  		if (this.tree != null) { /* store expanded state */
  			for (int i=0; i < this.tree.getRowCount(); i++) {
  				if (this.tree.isExpanded(i)) {
  					expanded.add(i);
  				}
  			}
  		}
  
  		this.tree = new JTree(top);
  
  		for (int i=0; i < this.tree.getRowCount(); i++) { /* restore expanded */
  			if (expanded.size() > 0 && expanded.firstElement() == i) {
  				this.tree.expandRow(i);
  				expanded.remove(0);
  			}
  		}
  
  		this.treePane.setViewportView(this.tree);
  		this.treePane.revalidate();
  	}
  
  
  	private void addChildren(DefaultMutableTreeNode node, RoutingInfo info) {
  		for (RoutingInfo ri : info.getMoreInfo()) {
  			DefaultMutableTreeNode child = new DefaultMutableTreeNode(ri);
  			node.add(child);
  			// recursively add children of this info
  			addChildren(child, ri);
  		}
  	}
  
  	public void actionPerformed(ActionEvent e) {
  		Object s = e.getSource();
  		if (s == this.refreshButton || s == this.refreshTimer) {
  			updateTree();
  		}
  		if (e.getSource() == this.autoRefresh) {
  			if (this.autoRefresh.isSelected()) {
  				this.refreshTimer = new Timer(AUTO_REFRESH_DELAY, this);
  				this.refreshTimer.start();
  			} else {
  				this.refreshTimer.stop();
  			}
  		}
  	}
  
  }
  