/*
 * SerialPortServicesView.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.
 * 
 */

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.tree.*;
import javax.swing.border.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.text.*;




/** 
 * This class is a view panel that shows the port services
 * available for a serial port of the Digi Connect device.
 * 
 * This view can be embedded in other panels as desired.
 */


public class SerialPortServicesView extends ConfigViewImpl {
    /** A KvpNode that holds just the fields used in this view */
    KvpNode viewSettingTree;
    /** listens to the device for changes to kvpGroup */
    DeviceChangeListener settingChangeListener;
    /** Panel that holds the view content */
    GridContentPanel content;

    GridContentPanel tcpClientContent;
    GridContentPanel tcpConnectOnContent;
    GridContentPanel tcpConnectOnDataContent;
    GridContentPanel tcpConnectToContent;

    GridContentPanel udpClientContent;
    GridContentPanel udpSendOnContent;
    GridContentPanel udpSendOnDataContent;
    GridContentPanel udpSopCustomContent;
    GridContentPanel udpSatContent;
    GridContentPanel udpSabContent;
    GridContentPanel udpSendToContent;

    int MAXDESTINATIONS = 64;

    // Data fields currently used in this view
    KvpField tcpAutoConnectEnabledKvpField; 
    KvpField tcpConnectTriggerKvpField;        
    KvpField tcpConnectOnDataPatternKvpField;
    KvpField tcpConnectOnDataStripPatternKvpField;
    KvpField tcpConnectToAddressKvpField;    
    KvpField tcpConnectToProtocolKvpField;        
    KvpField tcpConnectToPortKvpField;


    KvpField udpClientEnabledKvpField;
    KvpField udpSendToEnabledKvpField[] = new KvpField[MAXDESTINATIONS];
    KvpField udpSendToAddressKvpField[] = new KvpField[MAXDESTINATIONS];
    KvpField udpSendToPortKvpField[] = new KvpField[MAXDESTINATIONS];
    KvpField udpSendToDescKvpField[] = new KvpField[MAXDESTINATIONS];
    KvpField udpSendOnDataEnabledKvpField;     
    KvpField udpSendOnDataPatternKvpField;          
    KvpField udpSendOnDataStripPatternKvpField; 
    KvpField udpSatEnabledKvpField;     
    KvpField udpSatValueKvpField;       
    KvpField udpSabEnabledKvpField;     
    KvpField udpSabValueKvpField;


    // UI Controls for each field
    JCheckBox    tcpAutoConnectEnabled_UIC;
    JRadioButton tcpConnectOnAlways_UIC;
    JRadioButton tcpConnectOnData_UIC;
    JRadioButton tcpConnectOnDSR_UIC;
    JRadioButton tcpConnectOnDCD_UIC;
    JTextField   tcpConnectOnDataPattern_UIC;
    JMenuItem    tcpConnectOnDataPatternCR_UIC; 
    JMenuItem    tcpConnectOnDataPatternCRLF_UIC;
    JCheckBox    tcpConnectOnDataStripPattern_UIC;
    JTextField   tcpConnectToAddress_UIC;
    JComboBox    tcpConnectToProtocol_UIC;
    JTextField   tcpConnectToPort_UIC;

    JCheckBox    udpClientEnabled_UIC;
    JCheckBox    udpSendToEnabled_UIC[] = new JCheckBox[MAXDESTINATIONS];
    JTextField   udpSendToAddress_UIC[] = new JTextField[MAXDESTINATIONS];
    JTextField   udpSendToPort_UIC[] = new JTextField[MAXDESTINATIONS];
    JTextField   udpSendToDesc_UIC[] = new JTextField[MAXDESTINATIONS];
    JCheckBox    udpSendOnDataEnabled_UIC;
    JTextField   udpSendOnDataPattern_UIC;
    JMenuItem    udpSendOnDataPatternCR_UIC; 
    JMenuItem    udpSendOnDataPatternCRLF_UIC;
    JCheckBox    udpSendOnDataStripPattern_UIC;
    JCheckBox    udpSatEnabled_UIC;
    JTextField   udpSatValue_UIC;
    JCheckBox    udpSabEnabled_UIC;
    JTextField   udpSabValue_UIC;



    /**
     * Basic constructor. Sets up the tree view and the edit panel.
     */
    public SerialPortServicesView() throws Exception {
        // create the KvpNode and the kvpGroup change listener
        viewSettingTree = new KvpNode();
        settingChangeListener = new DeviceChangeListener() {
            public void deviceChanged(DeviceChangeEvent e) {
                SystemLog.debug("SerialPortServicesView was notified that device kvpGroup changed");
                refreshViewData();
                refreshViewControls();
            }
        };
        // Create the panel that will hold the view controls
        content = new GridContentPanel(this.getName(),1);
        // create a listener that will detect when a user edits the field values and update the appropriate view setting fields
        ControlChangeAdapter fieldListener = new ControlChangeAdapter() {
            public void changePerformed(Object source, ActionEvent ae, FocusEvent fe) {
                if (source==tcpAutoConnectEnabled_UIC) {
                    tcpAutoConnectEnabledKvpField.setStringValue(RciProtocol.toString(tcpAutoConnectEnabled_UIC.isSelected()));
                } else if (source==tcpConnectOnAlways_UIC) {
                    if (tcpConnectOnAlways_UIC.isSelected())
                        tcpConnectTriggerKvpField.setStringValue("always");
                } else if (source==tcpConnectOnData_UIC) {
                    if (tcpConnectOnData_UIC.isSelected())
//                        tcpConnectTriggerKvpField.setStringValue("data");
                        if (tcpConnectOnDataPattern_UIC.getText().length()>0) {
                            tcpConnectTriggerKvpField.setStringValue("string");
                        } else {
                            tcpConnectTriggerKvpField.setStringValue("data");
                        }
                } else if (source==tcpConnectOnDSR_UIC) {
                    if (tcpConnectOnDSR_UIC.isSelected())
                        tcpConnectTriggerKvpField.setStringValue("dsr");
                } else if (source==tcpConnectOnDCD_UIC) {
                    if (tcpConnectOnDCD_UIC.isSelected())
                        tcpConnectTriggerKvpField.setStringValue("dcd");
                } else if (source==tcpConnectOnDataPattern_UIC) {
                    tcpConnectOnDataPatternKvpField.setStringValue(tcpConnectOnDataPattern_UIC.getText());
                    if (tcpConnectOnDataPattern_UIC.getText().length()>0) {
                        tcpConnectTriggerKvpField.setStringValue("string");
                    } else {
                        tcpConnectTriggerKvpField.setStringValue("data");
                    }
                } else if (source==tcpConnectOnDataPatternCR_UIC) {
                    tcpConnectOnDataPattern_UIC.replaceSelection("\\r");
                    tcpConnectOnDataPatternKvpField.setStringValue(tcpConnectOnDataPattern_UIC.getText());
                    tcpConnectTriggerKvpField.setStringValue("string");
                } else if (source==tcpConnectOnDataPatternCRLF_UIC) {
                    tcpConnectOnDataPattern_UIC.replaceSelection("\\r\\n");
                    tcpConnectOnDataPatternKvpField.setStringValue(tcpConnectOnDataPattern_UIC.getText());
                    tcpConnectTriggerKvpField.setStringValue("string");
                } else if (source==tcpConnectOnDataStripPattern_UIC) {
                    tcpConnectOnDataStripPatternKvpField.setStringValue(RciProtocol.toString(tcpConnectOnDataStripPattern_UIC.isSelected()));
                } else if (source==tcpConnectToAddress_UIC) {
                    tcpConnectToAddressKvpField.setStringValue(tcpConnectToAddress_UIC.getText());
                } else if (source==tcpConnectToProtocol_UIC) {
                    tcpConnectToProtocolKvpField.setStringValue(tcpConnectToProtocol_UIC.getSelectedItem().toString());
                } else if (source==tcpConnectToPort_UIC) {
                    tcpConnectToPortKvpField.setStringValue(tcpConnectToPort_UIC.getText());

                } else if (source==udpClientEnabled_UIC) {
                    udpClientEnabledKvpField.setStringValue(RciProtocol.toString(udpClientEnabled_UIC.isSelected()));
                } else if (source==udpSendOnDataEnabled_UIC) {
                    udpSendOnDataEnabledKvpField.setStringValue(RciProtocol.toString(udpSendOnDataEnabled_UIC.isSelected()));
                } else if (source==udpSendOnDataPattern_UIC) {
                    udpSendOnDataPatternKvpField.setStringValue(udpSendOnDataPattern_UIC.getText());
                } else if (source==udpSendOnDataPatternCR_UIC) {
                    udpSendOnDataPattern_UIC.replaceSelection("\\r");
                    udpSendOnDataPatternKvpField.setStringValue(udpSendOnDataPattern_UIC.getText());
                } else if (source==udpSendOnDataPatternCRLF_UIC) {
                    udpSendOnDataPattern_UIC.replaceSelection("\\r\\n");
                    udpSendOnDataPatternKvpField.setStringValue(udpSendOnDataPattern_UIC.getText());
                } else if (source==udpSendOnDataStripPattern_UIC) {
                    udpSendOnDataStripPatternKvpField.setStringValue(RciProtocol.toString(udpSendOnDataStripPattern_UIC.isSelected()));
                } else if (source==udpSatEnabled_UIC) {
                    udpSatEnabledKvpField.setStringValue(RciProtocol.toString(udpSatEnabled_UIC.isSelected()));
                } else if (source==udpSatValue_UIC) {
                    udpSatValueKvpField.setStringValue(udpSatValue_UIC.getText());
//                 } else if (source==udpSabEnabled_UIC) {
//                     udpSabEnabledKvpField.setStringValue(RciProtocol.toString(udpSabEnabled_UIC.isSelected()));
                } else if (source==udpSabValue_UIC) {
                    udpSabValueKvpField.setStringValue(udpSabValue_UIC.getText());
                } else {
                    // Next, check to see if it was one of the destination list fields
                    for (int i=0;i<MAXDESTINATIONS; i++) {
                        if (source==udpSendToEnabled_UIC[i]) {
                            udpSendToEnabledKvpField[i].setStringValue(RciProtocol.toString(udpSendToEnabled_UIC[i].isSelected()));
                        } else if (source==udpSendToAddress_UIC[i]) {
                            udpSendToAddressKvpField[i].setStringValue(udpSendToAddress_UIC[i].getText());
                        } else if (source==udpSendToPort_UIC[i]) {
                            udpSendToPortKvpField[i].setStringValue(udpSendToPort_UIC[i].getText());
                        } else if (source==udpSendToDesc_UIC[i]) {
                            udpSendToDescKvpField[i].setStringValue(udpSendToDesc_UIC[i].getText());
                        } else {
                            continue;
                        }
                        break;
                    }
                }

                refreshViewControlStates();
            }
        };


        //
        // Create the fields and put them on the view
        // 
        content.addTextLine("SerialPortServicesDesc");

        //-----------------------------------------------
        // TCP Client Services - Route Serial Port data to TCP Destination
        //-----------------------------------------------
        content.addHeadingBar("TcpClientHeading");
        content.addTextLine("TcpClientDesc");
        tcpAutoConnectEnabled_UIC = content.addJCheckBox("TcpAutoConnectEnabled", fieldListener);
        tcpClientContent = new GridContentPanel(1);
        tcpClientContent.addTextLine("TcpConnectOnConditionDesc");
        tcpConnectOnContent = new GridContentPanel(1);
        tcpConnectOnAlways_UIC = tcpConnectOnContent.addJRadioButton("TcpConnectOnAlways",fieldListener);
        tcpConnectOnData_UIC = tcpConnectOnContent.addJRadioButton("TcpConnectOnData",fieldListener);
        tcpConnectOnDataContent = new GridContentPanel(3);
        tcpConnectOnContent.addSubPanel(tcpConnectOnDataContent);
        tcpConnectOnDSR_UIC = tcpConnectOnContent.addJRadioButton("TcpConnectOnDSR",fieldListener);
        tcpConnectOnDCD_UIC = tcpConnectOnContent.addJRadioButton("TcpConnectOnDCD",fieldListener);
        ButtonGroup connectOnChoiceGroup = new ButtonGroup();
        connectOnChoiceGroup.add(tcpConnectOnAlways_UIC);
        connectOnChoiceGroup.add(tcpConnectOnData_UIC);
        connectOnChoiceGroup.add(tcpConnectOnDSR_UIC);
        connectOnChoiceGroup.add(tcpConnectOnDCD_UIC);
        tcpClientContent.addSubPanel(tcpConnectOnContent);

        tcpConnectOnDataPattern_UIC = tcpConnectOnDataContent.addJTextField("TcpConnectOnDataPattern",null,100,fieldListener, 0, false);
        tcpConnectOnDataPattern_UIC.setDocument(createGeneralDocument());
        JMenuBar patternsMenuBar = new JMenuBar();
        JMenu patternsMenu = patternsMenuBar.add(new JMenu("insert special"));
        tcpConnectOnDataPatternCR_UIC= patternsMenu.add(new JMenuItem("Carriage Return"));
        tcpConnectOnDataPatternCR_UIC.addActionListener(fieldListener);
        tcpConnectOnDataPatternCRLF_UIC= patternsMenu.add(new JMenuItem("Carriage Return/Line Feed"));
        tcpConnectOnDataPatternCRLF_UIC.addActionListener(fieldListener);
        tcpConnectOnDataContent.addField(null,patternsMenuBar,null,1,false);
        tcpConnectOnDataStripPattern_UIC = tcpConnectOnDataContent.addJCheckBox("TcpConnectOnDataStripPattern",fieldListener, 2, true);

        tcpClientContent.addTextLine("TcpConnectToDesc");
        tcpConnectToContent = new GridContentPanel(3);
        tcpConnectToAddress_UIC = tcpConnectToContent.addJTextField("TcpConnectToAddress",null,100,fieldListener, 0, false);
        tcpConnectToAddress_UIC.setDocument(createGeneralDocument());
        String tcpConnectToProtocolChoices[] = {"raw", "telnet", "ssl"};
        tcpConnectToProtocol_UIC = tcpConnectToContent.addJComboBox("TcpConnectToProtocol",null,tcpConnectToProtocolChoices,fieldListener, 1, false);
        tcpConnectToPort_UIC = tcpConnectToContent.addJTextField("TcpConnectToPort",null,100,fieldListener, 2, true);
        tcpConnectToPort_UIC.setDocument(createGeneralDocument());
        tcpClientContent.addSubPanel(tcpConnectToContent);

        content.addSubPanel(tcpClientContent);



        //-----------------------------------------------
        // UDP Client Services - Route Serial Port data to Udp Destination
        //-----------------------------------------------
        content.addHeadingBar("UdpClientHeading");
        content.addTextLine("UdpClientDesc");
        udpClientEnabled_UIC = content.addJCheckBox("UdpClientEnabled",fieldListener);
        udpClientContent = new GridContentPanel(1);

        // Add Trigger Fields
        udpClientContent.addTextLine("UdpSendOnConditionDesc");
        udpSendOnContent = new GridContentPanel(1);
        // Send On Patter (Sop)
        udpSendOnDataEnabled_UIC = udpSendOnContent.addJCheckBox("UdpSendOnDataEnabled",fieldListener);
        udpSendOnDataContent = new GridContentPanel(3);
        udpSendOnContent.addSubPanel(udpSendOnDataContent);
        udpSendOnDataPattern_UIC = udpSendOnDataContent.addJTextField("UdpSendOnDataPattern",null,100,fieldListener, 0, false);
        udpSendOnDataPattern_UIC.setDocument(createGeneralDocument());
        JMenuBar udpPatternsMenuBar = new JMenuBar();
        JMenu udpPatternsMenu = udpPatternsMenuBar.add(new JMenu("insert special"));
        udpSendOnDataPatternCR_UIC= udpPatternsMenu.add(new JMenuItem("Carriage Return"));
        udpSendOnDataPatternCR_UIC.addActionListener(fieldListener);
        udpSendOnDataPatternCRLF_UIC= udpPatternsMenu.add(new JMenuItem("Carriage Return/Line Feed"));
        udpSendOnDataPatternCRLF_UIC.addActionListener(fieldListener);
        udpSendOnDataContent.addField(null,udpPatternsMenuBar,null,1,false);
        udpSendOnDataStripPattern_UIC = udpSendOnDataContent.addJCheckBox("UdpSendOnDataStripPattern",fieldListener, 2, true);
        udpSendOnContent.addSubPanel(udpSendOnDataContent);

        //Send After Time (Sat)
        udpSatEnabled_UIC = udpSendOnContent.addJCheckBox("UdpSendAfterTimeEnabled",fieldListener);
        udpSatContent = new GridContentPanel(1);
        udpSatValue_UIC = udpSatContent.addJTextField(null,"UdpSendAfterTimeValueDesc", 100, fieldListener);
        udpSatValue_UIC.setDocument(createIntegerDocument());
        udpSendOnContent.addSubPanel(udpSatContent);

        //Send After Bytes (Sab)
        udpSendOnContent.addTextLine("UdpSendAfterBytesEnabled");
//         udpSabEnabled_UIC = udpClientContent.addJCheckBox("UdpSendAfterBytesEnabled",fieldListener);    this trigger is always on.
        udpSabContent = new GridContentPanel(1);
//        udpSabValue_UIC = udpSabContent.addJTextField(null,"UdpSendAfterBytesValueDesc",100,fieldListener);
        udpSabValue_UIC = udpSabContent.addJTextField(null,"UdpSendAfterBytesValueDesc",100,fieldListener);
        udpSabValue_UIC.setDocument(createIntegerDocument());
        udpSendOnContent.addSubPanel(udpSabContent);
        udpClientContent.addSubPanel(udpSendOnContent);

        // Add Destination Fields
        udpClientContent.addTextLine("UdpSendToListDesc");
        udpSendToContent = new GridContentPanel(5);
        udpSendToContent.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        udpSendToContent.addColumnHeading("Dest #", fieldListener, 0, false);
        udpSendToContent.addColumnHeading("UdpSendToAddress", fieldListener, 1, false);
        udpSendToContent.addColumnHeading("UdpSendToPort",    fieldListener, 2, false);
        udpSendToContent.addColumnHeading("UdpSendToDesc",    fieldListener, 3, false);
        udpSendToContent.addColumnHeading("UdpSendToEnabled", fieldListener, 4, true);
        for (int i=0; i<MAXDESTINATIONS; i++) {
            JLabel label = udpSendToContent.addJLabel(null,null,30,0,false);
            label.setText(""+(i+1));
            udpSendToAddress_UIC[i] = udpSendToContent.addJTextField(null, null, 100, fieldListener, 1, false);
            udpSendToPort_UIC[i]    = udpSendToContent.addJTextField(null, null, 100, fieldListener, 2, false);            
            udpSendToDesc_UIC[i]    = udpSendToContent.addJTextField(null, null, 100, fieldListener, 3, false);
            udpSendToEnabled_UIC[i] = udpSendToContent.addJCheckBox(null, fieldListener, 4, true);

            udpSendToAddress_UIC[i].setDocument(createNetworkAddressDocument());
            udpSendToPort_UIC[i].setDocument(createIntegerDocument());
            udpSendToDesc_UIC[i].setDocument(createGeneralDocument());
        }
        JScrollPane scrollPane = new JScrollPane(udpSendToContent);
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);
        scrollPane.setPreferredSize(new Dimension(300,100));
        udpClientContent.addSubPanel(scrollPane);              


        content.addSubPanel(udpClientContent);

        content.addVGlue();
    }

    /**
     * Returns a one word name identifying this view. 
     */
    public String getName() {
        return "SerialPortServicesView";
    }

    /** 
     * Return the Component that displays the primary content for this view
     */
    public Component getViewContent() {
        return content;
    }

    /**
     * Informs view what device to work with. View should flush any
     * cached device data and mark current view content as invalid
     * so that it is refreshed appropriatly.
     */
    public void setDevice(Device device) {
        super.setDevice(device);
        refreshViewData();
        refreshViewControls();
        device.addSettingChangeListener(settingChangeListener);
    }


    /**
     * Informs view to use the specified primary index in selecting the
     * data to display in the view. Not all views will support indexed
     * viewing and it is up to each view to define what the index is based 
     * upon. 
     * <p>
     * An example of an indexed view would be the SerialBasicView. This view
     * is indexed off the port # whose data is to be displayed in the view. An
     * external control in the SerialView lets the user select the port to view
     * and then that view instructs the SerialBasicView to use the selected 
     * port number as it's ViewIndex. Other views could use the index to base
     * their view off other integer keys such as Alarm#, Destination#,etc...
     * <p>
     * Views that do not support indexing can simply ignore this call.
     */
    public void setViewIndex(int primaryIndex) {
        super.setViewIndex(primaryIndex);
        // Rebind kvp fields for this port and then refresh controls
        bindFieldsForIndex(primaryIndex);
        refreshViewControls();
    }


    /** 
     * Refreshes the local copy of the kvpGroup displayed in the view. The updated kvpGroup come
     * from those currently cached in the Device
     */
    private void refreshViewData() {
        viewSettingTree.clear();
        int portCount=0;
        if (device!=null) {
            portCount = device.getInternalSettingTree().getChildCount("serial");
        }
        // refresh data for each port
        for (int port=1; port<=portCount; port++) {
            refreshViewDataForIndex(port);
        }
        bindFieldsForIndex(this.viewIndex);
    }

    /** 
     * Refreshes the local copy of the kvpGroup displayed in the view. The updated kvpGroup come
     * from those currently cached in the Device
     */
    private void refreshViewDataForIndex(int port) {
        // TCP Client fields
        viewSettingTree.mergeChild(device.getInternalSettingTree().getChild("autoconnect", port),true);
        // UDP Client fields
        viewSettingTree.mergeChild(device.getInternalSettingTree().getChild("udp_serial", port),true);
    }

    /** 
     * Refreshes the local copy of the kvpGroup displayed in the view. The updated kvpGroup come
     * from those currently cached in the Device
     */
    private void bindFieldsForIndex(int port) {
        // TCP Client fields
        KvpNode tcpClientSettings = viewSettingTree.getChild("autoconnect", port);
        if (tcpClientSettings!=null) {
            tcpAutoConnectEnabledKvpField        = tcpClientSettings.getChild("state"); 
            tcpConnectTriggerKvpField            = tcpClientSettings.getChild("trigger"); 
            tcpConnectOnDataPatternKvpField      = tcpClientSettings.getChild("pattern"); 
            tcpConnectOnDataStripPatternKvpField = tcpClientSettings.getChild("strip_pattern"); 
            tcpConnectToAddressKvpField          = tcpClientSettings.getChild("address"); 
            tcpConnectToProtocolKvpField         = tcpClientSettings.getChild("service"); 
            tcpConnectToPortKvpField             = tcpClientSettings.getChild("port"); 
        }


        // UDP Client fields
        KvpNode udpClientSettings = viewSettingTree.getChild("udp_serial", port);
        if (udpClientSettings!=null) {
            udpClientEnabledKvpField = udpClientSettings.getChild("state");
            for (int i=0;i<MAXDESTINATIONS; i++) {
                KvpNode aDest = udpClientSettings.getChild("dest", i+1);
                udpSendToEnabledKvpField[i] = aDest.getChild("state");
                udpSendToAddressKvpField[i] = aDest.getChild("address");
                udpSendToPortKvpField[i] = aDest.getChild("port");
                udpSendToDescKvpField[i] = aDest.getChild("desc");
            }
            udpSendOnDataEnabledKvpField      = udpClientSettings.getChild("trigger_on_pattern");     
            udpSendOnDataPatternKvpField      = udpClientSettings.getChild("pattern");          
            udpSendOnDataStripPatternKvpField = udpClientSettings.getChild("strip_pattern"); 
            udpSatEnabledKvpField      = udpClientSettings.getChild("trigger_on_timeout");     
            udpSatValueKvpField        = udpClientSettings.getChild("timeout");       
            //udpSabEnabledKvpField    = udpClientSettings.getChild("trigger_on_count");     
            udpSabValueKvpField        = udpClientSettings.getChild("count");       
        }

    }



    /** 
     * Refreshes the state of the controls in the view to match the data in the views kvpGroup.
     */
    private void refreshViewControls() {
        // Set TCP Client Values
        if (tcpAutoConnectEnabledKvpField!=null) {
            tcpAutoConnectEnabled_UIC.setSelected(RciProtocol.booleanValue(tcpAutoConnectEnabledKvpField.getStringValue()));
        }
        if (tcpConnectTriggerKvpField!=null) {
            String trigger = tcpConnectTriggerKvpField.getStringValue();
            if (trigger.equals("always")) {
                tcpConnectOnAlways_UIC.setSelected(true);
            } else if (trigger.equals("data") || trigger.equals("string")) {
                tcpConnectOnData_UIC.setSelected(true);
            } else if (trigger.equals("dsr")) {
                tcpConnectOnDSR_UIC.setSelected(true);
            } else if (trigger.equals("dcd")) {
                tcpConnectOnDCD_UIC.setSelected(true);
            }
        }
        if (tcpConnectOnDataPatternKvpField!=null) {
            tcpConnectOnDataPattern_UIC.setText(tcpConnectOnDataPatternKvpField.getStringValue());
        }
        if (tcpConnectOnDataStripPatternKvpField!=null) {
            tcpConnectOnDataStripPattern_UIC.setSelected(RciProtocol.booleanValue(tcpConnectOnDataStripPatternKvpField.getStringValue()));
        }
        if (tcpConnectToAddressKvpField!=null) {
            tcpConnectToAddress_UIC.setText(tcpConnectToAddressKvpField.getStringValue());
        }
        if (tcpConnectToProtocolKvpField!=null) {
            tcpConnectToProtocol_UIC.setSelectedItem(tcpConnectToProtocolKvpField.getStringValue());
        }
        if (tcpConnectToPortKvpField!=null) {
            tcpConnectToPort_UIC.setText(tcpConnectToPortKvpField.getStringValue());
        }


        // Set UDP Client Values
        if (udpClientEnabledKvpField != null)
            udpClientEnabled_UIC.setSelected(RciProtocol.booleanValue(udpClientEnabledKvpField.getStringValue()));
        for (int i = 0; i < MAXDESTINATIONS; i++) {
            if (udpSendToEnabledKvpField[i] != null)
                udpSendToEnabled_UIC[i].setSelected(RciProtocol.booleanValue(udpSendToEnabledKvpField[i].getStringValue()));
            if (udpSendToAddressKvpField[i] != null)
                udpSendToAddress_UIC[i].setText(udpSendToAddressKvpField[i].getStringValue());
            if (udpSendToPortKvpField[i] != null)
                udpSendToPort_UIC[i].setText(udpSendToPortKvpField[i].getStringValue());
            if (udpSendToDescKvpField[i] != null)
                udpSendToDesc_UIC[i].setText(udpSendToDescKvpField[i].getStringValue());
        }
        if (udpSendOnDataEnabledKvpField != null)
            udpSendOnDataEnabled_UIC.setSelected(RciProtocol.booleanValue(udpSendOnDataEnabledKvpField.getStringValue()));

        if (udpSendOnDataPatternKvpField!=null) {
            udpSendOnDataPattern_UIC.setText(udpSendOnDataPatternKvpField.getStringValue());
        }
        if (udpSendOnDataStripPatternKvpField!=null) {
            udpSendOnDataStripPattern_UIC.setSelected(RciProtocol.booleanValue(udpSendOnDataStripPatternKvpField.getStringValue()));
        }
        if (udpSatValueKvpField != null)
            udpSatValue_UIC.setText(udpSatValueKvpField.getStringValue());
        if (udpSatEnabledKvpField != null)
            udpSatEnabled_UIC.setSelected(RciProtocol.booleanValue(udpSatEnabledKvpField.getStringValue()));

        if (udpSabValueKvpField != null)
            udpSabValue_UIC.setText(udpSabValueKvpField.getStringValue());
//         if (udpSabEnabledKvpField != null)
//             udpSabEnabled_UIC.setSelected(RciProtocol.booleanValue(udpSabEnabledKvpField.getStringValue()));

        refreshViewControlStates();
    }

    private void refreshViewControlStates() {
        // If no device data is available, then disable everything
        if (udpClientEnabledKvpField == null) {
            content.setContainerEnabled(false);
            return;
        }
        // Otherwise, start by enabling everything and then pruning it back as needed
        content.setContainerEnabled(true);

        // Disable TCP Controls
        // Set Individual States
        tcpConnectOnAlways_UIC.setEnabled(tcpConnectTriggerKvpField!=null);
        tcpConnectOnData_UIC.setEnabled(tcpConnectTriggerKvpField!=null);
        tcpConnectOnDSR_UIC.setEnabled(tcpConnectTriggerKvpField!=null);
        tcpConnectOnDCD_UIC.setEnabled(tcpConnectTriggerKvpField!=null);
        tcpConnectOnDataPattern_UIC.setEnabled(tcpConnectOnDataPatternKvpField!=null);
        tcpConnectOnDataStripPattern_UIC.setEnabled(tcpConnectOnDataStripPatternKvpField!=null);
        tcpConnectToAddress_UIC.setEnabled(tcpConnectToAddressKvpField!=null);
        tcpConnectToProtocol_UIC.setEnabled(tcpConnectToProtocolKvpField!=null);
        tcpConnectToPort_UIC.setEnabled(tcpConnectToPortKvpField!=null);

        // Disable Container States if Not Selected
        if (tcpAutoConnectEnabledKvpField==null || !tcpAutoConnectEnabled_UIC.isSelected()) {
            tcpClientContent.setContainerEnabled(false);
        } else {
            if (!tcpConnectOnData_UIC.isSelected()) {
                tcpConnectOnDataContent.setContainerEnabled(false);
            }
        }



        // Disable UDP Controls
        // Set Individual States
        udpClientEnabled_UIC.setEnabled(udpClientEnabledKvpField != null);
        udpSendOnDataEnabled_UIC.setEnabled(udpSendOnDataEnabledKvpField != null);
        udpSendOnDataPattern_UIC.setEnabled(udpSendOnDataPatternKvpField!=null);
        udpSendOnDataStripPattern_UIC.setEnabled(udpSendOnDataStripPatternKvpField!=null);
        udpSatValue_UIC.setEnabled(udpSatValueKvpField != null);
        udpSatEnabled_UIC.setEnabled(udpSatEnabledKvpField != null);
        udpSabValue_UIC.setEnabled(udpSabValueKvpField != null);
//        udpSabEnabled_UIC.setEnabled(udpSabEnabledKvpField != null);
        for (int i = 0; i < MAXDESTINATIONS; i++) {
            udpSendToEnabled_UIC[i].setEnabled(udpSendToEnabledKvpField[i] != null);
            udpSendToAddress_UIC[i].setEnabled(udpSendToAddressKvpField[i] != null);
            udpSendToPort_UIC[i].setEnabled(udpSendToPortKvpField[i] != null);
            udpSendToDesc_UIC[i].setEnabled(udpSendToDescKvpField[i] != null);
        }        

        // Disable Container States if Not Selected
        if (udpClientEnabledKvpField == null || !udpClientEnabled_UIC.isSelected())
            udpClientContent.setContainerEnabled(false);
        else {
            if (udpSendOnDataEnabledKvpField == null || !udpSendOnDataEnabled_UIC.isSelected())
                udpSendOnDataContent.setContainerEnabled(false);
            if (udpSatEnabledKvpField == null || !udpSatEnabled_UIC.isSelected())
                udpSatContent.setContainerEnabled(false);
//             if (udpSabEnabledKvpField == null || !udpSabEnabled_UIC.isSelected())
//                 udpSabContent.setContainerEnabled(false);
        }
    }


    /**
     * This method is called to instruct the view that it is about to be made
     * active. When a view is active it needs to make sure its content is correct.
     * An example of why a panel may be inactive is if it were on a tabbed pane 
     * and was not currently visible or if the user selected some other view.
     */
    public void activate() {
        SystemLog.debug("Activating "+getName());
    }

    /**
     * This method is called to instruct the view that it is about to be made
     * inactive. When a view is inactive, it does not need to worry
     * about maintaining its content in a correct state. An example of why a panel
     * may be inactive is if it were on a tabbed pane and was not currently visible
     * or if the user selected some other view.
     */
    public void deactivate() {
        SystemLog.debug("Deactivating "+getName());
    }

    /**
     * Indicates if any changes have been made by the user that have not yet been
     * saved to the device(ie committed).
     */
    public boolean isChanged() {
        return viewSettingTree.hasChanged();
    }

    /**
     * This method instructs the view to validate any of the changes the user has made
     * within the view. Any errors are to be added to the provided errorList. 
     * 
     * @param errorList is a collection of ViewValidationError objects
     */
    public void validateChanges(Collection errorList) {
        try {

            // Validate TCP Client
            if (tcpAutoConnectEnabled_UIC.isSelected()) {
//                 if (!ValidationHelper.isValidIPAddress(tcpConnectToAddress_UIC.getText()) ||
//                     InetAddress.getByName(tcpConnectToAddress_UIC.getText()).equals(InetAddress.getByName("0.0.0.0")))
//                     errorList.add(new ValidationError("SerialTcpConnectToAddressError"));
//                 if (!ValidationHelper.isValidNetworkPort(tcpConnectToPort_UIC.getText()) ||
//                     (Integer.parseInt(tcpConnectToPort_UIC.getText()) <= 0))
//                     errorList.add(new ValidationError("SerialTcpConnectToPortError"));
            }

            // Validate UDP Client
            if (udpClientEnabled_UIC.isSelected()) {
                // Verify String Mode if Enabled
//                 if (udpSendOnDataEnabled_UIC.isSelected()) {
//                     if (udpSopCR_UIC.isSelected() || udpSopCRLF_UIC.isSelected()) {
//                         // Nothing to Validate
//                     } else if (udpSopCustom_UIC.isSelected()) {
//                         if (udpSendOnDataPattern_UIC.getText().length() == 0)
//                             errorList.add(new ValidationError("SerialUdpCustomStringError"));
//                     } else errorList.add(new ValidationError("SerialUdpSendOnPatternError"));
//                 }

                // Verify Send after Byte Mode if Enabled
//                if (udpSabEnabled_UIC.isSelected()) {
                if (!ValidationHelper.isValidRange(udpSabValue_UIC.getText(), 4, 4096))
                    errorList.add(new ValidationError("SerialUdpSendAfterByteError"));
//                }

                // Verify Send after Time Mode if Enabled
                if (udpSatEnabled_UIC.isSelected()) {
                    if (!ValidationHelper.isValidRange(udpSatValue_UIC.getText(), 1, 65535))
                        errorList.add(new ValidationError("SerialUdpSendAfterTimeError"));
                }

                // Verify Destinations
                for (int i = 0; i < MAXDESTINATIONS; i++) {
                    if (!ValidationHelper.isValidIPAddress(udpSendToAddress_UIC[i].getText()))
                        errorList.add(new ValidationError("SerialUdpDestinationAddressError", new Serializable[]{ String.valueOf(i+1)}));
                    if (!ValidationHelper.isValidNetworkPort(udpSendToPort_UIC[i].getText()))
                        errorList.add(new ValidationError("SerialUdpDestinationPortError", new Serializable[]{ String.valueOf(i+1)}));

                    if (udpSendToEnabled_UIC[i].isSelected()) {
                        // Verify Valid
                        if (InetAddress.getByName(udpSendToAddress_UIC[i].getText()).equals(InetAddress.getByName("0.0.0.0")))
                            errorList.add(new ValidationError("SerialUdpDestinationAddressError", new Serializable[]{ String.valueOf(i+1)}));
                        if (Integer.parseInt(udpSendToPort_UIC[i].getText()) <= 0)
                            errorList.add(new ValidationError("SerialUdpDestinationPortError", new Serializable[]{ String.valueOf(i+1)}));
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("Caught Exception in SerialPortServicesView::validationChanges()");
            e.printStackTrace();
        }
    }

    /**
     * This method instructs the view to place any changes the user has made within 
     * the view into the provided clusters. Once the changes have been saved to
     * to the device, a subsequent call to commitChanges() will be made.
     */
    public void getChanges(KvpNode settingCluster, KvpNode stateCluster) {
        // Merge the view changes into the provided cluster
        settingCluster.merge(viewSettingTree, false);
    }

    /**
     * Instructs the view to consider any user changes within the view as 
     * saved to the device (ie committed).
     */
    public void commitChanges() {
        // simply reset flags indicating user changes in the contols
        viewSettingTree.resetChanged();
    }

    /** 
     * Instructs the view to discard any changes the user has made within the
     * view and revert those fields to the original state. The view is also 
     * free to refresh all its fields to the present cached state of the device at 
     * this time.
     */
    public void cancelChanges() {
        refreshViewData();
        refreshViewControls();
    }


}

