package com.dbxml.db.admin.components;
/*
* dbXML - Native XML Database
* Copyright (c) 1999-2006 The dbXML Group, L.L.C.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* $Id: DBBrowser.java,v 1.10 2008/08/18 17:24:53 bradford Exp $
*/
import com.dbxml.db.admin.nodes.*;
import javax.swing.*;
import javax.swing.tree.*;
import com.dbxml.db.admin.Admin;
import com.dbxml.db.client.dbXMLClient;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.border.Border;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import com.dbxml.util.Stopwatch;
import com.dbxml.db.admin.DocWrapper;
import java.awt.PopupMenu;
/**
* DBBrowser
*/
public class DBBrowser extends JTree {
private static final Border brdMargin = BorderFactory.createEmptyBorder(1, 1, 1, 1);
private Admin admin;
private RootNode adminRoot = new RootNode();
private DefaultMutableTreeNode nodeRoot = new DefaultMutableTreeNode();
private DefaultTreeModel treeModel;
private JMenu menu;
public DBBrowser(Admin admin) {
this.admin = admin;
ToolTipManager.sharedInstance().registerComponent(this);
nodeRoot.setUserObject(adminRoot);
setCellRenderer(new AdminNodeRenderer());
getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
treeModel = new DefaultTreeModel(nodeRoot, true);
setModel(treeModel);
TreePath rootPath = new TreePath(nodeRoot.getPath());
setSelectionPath(rootPath);
setEditable(false);
setAutoscrolls(true);
setRootVisible(true);
setShowsRootHandles(false);
setScrollsOnExpand(true);
addTreeExpansionListener(new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent e) {
browser_treeExpanded(e);
}
public void treeCollapsed(TreeExpansionEvent e) {
browser_treeCollapsed(e);
}
});
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
browser_mousePressed(e);
}
public void mouseClicked(MouseEvent e) {
browser_mouseClicked(e);
}
});
}
public void addClient(dbXMLClient client, String label) {
AdminNode info = new CollectionNode(client, label);
DefaultMutableTreeNode sn = new DefaultMutableTreeNode(info, true);
nodeRoot.add(sn);
treeModel.reload(nodeRoot);
}
public void addFileSystem(String filename, String label) {
AdminNode info = new DirectoryNode(adminRoot, filename, label);
DefaultMutableTreeNode sn = new DefaultMutableTreeNode(info, true);
nodeRoot.add(sn);
treeModel.reload(nodeRoot);
}
public void addFileSystem(String filename) {
addFileSystem(filename, null);
}
public void setMenu(JMenu menu) {
this.menu = menu;
generateMenu(menu, adminRoot, getSelectionPath(), false);
}
private JPopupMenu generateMenu(JMenu menu, final AdminNode info, final TreePath path, boolean useParentMenu) {
JPopupMenu pmenu = null;
if ( menu != null )
menu.setVisible(false);
else
pmenu = new JPopupMenu();
com.dbxml.db.admin.nodes.MenuItem[] items = null;
if ( info instanceof HasMenu )
items = ((HasMenu)info).getMenu();
if ( items != null && items.length > 0 ) {
HasMenu hm = (HasMenu)info;
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JMenuItem item = (JMenuItem)ae.getSource();
int result = ((HasMenu)info).menuAction(item.getMnemonic());
TreePath p = null;
switch ( result ) {
case HasMenu.REFRESH_PARENT:
p = path.getParentPath();
break;
case HasMenu.REFRESH_SELF:
case HasMenu.REFRESH_CHILDREN:
p = path;
break;
case HasMenu.REMOVE_SELF:
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
TreeNode parent = node.getParent();
node.removeFromParent();
treeModel.nodeStructureChanged(parent);
break;
}
if ( p != null ) {
collapsePath(p);
expandPath(p);
}
}
};
if ( pmenu != null )
pmenu.setLabel(hm.getMenuTitle());
else {
menu.removeAll();
menu.setText(hm.getMenuTitle());
menu.setVisible(true);
}
for ( int i = 0; i < items.length; i++ ) {
if ( items[i].getAction() != com.dbxml.db.admin.nodes.MenuItem.ACTION_SEPARATOR ) {
JMenuItem item = new JMenuItem(items[i].getLabel(), items[i].getAction());
item.addActionListener(listener);
if ( pmenu != null )
pmenu.add(item);
else
menu.add(item);
}
else {
if ( pmenu != null )
pmenu.addSeparator();
else
menu.addSeparator();
}
}
if ( useParentMenu && info.isParentMenuInherited() ) {
TreePath parentPath = path.getParentPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)parentPath.getLastPathComponent();
AdminNode parentInfo = (AdminNode)node.getUserObject();
if ( parentInfo instanceof HasMenu ) {
HasMenu parentHM = (HasMenu)parentInfo;
MenuItem[] parentItems = parentHM.getMenu();
if ( parentItems != null && parentItems.length > 0 ) {
JPopupMenu parentMenu = generateMenu(null, parentInfo, parentPath, false);
JMenu pm = new JMenu(parentHM.getMenuTitle());
Component[] menuItems = parentMenu.getComponents();
for ( int i = 0; i < menuItems.length; i++ )
pm.add(menuItems[i]);
if ( pmenu != null ) {
pmenu.addSeparator();
pmenu.add(pm);
}
else {
menu.addSeparator();
menu.add(pm);
}
}
}
}
}
else if ( useParentMenu && info.isParentMenuInherited() ) {
TreePath parentPath = path.getParentPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)parentPath.getLastPathComponent();
AdminNode parentInfo = (AdminNode)node.getUserObject();
if ( parentInfo instanceof HasMenu )
pmenu = generateMenu(null, parentInfo, parentPath, false);
}
return pmenu;
}
public boolean checkForPopup(MouseEvent e) {
final TreePath path = getPathForLocation(e.getX(), e.getY());
if ( path == null )
return false;
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
final AdminNode info = (AdminNode)node.getUserObject();
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
TreeExpansionEvent ex = new TreeExpansionEvent(this, path);
browser_treeCollapsed(ex);
browser_treeExpanded(ex);
}
};
if ( e.isPopupTrigger() ) {
JPopupMenu mnu = generateMenu(null, info, path, true);
if ( mnu != null ) {
if ( info instanceof HasChildren && isExpanded(path) ) {
if ( info instanceof HasMenu ) {
com.dbxml.db.admin.nodes.MenuItem[] items = ((HasMenu)info).getMenu();
if ( items != null && items.length > 0 )
mnu.addSeparator();
}
JMenuItem item = new JMenuItem("Refresh");
item.addActionListener(listener);
mnu.add(item);
}
if ( mnu.getComponentCount() > 0 )
mnu.show(this, e.getX(), e.getY());
}
return true;
}
else
return false;
}
public void browser_mousePressed(MouseEvent e) {
if ( checkForPopup(e) )
return;
final TreePath path = getPathForLocation(e.getX(), e.getY());
if ( path == null )
return;
try {
admin.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
final AdminNode info = (AdminNode)node.getUserObject();
switch ( e.getClickCount() ) {
case 1:
admin.setEnableQueries(info instanceof HasCollection);
if ( menu != null )
generateMenu(menu, info, path, true);
break;
case 2:
if ( info instanceof HasDocWrapper ) {
e.consume();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Stopwatch sw = new Stopwatch("Document Retrieval", true);
DocWrapper dw = ((HasDocWrapper)info).getDocWrapper();
sw.stop();
admin.setStatus(sw.toString());
admin.editDocument(dw);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
break;
}
admin.refreshMenuBar();
}
catch ( Exception ex ) {
admin.addMessage(ex.toString());
}
finally {
admin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
public void browser_mouseClicked(MouseEvent e) {
checkForPopup(e);
}
public AdminNode getAdminRoot() {
return adminRoot;
}
public void browser_treeExpanded(TreeExpansionEvent e) {
TreePath path = e.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
if ( node == nodeRoot )
return;
admin.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
node.removeAllChildren();
AdminNode info = (AdminNode)node.getUserObject();
if ( info instanceof HasChildren ) {
HasChildren hs = (HasChildren)info;
AdminNode[] nodes = hs.getChildren();
for ( int i = 0; i < nodes.length; i++ )
node.add(new DefaultMutableTreeNode(nodes[i], nodes[i] instanceof HasChildren));
if ( nodes.length == 0 )
collapsePath(path);
}
treeModel.nodeStructureChanged(node);
admin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
public void browser_treeCollapsed(TreeExpansionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.getPath().getLastPathComponent();
if ( node == nodeRoot )
return;
closeNode(node);
node.add(new DefaultMutableTreeNode());
treeModel.nodeStructureChanged(node);
}
private void closeNode(DefaultMutableTreeNode node) {
Enumeration iter = node.children();
ArrayList list = new ArrayList();
while ( iter.hasMoreElements() )
list.add(iter.nextElement());
for ( int i = 0; i < list.size(); i++ ) {
DefaultMutableTreeNode c = (DefaultMutableTreeNode)list.get(i);
closeNode(c);
AdminNode info = (AdminNode)c.getUserObject();
if ( info != null )
info.close();
node.remove(c);
}
}
/**
* AdminNodeRenderer
*/
private class AdminNodeRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
if ( node.getUserObject() instanceof AdminNode ) {
AdminNode info = (AdminNode)node.getUserObject();
setFont(info.getFont());
setForeground(info.getColor());
setText(info.getLabel());
setIcon(info.getIcon());
setToolTipText(info.getTooltip());
setBorder(brdMargin);
}
return this;
}
}
}