/** * PanelIDEBrowser.java - a SQL Connection Browser. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * @author David Martinez <david@hackerdude.com> * Revision: $Revision$ * Id : $Id$ * */ package com.hackerdude.apps.sqlide.plugins.browser; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Event; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeWillExpandListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.ExpandVetoException; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import com.hackerdude.apps.sqlide.ProgramConfig; import com.hackerdude.apps.sqlide.ProgramIcons; import com.hackerdude.apps.sqlide.SqlIdeApplication; import com.hackerdude.apps.sqlide.dataaccess.DatabaseProcess; import com.hackerdude.apps.sqlide.dataaccess.DatabaseService; import com.hackerdude.apps.sqlide.dataaccess.HostConfigRegistry; import com.hackerdude.apps.sqlide.nodes.CategoryDbUsersNode; import com.hackerdude.apps.sqlide.nodes.CategoryGeneralUsersNode; import com.hackerdude.apps.sqlide.nodes.CategoryIndexesNode; import com.hackerdude.apps.sqlide.nodes.CategoryTriggerNode; import com.hackerdude.apps.sqlide.nodes.CategoryUsersNode; import com.hackerdude.apps.sqlide.nodes.ItemIndexNode; import com.hackerdude.apps.sqlide.nodes.ItemServerNode; import com.hackerdude.apps.sqlide.nodes.ItemUserNode; import com.hackerdude.apps.sqlide.pluginapi.IDEVisualPluginIF; import com.hackerdude.apps.sqlide.pluginapi.NodeIDEBase; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.CategoryCatalogsNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.CategoryColumnsNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.CategorySchemaNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.CategoryTableNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.ItemCatalogNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.ItemSchemaNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.ItemTableColumnNode; import com.hackerdude.apps.sqlide.plugins.browser.browsejdbc.ItemTableNode; import com.hackerdude.lib.GPLAboutDialog; /** * Based on the sqlIDE Config, this browser * creates as many server nodes as necessary, and * it initializes all the default nodes. Eventually * we'll use these nodes and their DatabaseProcess' * classes to get metadata and server information. * * @version $Id$ * */ public class PluginIDEBrowser extends JPanel implements IDEVisualPluginIF { DatabaseProcess currentProcess; BrowserModel serverBrowser; DBBrowserTree browserTree; DefaultMutableTreeNode rootNode; JScrollPane scroll; BorderLayout mainBorderLayout = new BorderLayout(); JPanel browserPanel = new JPanel(); BorderLayout browserPanelBorderLayout = new BorderLayout(); JPanel bottomPanel = new JPanel(); JLabel lblInfo = new JLabel(); SqlIdeApplication ide; BorderLayout borderLayout3 = new BorderLayout(); public final Action ACTION_POPUP_MENU = new PopupMenuAction(); private final BrowserRenderer BROWSER_RENDERER = new BrowserRenderer(); private final TreeSelectionListener BROWSER_SELECTION_LISTENER = new IDEBrowserSelectionListener(); private final TreeWillExpandListener BROWSER_WILL_EXPAND_LISTENER = new BrowserWillExpandListener(); private Action[] contextActions = NULL_ACTIONS; public static final String PROPERTY_ELEMENT_SELECTED = "nodeSelected"; /** * JBuilder likes this */ public void jbInit() { rootNode = new DefaultMutableTreeNode("My Environment"); // Override the drawing for the tree with our own class, below. this.setLayout(mainBorderLayout); browserPanel.setLayout(browserPanelBorderLayout); bottomPanel.setLayout(borderLayout3); lblInfo.setText("Info:"); lblInfo.setIcon(ProgramIcons.getInstance().findIcon("images/Inform.gif")); this.setMinimumSize(new Dimension(200, 58)); this.add(browserPanel, BorderLayout.CENTER); browserPanel.add(bottomPanel, BorderLayout.SOUTH); createBrowserTree(); } public void createBrowserTree() { JScrollPane oldScroll = null; if (scroll != null) oldScroll = scroll; browserTree = new DBBrowserTree(rootNode); scroll = new JScrollPane(browserTree); browserTree.setShowsRootHandles(false); browserTree.addMouseListener(new BrowserTreePopupAdapter()); browserTree.putClientProperty("JTree.lineStyle", "Angled"); browserTree.addTreeWillExpandListener(BROWSER_WILL_EXPAND_LISTENER); browserTree.addTreeSelectionListener(BROWSER_SELECTION_LISTENER); browserPanel.add(scroll, BorderLayout.CENTER); scroll.getViewport().add(browserTree, null); bottomPanel.add(lblInfo, BorderLayout.CENTER); // BROWSER_RENDERER.setOpenIcon(ProgramIcons.getInstance().getExpandIcon()); // BROWSER_RENDERER.setClosedIcon(ProgramIcons.getInstance().getCollapseIcon()); browserTree.setCellRenderer(BROWSER_RENDERER); browserTree.setVisible(true); browserTree.setFont(ProgramConfig.getInstance().getFont(ProgramConfig.PROP_FONT_FOR_BROWSER)); if (oldScroll != null) browserPanel.remove(oldScroll); if (ide != null) ide.pack(); } /** * A basic selection listener for the browser tree. It changes the current * process for this plugin and it also changes the information label in the * bottom to reflect what has been selected. */ class IDEBrowserSelectionListener implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent e) { determineContextActions(); TreePath leadSelectionPath = e.getNewLeadSelectionPath(); Object[] objs; if (leadSelectionPath == null) return; objs = leadSelectionPath.getPath(); TreeNode myNode; for (int i = 0; i < objs.length; i++) { myNode = (TreeNode) objs[i]; if (myNode != null && myNode instanceof ItemServerNode) { currentProcess = ( (ItemServerNode) myNode).getDatabaseProcess(); } } TreePath selectionPath = browserTree.getSelectionPath(); if (selectionPath == null) { lblInfo.setText(""); return; } TreeNode tn = (DefaultMutableTreeNode) selectionPath.getLastPathComponent(); NodeIDEBase bn = null; if (tn instanceof NodeIDEBase) { bn = (NodeIDEBase) tn; firePropertyChange(PROPERTY_ELEMENT_SELECTED, null, bn); } if (bn != null) lblInfo.setText(bn.getInfo()); } } /** * Constructor. */ public PluginIDEBrowser() { super(); } public void initPlugin() { jbInit(); serverBrowser = new BrowserModel(rootNode); // UIManager.put("Tree.exp andedIcon", new IconUIResource(ProgramIcons.getInstance().getExpandIcon())); // UIManager.put("Tree.collapsedIcon", new IconUIResource(ProgramIcons.getInstance().getCollapseIcon())); if (currentProcess == null) currentProcess = DatabaseService.getInstance().getDatabaseProcess( HostConfigRegistry.getInstance().getSqlideHostConfig(0) ); } public void freePlugin() { // } public void setSQLIDE(SqlIdeApplication ide) { this.ide = ide; } /** * Creates the IdeBrowser-specific menu. */ public JMenu createPanelMenu(JMenu parent) { return (null); } /** * Shows/hides the menus. */ public void setVisibleMenus(boolean value, JMenu menu) { } /** * Returns the Currently selected Database Process. */ public DatabaseProcess getDatabaseProcess() { System.out.println("[PanelIDEBrowser] " + currentProcess); return (currentProcess); } /** * Since this is a collection panel and doesn't have * one database process (it can potentially have many, * or even zero), this method is empty. It is not very * common to have this method empty, but it does happen * in "Browser tree" situations that span across multiple * servers. */ public void setDatabaseProcess(DatabaseProcess proc) {} /** * Returns the "short name" for this plugin (to be put on * the tabs on a TabbedPane, for instance). */ public String getPluginShortName() { return ("Browser"); } public String getPluginName() { return "SQL-IDE Browser"; } /** * Returns the version of this plugin as a string. */ public String getPluginVersion() { return ("$Revision$"); } /** * The listener for the expansion of the nodes. * * see treeWillExpand call. */ class BrowserWillExpandListener implements TreeWillExpandListener { /** * This method is called by the tree when the node is about to expand * and before it actually does. This node */ public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException { setCursor(new Cursor(Cursor.WAIT_CURSOR)); TreePath path = e.getPath(); Object comp = path.getLastPathComponent(); if (comp == null) return; // Odd... ignore. NodeIDEBase node = null; try { node = (NodeIDEBase) comp; } catch (ClassCastException exc) { // Don't do anything } if (node == null) { setCursor(Cursor.getDefaultCursor()); return; } // Remove all the children, and re-read them. node.removeAllChildren(); try { /* Read the standard children for this node, and also ask any running browser extension plugins to put their contributions to this node (if any). */ node.readChildren(); ide.requestAddSubNodes(node); } catch (Exception exc) { node.removeAllChildren(); node.add(new DefaultMutableTreeNode("Dummy")); setCursor(Cursor.getDefaultCursor()); throw new ExpandVetoException(e); } setCursor(Cursor.getDefaultCursor()); } // Required by TreeWillExpandListener interface. public void treeWillCollapse(TreeExpansionEvent e) { TreePath path = e.getPath(); Object comp = path.getLastPathComponent(); try { NodeIDEBase node = (NodeIDEBase) comp; node.removeChildren(); } catch (ClassCastException exc) {} } } /** * The Renderer for the different Icons */ class BrowserRenderer extends DefaultTreeCellRenderer { final ImageIcon folderIcon = ProgramIcons.getInstance().findIcon("images/Folder.gif"); final ImageIcon catalogIcon = ProgramIcons.getInstance().getDatabaseIcon(); final ImageIcon schemaIcon = ProgramIcons.getInstance().findIcon("images/Data.gif"); final ImageIcon serverIcon = ProgramIcons.getInstance().getServerIcon(); final ImageIcon loginsIcon = ProgramIcons.getInstance().getLoginsIcon(); final ImageIcon storedProcIcon = ProgramIcons.getInstance().getStoredProcIcon(); final ImageIcon triggerIcon = ProgramIcons.getInstance().getTriggerIcon(); // final ImageIcon expandIcon = ProgramIcons.getInstance().getExpandIcon(); // final ImageIcon collapseIcon = ProgramIcons.getInstance().getCollapseIcon(); final ImageIcon columnIcon = ProgramIcons.getInstance().findIcon("images/Column.gif"); final ImageIcon tableIcon = ProgramIcons.getInstance().findIcon("images/Sheet.gif"); final ImageIcon indexIcon = ProgramIcons.getInstance().findIcon("images/BCard.gif"); final ImageIcon usersIcon = ProgramIcons.getInstance().findIcon("images/Users.gif"); final ImageIcon userIcon = ProgramIcons.getInstance().findIcon("images/User.gif"); public BrowserRenderer() { /* setOpenIcon(expandIcon); setClosedIcon(collapseIcon);*/ } 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); // Get this node. TreeNode node = (TreeNode) value; ImageIcon icon = null; TreeNode parent = node.getParent(); icon = getIconfor(node); if (tree.getModel().getRoot() == value) { icon = ProgramIcons.getInstance().getRootIcon(); } if (icon == null) { System.out.println("[PanelIDEBrowser] Couldn't find icon for class " + node.getClass().getName()); } // Still No icon?? Put a default on it. if (icon == null) { icon = folderIcon; } ; setIcon(icon); return this; } protected ImageIcon getIconfor(TreeNode treeNode) { Class nodeClass = treeNode.getClass(); ImageIcon icon = null; if ( treeNode instanceof NodeIDEBase ) { icon = ((NodeIDEBase)treeNode).getIcon(); } if ( icon != null ) return icon; if (nodeClass == ItemCatalogNode.class || nodeClass == CategoryCatalogsNode.class) { icon = catalogIcon; } if (nodeClass == ItemSchemaNode.class || nodeClass == CategorySchemaNode.class) { icon = schemaIcon; } if (nodeClass == ItemTableNode.class) { icon = tableIcon; } if (nodeClass == CategoryTableNode.class) { icon = folderIcon; } if (nodeClass == CategoryTriggerNode.class) { icon = triggerIcon; } if (nodeClass == ItemIndexNode.class) { icon = indexIcon; } if (nodeClass == ItemServerNode.class) { icon = serverIcon; } if (nodeClass == CategoryIndexesNode.class) { icon = indexIcon; } if (nodeClass == CategoryColumnsNode.class) { icon = columnIcon; } if (nodeClass == ItemTableColumnNode.class) { icon = columnIcon; } if (nodeClass == CategoryUsersNode.class) { icon = usersIcon; } if (nodeClass == CategoryGeneralUsersNode.class) { icon = usersIcon; } if (treeNode instanceof ItemUserNode) { icon = userIcon; } if (nodeClass == CategoryDbUsersNode.class) { icon = catalogIcon; } return icon; } } public boolean isActionPossible(String action) { boolean theResult = false; if (action.equals("Cut")) {} ; if (action.equals("Copy")) {} ; if (action.equals("Paste")) {} ; return (theResult); } public boolean executeAction(String action) { /** @todo Implement */ return false; } public void showAboutBox() { GPLAboutDialog gpl = new GPLAboutDialog(this, "IDE Browser Panel", getPluginVersion(), "A Tree-Based Multiple Database browser panel for SQLIDE.", "(C) 1999 by David Martinez."); gpl.actionPerformed(null); } public void refreshPanel() { // serverBrowser = new BrowserModel(rootNode); // createBrowserTree(); DefaultTreeModel model = (DefaultTreeModel)browserTree.getModel(); serverBrowser.createDBNodes(); model.nodeStructureChanged(rootNode); browserTree.setFont(ProgramConfig.getInstance().getFont(ProgramConfig.PROP_FONT_FOR_BROWSER)); } /** * This is a Popup Adapter for the browser tree. It actually checks for the * right-click because some JDKs don't have a registered gesture (at least * as of JDK1.2). */ public class BrowserTreePopupAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e) { try { /** @todo This does not work on MacOS */ if (e.getModifiers() == InputEvent.BUTTON3_MASK || e.getModifiers() == InputEvent.CTRL_MASK) { if (contextActions == null || contextActions.length > 0) { JPopupMenu thisMenu = new JPopupMenu("Actions"); for (int i = 0; i < contextActions.length; i++) thisMenu.add(contextActions[i]); if (thisMenu != null) { Double theX = new Double(e.getPoint().getX()); Double theY = new Double(e.getPoint().getY()); thisMenu.show(browserTree, theX.intValue(), theY.intValue()); } } } } catch (Exception ex) { ex.printStackTrace(); } } } /** * Determines the available context actions for this panel. These actions * change when the current selection changes on the browser. */ public void determineContextActions() { TreePath[] selectedPaths = browserTree.getSelectionModel().getSelectionPaths(); if (selectedPaths == null) return; NodeIDEBase[] selectedNodes = new NodeIDEBase[selectedPaths.length]; for (int i = 0; i < selectedPaths.length; i++) { Object lastPathComponent = selectedPaths[i].getLastPathComponent(); Object selectedNode = lastPathComponent; if (selectedNode instanceof NodeIDEBase) { selectedNodes[i] = (NodeIDEBase) selectedNode; } else return; } contextActions = ide.getActionsFor(selectedNodes); } public JPopupMenu getPopupMenuFor(NodeIDEBase node) { return null; } public Action[] getPossibleActions() { return contextActions; } public void receivePluginFocus() { browserTree.requestFocus(); } public Icon getPluginIcon() { return ProgramIcons.getInstance().findIcon("images/World2.gif"); } public boolean executeStandardAction(ActionEvent evt) { /** @todo Implement. */ return false; } public class PopupMenuAction extends AbstractAction { public PopupMenuAction() { super("Display Popup Menu"); putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F12, Event.CTRL_MASK, false)); // putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_A)); } public void actionPerformed(ActionEvent e) { // if ( about == null ) { // about = new AboutDialog(frame); // about.pack(); // Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // double x = ( screenSize.getWidth() - about.getWidth() ) / 2; // double y = ( screenSize.getHeight() - about.getHeight() ) / 2; // about.setBounds(new Double(x).intValue(), new Double(y).intValue(), about.getWidth(), about.getHeight()); // } // about.show(); } } }