/*
 * ConfigAppPanel.java
 * 
 * Copyright (c) 2003-2004 Digi International
 * This program and the information contained in it is confidential and
 * proprietary to Digi International and may not be used, copied, or re-
 * produced without the prior written permission of Digi International.
 * 
 * All rights reserved.
 */

package com.digi.config.ui;

import com.digi.config.core.*;
import com.digi.config.util.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.lang.Thread;

import javax.xml.parsers.*;
import org.w3c.dom.*;



/** 
 * This class represents the main configuration user interface. This class is
 * a JPanel that can be imbedded in other constructs such as a JFrame or an Applet. 
 */


public class ConfigAppPanel extends CustomPanel implements StatusDisplay {

    /** Proxy to the device we are configuring */
    Device device;
    /** TitleBar area of the config screen */
    JPanel titleBar = null;
    /** MenuBar area of the config screen */
    JMenuBar menuBar = null;
    /** Toolbar area of the config screen */
    JToolBar toolBar = null;
    /** Holds the MenuBar & ToolBar components */
    JPanel actionPanel = null;
    /** Navigation menu area of the config screen */
    JPanel navigationPanel = null;
    /** View Details area of the config screen */
    JPanel contentPanel = null;
    /** Status area of the config screen */
    StatusPanel statusPanel = null;
    /** Display/Edit panel showing URL applet is connected to */
    JPanel urlPanel = null;
    /** Message area of the config screen */
    private MessageArea messageArea;
    /** Secure access tray icon */
    SecureAccessIcon secureAccessIcon = null;

    boolean showMenuBar = false;                   // finish this... fetch these from config props
    boolean showToolBar = false;
    boolean showNavigationPanel = true;
    boolean artificialFrame = false;


    // The preferred size of the view area
    private static final int PREFERRED_WIDTH = 720;
    private static final int PREFERRED_HEIGHT = 640;


    // Available Actions   Finish this... move these into a Dynamic list of Actions
    Action homeAction;
    Action configAllAction;
    Action networkAction;
    Action serialAction;
    Action gpioAction;
    Action securityAction;
    Action systemAction;
    Action alarmAction;
    Action rebootAction;
    Action backupAction;
    Action updateFirmwareAction;
    Action factoryAction;
    Action configHelpAction;
    Action viewHelpAction;

    // Available Configuration views    Finish this... move these into a Dynamic list of Views
    ConfigView homeView;
    ConfigView configAllView;
    ConfigView networkView;
    ConfigView serialView;
    ConfigView gpioView;
    ConfigView securityView;
    ConfigView systemView;
    ConfigView alarmView;
    ConfigView backupView;
    ConfigView rebootView;
    ConfigView factoryView;

    /** The currently selected ConfigView */
    ConfigView currentView;



    /**
     * ConfigAppPanel Constructor
     */
    public ConfigAppPanel() throws Exception {
        this(true);
    }
    public ConfigAppPanel(boolean artificialFrame) throws Exception {
        super("App");
        this.artificialFrame = artificialFrame;

        ConfigTheme configTheme = new ConfigTheme();
        MetalLookAndFeel.setCurrentTheme(configTheme);
        UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        Color tabbedPaneColor = ConfigSettings.getColor("WindowSettings", "TabbedPaneBackgroundColor");
        if (tabbedPaneColor!=null) {
            UIManager.put("TabbedPane.selected", tabbedPaneColor);
        }

        if ((this.backgroundImage==null) && 
            ((this.backgroundColor==null) || (this.backgroundColor.getAlpha()==0))) {
            this.setBackground(ConfigSettings.getColor("WindowSettings", "BackgroundColor"));
        }
//        this.setBackground(Color.WHITE);
        this.setBorder(new EtchedBorder());

        // Set up the Device proxy
        device = new Device();
        SplashScreenPanel.currentScreen().updateProgress();

        // Try initializing the cached kvpGroup        
        try {
            device.refreshSettingTree();
            SplashScreenPanel.currentScreen().updateProgress();
        } catch (DeviceCommandException dce) {
            SystemLog.log("DeviceNotAvailable", new Serializable[]{device.getUrlName()}, dce);
        }

        // Setup the actions and associated views
        initializeActions();
        //initializeViews();      // To defer the building of views until first touch comment this line

        // Define the content of the panel
        setLayout(new BorderLayout());  
        add(getActionPanel(), BorderLayout.NORTH);
        JPanel workPanel = new JPanel();
        workPanel.setLayout(new BorderLayout());
        workPanel.setOpaque(false);
        workPanel.add(getNavigationPanel(), BorderLayout.WEST);
        workPanel.add(getContentPanel(), BorderLayout.CENTER);
        JSplitPane mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, workPanel, getMessageAreaPanel());
        mainSplit.setOpaque(false);
        mainSplit.setDividerLocation(-1); // Position relative to components size
        mainSplit.setResizeWeight(1);     // Use any extra space on top
        mainSplit.setDividerSize(1);
        add(mainSplit, BorderLayout.CENTER);
        add(getStatusPanel(), BorderLayout.SOUTH);

        // If running standalone, or in developer mode, show the URL Panel too
        if (!ConfigSettings.getBoolean("General", "AppletMode") ||
            ConfigSettings.getBoolean("DebugSettings", "GeneralDebug")) {       // only show this view to developers
            statusPanel.addTrayComponent(getUrlPanel());
        }

        // TODO: handle this somewhere else and implement some type of listener
        // so that we can detect when the URL/protocol changes.
        secureAccessIcon = new SecureAccessIcon(device.getUrlName());
        statusPanel.addTrayComponent(secureAccessIcon);

        // Show/Hide menu components as specified
        boolean useMenus = ConfigSettings.getBoolean("PropertiesSettings", "UseMenus");

        getMenuBar().setVisible(useMenus);
        getToolBar().setVisible(useMenus);
        getNavigationPanel().setVisible(!useMenus);

        Busy.registerGUIComponent(this);

        // initially position to the home view
        doHomeAction();

        SplashScreenPanel.currentScreen().updateProgress();
    }

//    /**
//     * Called to set the font in the components
//     * @param String - name of font
//     * @param int - size of font
//     */
//    public void setUIFont (String name, int size){
//        int style = 1;
//        java.util.Enumeration keys = UIManager.getDefaults().keys();
//        while (keys.hasMoreElements()) {
//            Object key = keys.nextElement();
//            Object value = UIManager.get (key);
//            if (value instanceof javax.swing.plaf.FontUIResource) {
//                style = ((FontUIResource)value).getStyle();
//                UIManager.put (key,new FontUIResource(name, style, size));
//            }
//        }
//    }    
//

    /**
    * Defines the main actions that can be invoked from the menus or
    * toolbar buttons. These actions will be used to construct the menus &
    * toolbar buttons.
    */
    public void initializeActions() throws Exception {        
        SplashScreenPanel.currentScreen().updateProgress();

        // finish this... can we somehow assign the view to the action here???
        homeAction      = new ConfigAction("Home", this, "doHomeAction");
        configAllAction = new ConfigAction("ConfigAll", this, "doConfigAllAction");
        networkAction = new ConfigAction("Network", this, "doNetworkAction");
        serialAction = new ConfigAction("Serial", this, "doSerialAction");
        gpioAction = new ConfigAction("Gpio", this, "doGpioAction");
        securityAction = new ConfigAction("Security", this, "doSecurityAction");
        systemAction = new ConfigAction("System", this, "doSystemAction");
        alarmAction      = new ConfigAction("Alarm", this, "doAlarmAction");
        backupAction      = new ConfigAction("Backup", this, "doBackupAction");
        rebootAction = new ConfigAction("Reboot", this, "doRebootAction");
        updateFirmwareAction      = new ConfigAction("UpdateFirmware", this, "doUpdateFirmwareAction");
        factoryAction = new ConfigAction("RestoreFactoryDefaults", this, "doFactoryAction");
        configHelpAction      = new ConfigAction("ConfigHelp", this, "doConfigHelpAction");
        viewHelpAction      = new ConfigAction("ViewHelp", this, "doViewHelpAction");

        SplashScreenPanel.currentScreen().updateProgress();
    }


    /**
     * Creates and initializes the view's used in the configuration application.
     * 
     * Note: this could be handled on first touch of each view as well.
     */
    public void initializeViews() throws Exception {
        SplashScreenPanel.currentScreen().updateProgress();

        homeView = new HomeView();
        homeView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        configAllView = new GlobalSettingView();
        configAllView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        networkView = new NetworkView();
        networkView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        serialView = new SerialView();
        serialView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        gpioView = new GpioView();
        gpioView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        securityView = new SecurityView();
        securityView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        systemView = new SystemView();
        systemView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        alarmView = new AlarmGpioView();
        alarmView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        backupView = new BackupView();
        backupView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        rebootView = new RebootView();
        rebootView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();

        factoryView = new RestoreFactoryDefaultsView();
        factoryView.setDevice(device);
        SplashScreenPanel.currentScreen().updateProgress();
    }


    /**
     * Gets the panel that holds the action controls (ie menu and toolbar) - creating
     * if necessary.
     */
    public JPanel getActionPanel() {
        if (actionPanel==null) {
            actionPanel = new JPanel();
            actionPanel.setLayout(new BoxLayout(actionPanel, BoxLayout.Y_AXIS));
            if (artificialFrame) {
                actionPanel.add(getTitleBar());
            }
            actionPanel.add(getMenuBar());
            actionPanel.add(getToolBar());
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return actionPanel;
    }

    /**
     * Gets the panel that holds the action controls (ie menu and toolbar) - creating
     * if necessary.
     */
    public JPanel getNavigationPanel() {
        if (navigationPanel==null) {
            SplashScreenPanel.currentScreen().updateProgress();

            navigationPanel = new CustomPanel("Navigation");
            navigationPanel.setLayout(new BoxLayout(navigationPanel, BoxLayout.Y_AXIS));
            navigationPanel.setBorder(new EtchedBorder());

            JMenuBar menuBar = getMenuBar();
            JButton button;
            Color menuColor = ConfigSettings.getColor("WindowSettings","MenuColor");
            if (menuColor==null) {
                menuColor = Color.BLUE;
            }
            for (int i=0; i<menuBar.getMenuCount(); i++) {
                JMenu menu = menuBar.getMenu(i);
                Component navItem;
                if (menu!=null) {
                    //System.out.println("Menu["+i+"] is "+menu.getText());
                    if (menu.getAction()==null) {
                        navItem = new JLabel(menu.getText());
                        ((JLabel)navItem).setBorder(BorderFactory.createEmptyBorder(2,10,2,10));
                    } else {
                        navItem = new JButton(menu.getAction());
                        ((JButton)navItem).setContentAreaFilled(false);
                        ((JButton)navItem).setBorderPainted(false);
                        ((JButton)navItem).setForeground(menuColor);
                        ((JButton)navItem).setIcon(null);
                        ((JButton)navItem).setBorder(BorderFactory.createEmptyBorder(2,10,2,10));
                        ((JButton)navItem).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                    }
                    navigationPanel.add(navItem);
                    //System.out.println("  menu has "+menu.getMenuComponentCount()+" items");
                    for (int j=0; j<menu.getMenuComponentCount(); j++) {
                        Component c = menu.getMenuComponent(j);
                        if ((c!=null) && (c instanceof JMenuItem)) {
                            JMenuItem item = (JMenuItem)c;
                            //System.out.println("MenuItem["+i+","+j+"] is "+item.getText());
                            if (item.getAction()==null) {
                                navItem = new JLabel(item.getText());
                                ((JLabel)navItem).setBorder(BorderFactory.createEmptyBorder(2,20,2,10));
                            } else {
                                navItem = new JButton(item.getAction());
                                ((JButton)navItem).setContentAreaFilled(false);
                                ((JButton)navItem).setBorderPainted(false);
                                ((JButton)navItem).setForeground(menuColor);
                                ((JButton)navItem).setIcon(null);
                                ((JButton)navItem).setBorder(BorderFactory.createEmptyBorder(2,20,2,10));
                                ((JButton)navItem).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                            }
                            navigationPanel.add(navItem);
                            if (item instanceof JMenu) {
                                // further submenu... finish this...
                            }
                        }
                    }
                }
            }

            // properly size ourselves
            int width=ConfigSettings.getInteger("WindowSettings",
                                                "NavigationAreaWidth");
            int height=ConfigSettings.getInteger("WindowSettings",
                                                 "NavigationAreaHeight");
            navigationPanel.setSize(width, height);
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return navigationPanel;
    }



    public JPanel getTitleBar() {
        if (titleBar==null) {
            titleBar = new JPanel();
            titleBar.setBackground(new Color(0, 0, 139));
            JLabel title = new JLabel(ConfigResource.getUiRbString("AppTitle"));
            title.setForeground(Color.WHITE);
            titleBar.add(title);
            titleBar.setAlignmentX(Component.LEFT_ALIGNMENT);
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return titleBar;
    }

    // Finish this...eventually create the menu from the dynamically loaded menu hierarchy
    public JMenuBar getMenuBar() {
        if (menuBar==null) {
            JMenu menu;
            menuBar = new JMenuBar();

            menuBar.add(new JMenu(homeAction));
            menu = menuBar.add(new JMenu("Configuration"));
            menu.add(new JMenuItem(networkAction));
            if (device.getDeviceModelInfo().getSerialPortCount()>0) {
                menu.add(new JMenuItem(serialAction));
            }
            if (device.hasGpio()) {
                menu.add(new JMenuItem(gpioAction));
            }
            menu.add(new JMenuItem(securityAction));
            if (ConfigSettings.getBoolean("DebugSettings", "GeneralDebug")) {       // only show this view to developers
                menu.add(new JMenuItem(configAllAction));
            }

            if (device.getDeviceModelInfo().getAlarmCount()>0) {
                menu = menuBar.add(new JMenu("Management"));
                menu.add(new JMenuItem(alarmAction));
            }

            menu = menuBar.add(new JMenu("Administration"));
            menu.add(new JMenuItem(backupAction));
            //menu.add(new JMenuItem(updateFirmwareAction));  // Not in initial Release
            menu.add(new JMenuItem(factoryAction));
            menu.add(new JMenuItem(systemAction));
            menu.add(new JMenuItem(rebootAction));

            //menu = menuBar.add(new JMenu("Logout"));        // Not in initial Release

            menuBar.add(Box.createHorizontalGlue());

            //menu = menuBar.add(new JMenu("Help"));          // Not in initial Release
            //menu.add(new JMenuItem(configHelpAction));      // Not in initial Release
            //menu.add(new JMenuItem(viewHelpAction));        // Not in initial Release

            menuBar.setAlignmentX(Component.LEFT_ALIGNMENT);
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return menuBar;
    }

    // Finish this...eventually create the menu from the dynamically loaded menu hierarchy
    public JToolBar getToolBar() {
        if (toolBar==null) {
            toolBar = new JToolBar();
            toolBar.add(configAllAction);
            toolBar.add(viewHelpAction);
            toolBar.add(Box.createHorizontalGlue());
            toolBar.setAlignmentX(Component.LEFT_ALIGNMENT);
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return toolBar;
    }

    /**
     * Returns the panel that holds the current view
     */
    public JPanel getContentPanel() {
        if (contentPanel==null) {
//             contentPanel = new JPanel(new BorderLayout());
//             contentPanel.setBorder(BorderFactory.createEtchedBorder());
//             contentPanel.setBackground(this.getBackground());
//             // properly size ourselves
//             int width=ConfigSettings.getInteger("WindowSettings",
//                 "ContentAreaWidth");
//             int height=ConfigSettings.getInteger("WindowSettings",
//                 "ContentAreaHeight");
//             contentPanel.setSize(width, height);
            contentPanel = new CustomPanel("Content");
            contentPanel.setLayout(new BorderLayout());
            contentPanel.setBorder(BorderFactory.createEtchedBorder());
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return contentPanel;
    }


    /**
     * Returns the panel that holds the status line
     */
    public StatusPanel getStatusPanel() throws Exception {
        statusPanel = StatusPanel.getInstance();
        SplashScreenPanel.currentScreen().updateProgress();
        return statusPanel;
    }

    /**
     * Returns the panel that displays the URL of the device we are connected to. User can
     * also edit the URL which results in us changing the device we are connected to.
     */
    public JPanel getUrlPanel() {
        if (urlPanel==null) {
            // content pane that lets user type a URL and press enter. Then we will
            // post the the url, read the replay, and put it into the output text area.
            urlPanel = new JPanel(new BorderLayout());
            JLabel urlLabel = new JLabel("RCI Server URL: ");
            urlPanel.add(urlLabel, BorderLayout.WEST);
            JTextField urlField = new JTextField();
            urlField.setMaximumSize(new Dimension(250,20));
            urlField.setPreferredSize(new Dimension(250,20));
            urlField.setText(device.getUrlName());
            urlField.addActionListener(new ActionListener() {
                                           public void actionPerformed(ActionEvent e) {
                                               try {
                                                   String urlStr = ((JTextField)e.getSource()).getText();
                                                   device.setUrlName(urlStr);
                                                   secureAccessIcon.setSecure(urlStr);
                                                   device.refreshSettingTree();
                                                   device.refreshStateTree();
                                                   doHomeAction();
                                               } catch (DeviceCommandException dce) {
                                                   SystemLog.log("DeviceNotAvailable", new Serializable[]{device.getUrlName()}, dce);
                                               } catch (Exception ex) {
                                                   SystemLog.log("Op1Fail", new Serializable[] {"SetDeviceIP"}, ex);
                                               }
                                           }
                                       });
            urlPanel.add(urlField, BorderLayout.CENTER);
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return urlPanel;
    }

    /**
     * Define the message area - this is where log messages are displayed.
     * @return a message panel
     */
    private MessageArea getMessageAreaPanel() throws Exception {
        if (messageArea==null) {
            messageArea = new MessageArea();
            messageArea.doRefreshLogAction();
            messageArea.doSetMinimumSeverityInformationFilterAction();
            SplashScreenPanel.currentScreen().updateProgress();
        }
        return messageArea;
    }



    /**
     * Switches contents of the ContentPanel to the specified view. Disables
     * the previous view and activates the new view.
     */
    public void switchToView(ConfigView view) {
        if (view==null) {
            return;
        }
        // deactivate and remove the old view if it exists
        if (currentView!=null) {
            contentPanel.removeAll();
            currentView.deactivate();
        }
        // activate and insert the new view
        view.activate();
        if (view.getViewHeading()!=null) {
            contentPanel.add(view.getViewHeading(), BorderLayout.NORTH);
        }
        if (view.getViewContent()!=null) {
            JScrollPane scrollPane = new JScrollPane(view.getViewContent());
            scrollPane.setOpaque(false);
            scrollPane.getViewport().setOpaque(false);
//             scrollPane.setOpaque(true);
//             scrollPane.getViewport().setOpaque(true);
//             Color clear = new Color(0,0,0,0);
//             scrollPane.setBackground(clear);
//             scrollPane.getViewport().setBackground(clear);

//            scrollPane.setPreferredSize(new Dimension(500,500));
            contentPanel.add(scrollPane, BorderLayout.CENTER);
        }
        if (view.getViewButtons()!=null) {
            contentPanel.add(view.getViewButtons(), BorderLayout.SOUTH);
        }
        this.revalidate();
        this.repaint();

        // record this as the current view
        currentView = view;
    }


    /*************** Status Display interface methods ***************/

    /**
     * Update the status of the UI.
     * Sets the cursor and status panel text.
     * @param busy if true status should indicate a busy state.
     * @param text status text to be displayed.
     */
    public void updateStatus(boolean busy, String text) {
        statusPanel.setStatusText(text);
        if (busy) {
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        } else {
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }

    /**
     * Get the current status text.
     * @return the current status text.
     */
    public String getStatusText() {
        return statusPanel.getStatusText();
    }


    /*************** Custom Action methods *************/

    // finish this... it would be REALLY nice if we modified the ConfigAction to allow passing a
    // parameter to the call. Then at action definition, we could specify the view to be switched
    // to and call a single switchToView method that went to the appropriate view. Then all the 
    // view creation and mapping is done right in the initializeActions where we will probably be
    // loading it from an XML file anyway.
    public void doHomeAction() throws Exception {
        if (homeView==null) {
            SplashScreenPanel.currentScreen().updateProgress();

            homeView = new HomeView();
            homeView.setDevice(device);
        }
        switchToView(homeView);
    }

    public void doConfigAllAction() throws Exception {
        if (configAllView==null) {
            configAllView = new GlobalSettingView();
            configAllView.setDevice(device);
        }
        switchToView(configAllView);
    }

    public void doNetworkAction() throws Exception {
        if (networkView==null) {
            networkView = new NetworkView();
            networkView.setDevice(device);
        }
        switchToView(networkView);
    }

    public void doSerialAction() throws Exception {
        if (serialView==null) {
            serialView = new SerialView();
            serialView.setDevice(device);
        }
        switchToView(serialView);
    }

    public void doGpioAction() throws Exception {
        if (gpioView==null) {
            gpioView = new GpioView();
            gpioView.setDevice(device);
        }
        switchToView(gpioView);
    }

    public void doSecurityAction() throws Exception {
        if (securityView==null) {
            securityView = new SecurityView();
            securityView.setDevice(device);
        }
        switchToView(securityView);
    }

    public void doSystemAction() throws Exception {
        if (systemView==null) {
            systemView = new SystemView();
            systemView.setDevice(device);
        }
        switchToView(systemView);   
    }

    public void doAlarmAction() throws Exception {
        if (alarmView==null) {
            alarmView = new AlarmGpioView();
            alarmView.setDevice(device);
        }
        switchToView(alarmView);
    }

    public void doBackupAction() throws Exception {
        if (backupView==null) {
            backupView = new BackupView();
            backupView.setDevice(device);
        }
        switchToView(backupView);
    }

    public void doRebootAction() throws Exception {
        if (rebootView==null) {
            rebootView = new RebootView();
            rebootView.setDevice(device);
        }
        switchToView(rebootView);   
    }

    public void doUpdateFirmwareAction() throws Exception {
        String deviceUrlName = device.getUrlName();
        String path="";
        try {
            URL url = new URL(deviceUrlName);
            path = url.getProtocol()+"://"+url.getHost()+"/admin/upgrade_firmware.htm";
            HelpDisplay.showHelp(path);
        } catch (Exception e) {
            SystemLog.log("DeviceNotAvailable", new Serializable[] {path}, e);
        }
    }

    public void doFactoryAction() throws Exception {
        if (factoryView==null) {
            factoryView = new RestoreFactoryDefaultsView();
            factoryView.setDevice(device);
        }
        switchToView(factoryView);   
    }

    public void doConfigHelpAction() throws Exception {
        HelpDisplay.showHelp("UserGuide");
    }

    public void doViewHelpAction() throws Exception {
        String key = currentView.getHelpResource();
        if (key==null) {
            SystemLog.log("NoHelpAvailable");
        } else {
            SystemLog.debug("Launching view help . Help key = "+key);
            HelpDisplay.showHelp(key);
        }
    }






    private void dumpNode(Node node, StringBuffer buffer, String prefix) {
//         if ((node.getNodeType()==Node.TEXT_NODE) &&
//             (node.getNodeValue().trim().length()==0)) {
//             return; // skip empty text nodes
//         }

        buffer.append(prefix+"Node Name = "+node.getNodeName()+
                      ", Type = "+node.getNodeType()+
                      ", Value = '"+node.getNodeValue()+"'\n");
    }

    private void dumpTree(Node branchNode, StringBuffer buffer, String prefix) {
        // First dump the branch node
        dumpNode(branchNode, buffer, prefix);
        // Next iterate through the child branches and dump them
        NodeList nodeList = branchNode.getChildNodes();
        String childPrefix = prefix+"  ";
        for (int i=0; i<nodeList.getLength(); i++) {
            Node child = nodeList.item(i);
            dumpTree(child, buffer, childPrefix);
        }
    }

    private void dump(Throwable t, StringBuffer buffer) {
        buffer.append(t.getMessage()); 
        StringWriter writer = new StringWriter();
        t.printStackTrace(new PrintWriter(writer));
        buffer.append(writer.getBuffer().toString());
    }



    private class ConfigTheme extends DefaultMetalTheme {
        Color control;
        Color black;
        Color white;
        Color primary1;
        Color primary2;
        Color primary3;
        Color secondary1;
        Color secondary2;
        Color secondary3;
        Font  windowTitleFont;
        Font  systemTextFont; 
        Font  userTextFont; 
        Font  controlTextFont;
        Font  menuTextFont; 
        Font  subTextFont;

        {
            control = ConfigSettings.getColor("WindowSettings","ControlColor");
            black = ConfigSettings.getColor("WindowSettings","Black","WindowSettings","TextColor");
            white = ConfigSettings.getColor("WindowSettings","White","WindowSettings","BackgroundColor");
            primary1 = ConfigSettings.getColor("WindowSettings","Primary1");
            primary2 = ConfigSettings.getColor("WindowSettings","Primary2");
            primary3 = ConfigSettings.getColor("WindowSettings","Primary3");
            secondary1 = ConfigSettings.getColor("WindowSettings","Secondary1");
            secondary2 = ConfigSettings.getColor("WindowSettings","Secondary2","WindowSettings","DisabledColor");
            secondary3 = ConfigSettings.getColor("WindowSettings","Secondary3","WindowSettings","ControlColor");
            windowTitleFont = ConfigSettings.getFont("WindowSettings","WindowTitleFont","WindowSettings","TextFont");
            systemTextFont = ConfigSettings.getFont("WindowSettings","SystemTextFont","WindowSettings","TextFont");
            userTextFont = ConfigSettings.getFont("WindowSettings","UserTextFont","WindowSettings","TextFont");
            controlTextFont = ConfigSettings.getFont("WindowSettings","ControlTextFont","WindowSettings","TextFont");
            menuTextFont = ConfigSettings.getFont("WindowSettings","MenuTextFont","WindowSettings","TextFont");
            subTextFont = ConfigSettings.getFont("WindowSettings","SubTextFont","WindowSettings","TextFont");
        }


        public ColorUIResource getControl() {
            return(control!=null) ? new ColorUIResource(control) : super.getControl();
        }
        protected ColorUIResource getBlack() {
            return(black!=null) ? new ColorUIResource(black) : super.getBlack();
        }
        protected ColorUIResource getWhite() {
            return(white!=null) ? new ColorUIResource(white) : super.getWhite();
        }
        protected ColorUIResource getPrimary1() {
            return(primary1!=null) ? new ColorUIResource(primary1) : super.getPrimary1();
        }
        protected ColorUIResource getPrimary2() {
            return(primary2!=null) ? new ColorUIResource(primary2) : super.getPrimary2();
        }
        protected ColorUIResource getPrimary3() {
            return(primary3!=null) ? new ColorUIResource(primary3) : super.getPrimary3();
        }
        protected ColorUIResource getSecondary1() {
            return(secondary1!=null) ? new ColorUIResource(secondary1) : super.getSecondary1();
        }
        protected ColorUIResource getSecondary2() {
            return(secondary2!=null) ? new ColorUIResource(secondary2) : super.getSecondary2();
        }
        protected ColorUIResource getSecondary3() {
            return(secondary3!=null) ? new ColorUIResource(secondary3) : super.getSecondary3();
        }
        public FontUIResource getWindowTitleFont() {
            return(windowTitleFont!=null) ? new FontUIResource(windowTitleFont) : super.getWindowTitleFont();
        }
        public FontUIResource getSystemTextFont() {
            return(systemTextFont!=null) ? new FontUIResource(systemTextFont) : super.getSystemTextFont();
        }
        public FontUIResource getUserTextFont() {
            return(userTextFont!=null) ? new FontUIResource(userTextFont) : super.getUserTextFont();
        }
        public FontUIResource getControlTextFont() {
            return(controlTextFont!=null) ? new FontUIResource(controlTextFont) : super.getControlTextFont();
        }
        public FontUIResource getMenuTextFont() {
            return(menuTextFont!=null) ? new FontUIResource(menuTextFont) : super.getMenuTextFont();
        }
        public FontUIResource getSubTextFont() {
            return(subTextFont!=null) ? new FontUIResource(subTextFont) : super.getSubTextFont();
        }
    }


}

