//Copyright (c)2005 Holobloc Inc.
//Contributed to the OOONEIDA Workbench project under the Common Public License.
package fbench.tree;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import fbench.FBench;
import fbench.dom.events.ElementSelectionEvent;
import fbench.graph.popup.ContextMenu;
import org.apache.xerces.dom.events.MutationEventImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.events.MutationEvent;
/**
* A tree for navigating the DOM of an IEC 61499 LibraryElement.
*
* @author JHC
* @version 20051109/JHC - Replaces DOMTreeModel.
*/
public class DOMTree extends JTree implements TreeCellRenderer, TreeSelectionListener,
org.w3c.dom.events.EventListener, ActionListener {
/**
*
*/
private static final long serialVersionUID = -6831240633532660344L;
protected ElementSelectionEvent selevt = new ElementSelectionEvent();
// protected JButton renderer = new JButton();
// cpan024: Changed the JButton to JLabel so looks much better in native
// look-and-feel
protected JLabel renderer = new JLabel();
protected Document document;
protected int mouseButton = -1;
protected MouseEvent mouseEvent = null;
private MouseAdapter mouseListener;
private DefaultTreeModel treeModel = null;
private DOMTreeNode root = null;
public DOMTree(Document doc) {
super(DOMTreeNode.forElement(doc.getDocumentElement()));
treeModel = (DefaultTreeModel)this.getModel();
root = (DOMTreeNode)this.treeModel.getRoot();
//treeModel.
//this.add
//super(treeModel);
// java.lang.System.out.println("[DOMT] Created");
document = doc;
//java.lang.System.out.println("[DOMT] document " + document.hashCode());
setCellRenderer(this);
this.setRowHeight(22);
addTreeSelectionListener(this);
renderer.setFont(new Font("Dialog", Font.BOLD, 12));
renderer.setVerticalTextPosition(SwingConstants.CENTER);
// renderer.setBorder(BorderFactory.createEmptyBorder());
//((org.w3c.dom.events.EventTarget) document).addEventListener(MutationEventImpl.DOM_ATTR_MODIFIED, this, false);
// DONT NEED MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED OR MutationEventImpl.DOM_ATTR_MODIFIED
// DOMTreeNode will handle...
((org.w3c.dom.events.EventTarget) document).addEventListener(MutationEventImpl.DOM_NODE_INSERTED, this, false);
((org.w3c.dom.events.EventTarget) document).addEventListener(MutationEventImpl.DOM_NODE_REMOVED, this, false);
mouseListener = (new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
mouseButton = evt.getButton();
mouseEvent = evt;
TreePath clickedPath = getPathForLocation(evt.getX(), evt.getY());
if(mouseButton == MouseEvent.BUTTON3) {
DOMTreeNode clickedNode = null;
if(clickedPath != null)
clickedNode = (DOMTreeNode) clickedPath.getLastPathComponent();
else
return; // clickedPath == null ... what else can u do?
TreePath selectedPath = getSelectionPath();
if(selectedPath != null) {
DOMTreeNode selectedNode =
(DOMTreeNode) selectedPath.getLastPathComponent();
if(selectedNode.equals(clickedNode)) {
// The node that was clicked on was already
// selected, so
// create the menu now.
Element el = selectedNode.getElement();
java.lang.System.out.println("[DOMT] Element: " + el.getNodeName());
if(FBench.getTreeMenus().containsKey(el.getNodeName())) {
java.lang.System.out.println("[DOMT] Element: " + el.getNodeName()
+ " has a menu");
ContextMenu menu = new ContextMenu(el, mouseEvent);
menu.create(el.getNodeName());
}
mouseEvent = null;
mouseButton = -1;
}
}
}
setSelectionPath(clickedPath);
}
});
this.addMouseListener(mouseListener);
// java.lang.System.out.println("[DOMT] Finish INIT");
}
/**
* Issues an ElementSelectionEvent with HYPERACTIVATE detail (so GraphView
* knows to draw a new diagram).
*/
public void valueChanged(TreeSelectionEvent e) {
DOMTreeNode selectedNode = (DOMTreeNode) e.getPath().getLastPathComponent();
Element el = selectedNode.getElement();
java.lang.System.out.println("[DOMT] Button: " + mouseButton + " " + el.getNodeName());
// Application needs to be handled differently.
if(el.getNodeName().equals("Application"))
el = (Element) el.getFirstChild();
selevt.initSelectionEvent(el, this, ElementSelectionEvent.HYPERACTIVATE);
((org.w3c.dom.events.EventTarget) document).dispatchEvent(selevt);
/*if(mouseButton == MouseEvent.BUTTON3 && mouseEvent != null) {
if(el.getNodeName().equals("AlgorithmList")) {
ContextMenu menu = new ContextMenu(el, mouseEvent);
menu.create("Algorithm");
}
mouseEvent = null;
mouseButton = -1;
}*/
}
public void handleEvent(org.w3c.dom.events.Event evt) {
java.lang.System.out.println("[DOMT] Event thrown " + evt.getType());
if(!(evt instanceof MutationEvent))
return;
treeDidChange();
/*
MutationEvent mutev = (MutationEvent) evt;
if ( mutev.getType().equals(MutationEventImpl.DOM_ATTR_MODIFIED) )
{
java.lang.System.out.println("[DOMT] AttrMod");
Node munode = mutev.getRelatedNode();
if(!(munode instanceof Element))
return;
if(DOMTreeNode.forElement((Element) munode) == null)
return;
}
else if ( mutev.getType().equals(MutationEventImpl.DOM_NODE_INSERTED) )
{
java.lang.System.out.println("[DOMT] Node added");
}
else if ( mutev.getType().equals(MutationEventImpl.DOM_NODE_REMOVED) )
{
java.lang.System.out.println("[DOMT] Node added / removed .. refresh");
treeDidChange();
}*/
// 'old' way
/*Node munode = mutev.getRelatedNode();
if(!(munode instanceof Element))
return;
if(DOMTreeNode.forElement((Element) munode) == null)
return;
int attrChange = mutev.getAttrChange();
if((attrChange == MutationEvent.ADDITION) || (attrChange == MutationEvent.REMOVAL)) {
// TODO process structure changes
}
else if(attrChange == MutationEvent.MODIFICATION) {
treeDidChange();
}*/
}
Color selectedColor = new Color(119, 190, 255);
public void setSelectedColor(Color newColor) {
selectedColor = newColor;
}
public void setRendererEnabled(boolean isEnabled) {
renderer.setEnabled(isEnabled);
if( isEnabled == false )
{
// Remove Mouse
this.removeMouseListener(mouseListener);
}
else
{
this.addMouseListener(mouseListener);
}
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
DOMTreeNode v = (DOMTreeNode) value;
renderer.setText(v.getText());
renderer.setBounds(new Rectangle(0,0,v.getText().length()*5,renderer.getFont().getSize()));
renderer.setIcon(v.getIcon());
// set Opaque to true to honour the setBackground method
renderer.setOpaque(true);
renderer.setForeground(Color.black);
renderer.setBackground(selected ? selectedColor : Color.white);
// renderer.setBorder(BorderFactory.createEmptyBorder(15,0,15,0));
return renderer;
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
public void setDocument(Document doc)
{
document = doc;
root = DOMTreeNode.forElement(document.getDocumentElement());
this.treeModel.setRoot(root);
}
public void refreshTree() {
/*root.removeAllChildren();
//createNodes(root);
treeModel.nodeStructureChanged(root);
treeModel.reload();
this.setModel(treeModel);
//this.set*/
this.setDocument(this.document);
}
}