Пример #1
0
    def OnSelect(self, event):
        item = event.GetSelection()
        event_id = event.GetId()
        if event_id == ID_CBX_SEL_STATION:
            keyItem = self.cbxStationID.GetClientData(item)
            print 'Station cbx, item ', item, 'key', keyItem
            # refill the Loggers combobox based on the Series selected
            stSQLLoggers = """SELECT Loggers.ID, Loggers.LoggerSerialNumber
            FROM (ChannelSegments LEFT JOIN DataChannels
            ON ChannelSegments.ChannelID = DataChannels.ID)
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID
            WHERE (((ChannelSegments.StationID)={iSe}))
            GROUP BY Loggers.ID, Loggers.LoggerSerialNumber;
            """.format(iSe=keyItem)
            scidb.fillComboboxFromSQL(self.cbxLoggerID, stSQLLoggers)

            stSQLChan = """SELECT DataChannels.ID, ( DataChannels.Column || ',' ||
            Loggers.LoggerSerialNumber || ',' ||  Sensors.SensorSerialNumber || ',' ||
            DataTypes.TypeText || ',' ||  DataUnits.UnitsText || ',' ||
            DataChannels.UTC_Offset) AS Channel,
            DataSeries.DataSeriesDescription AS Series,
            ChannelSegments.SegmentBegin AS Begin
            FROM (((((DataChannels
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID)
            LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID)
             LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID)
            LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID)
            LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID)
            LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID
            WHERE Loggers.ID IN (SELECT Loggers.ID
            FROM (ChannelSegments LEFT JOIN DataChannels
            ON ChannelSegments.ChannelID = DataChannels.ID)
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID
            WHERE (((ChannelSegments.StationID)={iSe}))
            GROUP BY Loggers.ID, Loggers.LoggerSerialNumber)
            """.format(iSe=keyItem)
            scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan,
                                            [300, 180, 140])

        if event_id == ID_CBX_SEL_LOGGER:
            keyItem = self.cbxLoggerID.GetClientData(item)
            print 'Logger cbx, item ', item, 'key', keyItem
            stSQLChan = """SELECT DataChannels.ID, ( DataChannels.Column || ',' ||
            Loggers.LoggerSerialNumber || ',' ||  Sensors.SensorSerialNumber || ',' ||
            DataTypes.TypeText || ',' ||  DataUnits.UnitsText || ',' ||
            DataChannels.UTC_Offset) AS Channel,
            DataSeries.DataSeriesDescription AS Series,
            ChannelSegments.SegmentBegin AS Begin
            FROM (((((DataChannels
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID)
            LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID)
             LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID)
            LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID)
            LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID)
            LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID
            WHERE Loggers.ID = {iSe}
            """.format(iSe=keyItem)
            scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan,
                                            [300, 180, 140])
Пример #2
0
    def OnSelect(self, event):
        item = event.GetSelection()
        event_id = event.GetId()
        if event_id == ID_CBX_SEL_STATION:
            keyItem = self.cbxStationID.GetClientData(item)
            print 'Station cbx, item ', item, 'key', keyItem
            # refill the Loggers combobox based on the Series selected
            stSQLLoggers = """SELECT Loggers.ID, Loggers.LoggerSerialNumber
            FROM (ChannelSegments LEFT JOIN DataChannels
            ON ChannelSegments.ChannelID = DataChannels.ID)
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID
            WHERE (((ChannelSegments.StationID)={iSe}))
            GROUP BY Loggers.ID, Loggers.LoggerSerialNumber;
            """.format(iSe=keyItem)
            scidb.fillComboboxFromSQL(self.cbxLoggerID, stSQLLoggers)

            stSQLChan = """SELECT DataChannels.ID, ( DataChannels.Column || ',' ||
            Loggers.LoggerSerialNumber || ',' ||  Sensors.SensorSerialNumber || ',' ||
            DataTypes.TypeText || ',' ||  DataUnits.UnitsText || ',' ||
            DataChannels.UTC_Offset) AS Channel,
            DataSeries.DataSeriesDescription AS Series,
            ChannelSegments.SegmentBegin AS Begin
            FROM (((((DataChannels
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID)
            LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID)
             LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID)
            LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID)
            LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID)
            LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID
            WHERE Loggers.ID IN (SELECT Loggers.ID
            FROM (ChannelSegments LEFT JOIN DataChannels
            ON ChannelSegments.ChannelID = DataChannels.ID)
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID
            WHERE (((ChannelSegments.StationID)={iSe}))
            GROUP BY Loggers.ID, Loggers.LoggerSerialNumber)
            """.format(iSe=keyItem)
            scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan, [300, 180, 140])

        if event_id == ID_CBX_SEL_LOGGER:
            keyItem = self.cbxLoggerID.GetClientData(item)
            print 'Logger cbx, item ', item, 'key', keyItem
            stSQLChan = """SELECT DataChannels.ID, ( DataChannels.Column || ',' ||
            Loggers.LoggerSerialNumber || ',' ||  Sensors.SensorSerialNumber || ',' ||
            DataTypes.TypeText || ',' ||  DataUnits.UnitsText || ',' ||
            DataChannels.UTC_Offset) AS Channel,
            DataSeries.DataSeriesDescription AS Series,
            ChannelSegments.SegmentBegin AS Begin
            FROM (((((DataChannels
            LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID)
            LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID)
             LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID)
            LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID)
            LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID)
            LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID
            WHERE Loggers.ID = {iSe}
            """.format(iSe=keyItem)
            scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan, [300, 180, 140])
Пример #3
0
    def LayoutMaskingSetupPanel(self, pnl):

        pnl.SetBackgroundColour(wx.WHITE)
        iLinespan = 5
        stpSiz = wx.GridBagSizer(1, 1)
        
        gRow = 0
        stpLabel = wx.StaticText(pnl, -1, 'Set up Masking here')
        stpSiz.Add(stpLabel, pos=(gRow, 0), span=(1, 2), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl), pos=(gRow, 0), span=(1, iLinespan), flag=wx.EXPAND)
        
        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Narrow Logger(s) to Station:'),
                     pos=(gRow, 0), span=(1, 2), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)

        stSQLStations = 'SELECT ID, StationName FROM Stations;'
        self.cbxStationID = wx.ComboBox(pnl, ID_CBX_SEL_STATION, style=wx.CB_READONLY)
        scidb.fillComboboxFromSQL(self.cbxStationID, stSQLStations)
        stpSiz.Add(self.cbxStationID, pos=(gRow, 2), span=(1, 3), flag=wx.LEFT, border=5)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Narrow Channel choices to Logger:'),
                     pos=(gRow, 0), span=(1, 2), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)

        stSQLLoggers = 'SELECT ID, LoggerSerialNumber FROM Loggers;'
        self.cbxLoggerID = wx.ComboBox(pnl, ID_CBX_SEL_LOGGER, style=wx.CB_READONLY)
        scidb.fillComboboxFromSQL(self.cbxLoggerID, stSQLLoggers)
        stpSiz.Add(self.cbxLoggerID, pos=(gRow, 2), span=(1, 3), flag=wx.LEFT, border=5)

        self.Bind(wx.EVT_COMBOBOX, self.OnSelect)

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl), pos=(gRow, 0), span=(1, iLinespan), flag=wx.EXPAND)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Data Channel:'),
                     pos=(gRow, 0), span=(1, 2), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)

        self.cbxChanID = wx.combo.ComboCtrl(pnl, ID_CHAN_TEXT, "", style=wx.CB_READONLY | wx.TE_PROCESS_ENTER)
        self.chanPopup = ListCtrlComboPopup()
#        pnl.chanPopup.id = ID_CHAN_LIST
        # It is important to call SetPopupControl() as soon as possible
        self.cbxChanID.SetPopupControl(self.chanPopup)
        stpSiz.Add(self.cbxChanID, pos=(gRow, 2), span=(1, 7), flag=wx.LEFT, border=5)
        stSQLChan = "SELECT DataChannels.ID, " \
            "( DataChannels.Column || ',' ||  Loggers.LoggerSerialNumber || ',' ||  " \
            "Sensors.SensorSerialNumber || ',' ||  DataTypes.TypeText || ',' ||  " \
            "DataUnits.UnitsText || ',' ||  DataChannels.UTC_Offset) AS Channel, " \
            "DataSeries.DataSeriesDescription AS Series, ChannelSegments.SegmentBegin AS Begin " \
            "FROM (((((DataChannels LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID) " \
            "LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID) " \
            "LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID) " \
            "LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID) " \
            "LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID) " \
            "LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID;"
        scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan, [300, 180, 140])
#        pnl.chanPopup.AddItem(("a",None,3,4,5,6,7)) # test AddItem w /every imaginable error

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl), pos=(gRow, 0), span=(1, iLinespan), flag=wx.EXPAND)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Time interval to view, in Universal Time'),
                     pos=(gRow, 1), span=(1, 5), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Start'),
                     pos=(gRow, 0), span=(1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
        self.tcDTStart = wx.TextCtrl(pnl, ID_START_TIME, style=wx.TE_PROCESS_ENTER)
        self.tcDTStart.Bind(wx.EVT_TEXT_ENTER, self.OnEnterKey)
        self.tcDTStart.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        stpSiz.Add(self.tcDTStart, pos=(gRow, 1), span=(1, 3), 
            flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)
#        self.tcDTStart.SetValue('2010-06-13 5pm') # for testing
        self.tcDTStart.SetValue('timestamp, or blank for first in Channel')

        # add StartTime adjustment buttons
        sbHorizSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.StartDayDnButton = wx.Button(pnl, ID_ST_DAY_DN_BTN, '<Da', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_ST_DAY_DN_BTN)
        sbHorizSizer.Add(self.StartDayDnButton)

        self.StartHourDnButton = wx.Button(pnl, ID_ST_HOUR_DN_BTN, '<Hr', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_ST_HOUR_DN_BTN)
        sbHorizSizer.Add(self.StartHourDnButton)

        self.StartHourUpButton = wx.Button(pnl, ID_ST_HOUR_UP_BTN, 'Hr>', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_ST_HOUR_UP_BTN)
        sbHorizSizer.Add(self.StartHourUpButton)

        self.StartDayUpButton = wx.Button(pnl, ID_ST_DAY_UP_BTN, 'Da>', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_ST_DAY_UP_BTN)
        sbHorizSizer.Add(self.StartDayUpButton)

        stpSiz.Add(sbHorizSizer, pos=(gRow, 4), span=(1, 1))

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'End'),
                     pos=(gRow, 0), span=(1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
        self.tcDTEnd = wx.TextCtrl(pnl, ID_END_TIME, style=wx.TE_PROCESS_ENTER)
        self.tcDTEnd.Bind(wx.EVT_TEXT_ENTER, self.OnEnterKey)
        self.tcDTEnd.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        stpSiz.Add(self.tcDTEnd, pos=(gRow, 1), span=(1, 3), 
            flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)
        
#        self.tcDTEnd.SetValue('2010-06-14 5pm') # for testing
        self.tcDTEnd.SetValue('timestamp, or blank for last in Channel')

        # add EndTime adjustment buttons
        ebHorizSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.EndDayDnButton = wx.Button(pnl, ID_EN_DAY_DN_BTN, '<Da', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_EN_DAY_DN_BTN)
        ebHorizSizer.Add(self.EndDayDnButton)

        self.EndHourDnButton = wx.Button(pnl, ID_EN_HOUR_DN_BTN, '<Hr', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_EN_HOUR_DN_BTN)
        ebHorizSizer.Add(self.EndHourDnButton)

        self.EndHourUpButton = wx.Button(pnl, ID_EN_HOUR_UP_BTN, 'Hr>', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_EN_HOUR_UP_BTN)
        ebHorizSizer.Add(self.EndHourUpButton)

        self.EndDayUpButton = wx.Button(pnl, ID_EN_DAY_UP_BTN, 'Da>', style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON,  self.OnTimeAdjustButton, id=ID_EN_DAY_UP_BTN)
        ebHorizSizer.Add(self.EndDayUpButton)

        stpSiz.Add(ebHorizSizer, pos=(gRow, 4), span=(1, 1))
        
        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl), pos=(gRow, 0), span=(1, iLinespan), flag=wx.EXPAND)

        gRow += 1
        mrbVertSizer = wx.BoxSizer(wx.VERTICAL)
        
        self.rbMask = wx.RadioButton(pnl, ID_RB_MASK, label='Mask', style=wx.RB_GROUP)
        mrbVertSizer.Add(self.rbMask, proportion=0, flag=wx.ALIGN_LEFT|wx.LEFT)
        self.rbMask.Bind(wx.EVT_RADIOBUTTON, self.giveRBInfo)

        self.rbUnmask = wx.RadioButton(pnl, ID_RB_UNMASK, label='Unmask')
        mrbVertSizer.Add(self.rbUnmask, proportion=0, flag=wx.ALIGN_LEFT|wx.LEFT)
        self.rbUnmask.Bind(wx.EVT_RADIOBUTTON, self.giveRBInfo)

        iRBLeftBorderWd = 30
        stpSiz.Add(mrbVertSizer, pos=(gRow, 0), span=(1, 2), 
            flag=wx.ALIGN_LEFT|wx.LEFT, border=iRBLeftBorderWd)

        self.applyButton = wx.Button(pnl, ID_APPLY_BTN, 'Apply')
        self.Bind(wx.EVT_BUTTON,  self.OnApplyBtn, id=ID_APPLY_BTN)
        stpSiz.Add(self.applyButton, pos=(gRow, 3), span=(1, 1), 
            flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)

        self.giveRBInfo(-1) # have to explictly call this 1st time; -1 is dummy value for event

        pnl.SetSizer(stpSiz)
        pnl.SetAutoLayout(1)
        pnl.SetupScrolling()
Пример #4
0
    def LayoutMaskingSetupPanel(self, pnl):

        pnl.SetBackgroundColour(wx.WHITE)
        iLinespan = 5
        stpSiz = wx.GridBagSizer(1, 1)

        gRow = 0
        stpLabel = wx.StaticText(pnl, -1, 'Set up Masking here')
        stpSiz.Add(stpLabel,
                   pos=(gRow, 0),
                   span=(1, 2),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl),
                   pos=(gRow, 0),
                   span=(1, iLinespan),
                   flag=wx.EXPAND)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Narrow Logger(s) to Station:'),
                   pos=(gRow, 0),
                   span=(1, 2),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)

        stSQLStations = 'SELECT ID, StationName FROM Stations;'
        self.cbxStationID = wx.ComboBox(pnl,
                                        ID_CBX_SEL_STATION,
                                        style=wx.CB_READONLY)
        scidb.fillComboboxFromSQL(self.cbxStationID, stSQLStations)
        stpSiz.Add(self.cbxStationID,
                   pos=(gRow, 2),
                   span=(1, 3),
                   flag=wx.LEFT,
                   border=5)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Narrow Channel choices to Logger:'),
                   pos=(gRow, 0),
                   span=(1, 2),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)

        stSQLLoggers = 'SELECT ID, LoggerSerialNumber FROM Loggers;'
        self.cbxLoggerID = wx.ComboBox(pnl,
                                       ID_CBX_SEL_LOGGER,
                                       style=wx.CB_READONLY)
        scidb.fillComboboxFromSQL(self.cbxLoggerID, stSQLLoggers)
        stpSiz.Add(self.cbxLoggerID,
                   pos=(gRow, 2),
                   span=(1, 3),
                   flag=wx.LEFT,
                   border=5)

        self.Bind(wx.EVT_COMBOBOX, self.OnSelect)

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl),
                   pos=(gRow, 0),
                   span=(1, iLinespan),
                   flag=wx.EXPAND)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Data Channel:'),
                   pos=(gRow, 0),
                   span=(1, 2),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)

        self.cbxChanID = wx.combo.ComboCtrl(pnl,
                                            ID_CHAN_TEXT,
                                            "",
                                            style=wx.CB_READONLY
                                            | wx.TE_PROCESS_ENTER)
        self.chanPopup = ListCtrlComboPopup()
        #        pnl.chanPopup.id = ID_CHAN_LIST
        # It is important to call SetPopupControl() as soon as possible
        self.cbxChanID.SetPopupControl(self.chanPopup)
        stpSiz.Add(self.cbxChanID,
                   pos=(gRow, 2),
                   span=(1, 7),
                   flag=wx.LEFT,
                   border=5)
        stSQLChan = "SELECT DataChannels.ID, " \
            "( DataChannels.Column || ',' ||  Loggers.LoggerSerialNumber || ',' ||  " \
            "Sensors.SensorSerialNumber || ',' ||  DataTypes.TypeText || ',' ||  " \
            "DataUnits.UnitsText || ',' ||  DataChannels.UTC_Offset) AS Channel, " \
            "DataSeries.DataSeriesDescription AS Series, ChannelSegments.SegmentBegin AS Begin " \
            "FROM (((((DataChannels LEFT JOIN Loggers ON DataChannels.LoggerID = Loggers.ID) " \
            "LEFT JOIN Sensors ON DataChannels.SensorID = Sensors.ID) " \
            "LEFT JOIN DataTypes ON DataChannels.DataTypeID = DataTypes.ID) " \
            "LEFT JOIN DataUnits ON DataChannels.DataUnitsID = DataUnits.ID) " \
            "LEFT JOIN ChannelSegments ON DataChannels.ID = ChannelSegments.ChannelID) " \
            "LEFT JOIN DataSeries ON ChannelSegments.SeriesID = DataSeries.ID;"
        scidb.fillComboCtrlPopupFromSQL(self.chanPopup, stSQLChan,
                                        [300, 180, 140])
        #        pnl.chanPopup.AddItem(("a",None,3,4,5,6,7)) # test AddItem w /every imaginable error

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl),
                   pos=(gRow, 0),
                   span=(1, iLinespan),
                   flag=wx.EXPAND)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1,
                                 'Time interval to view, in Universal Time'),
                   pos=(gRow, 1),
                   span=(1, 5),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'Start'),
                   pos=(gRow, 0),
                   span=(1, 1),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)
        self.tcDTStart = wx.TextCtrl(pnl,
                                     ID_START_TIME,
                                     style=wx.TE_PROCESS_ENTER)
        self.tcDTStart.Bind(wx.EVT_TEXT_ENTER, self.OnEnterKey)
        self.tcDTStart.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        stpSiz.Add(self.tcDTStart,
                   pos=(gRow, 1),
                   span=(1, 3),
                   flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                   border=5)
        #        self.tcDTStart.SetValue('2010-06-13 5pm') # for testing
        self.tcDTStart.SetValue('timestamp, or blank for first in Channel')

        # add StartTime adjustment buttons
        sbHorizSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.StartDayDnButton = wx.Button(pnl,
                                          ID_ST_DAY_DN_BTN,
                                          '<Da',
                                          style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_ST_DAY_DN_BTN)
        sbHorizSizer.Add(self.StartDayDnButton)

        self.StartHourDnButton = wx.Button(pnl,
                                           ID_ST_HOUR_DN_BTN,
                                           '<Hr',
                                           style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_ST_HOUR_DN_BTN)
        sbHorizSizer.Add(self.StartHourDnButton)

        self.StartHourUpButton = wx.Button(pnl,
                                           ID_ST_HOUR_UP_BTN,
                                           'Hr>',
                                           style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_ST_HOUR_UP_BTN)
        sbHorizSizer.Add(self.StartHourUpButton)

        self.StartDayUpButton = wx.Button(pnl,
                                          ID_ST_DAY_UP_BTN,
                                          'Da>',
                                          style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_ST_DAY_UP_BTN)
        sbHorizSizer.Add(self.StartDayUpButton)

        stpSiz.Add(sbHorizSizer, pos=(gRow, 4), span=(1, 1))

        gRow += 1
        stpSiz.Add(wx.StaticText(pnl, -1, 'End'),
                   pos=(gRow, 0),
                   span=(1, 1),
                   flag=wx.TOP | wx.LEFT | wx.BOTTOM,
                   border=5)
        self.tcDTEnd = wx.TextCtrl(pnl, ID_END_TIME, style=wx.TE_PROCESS_ENTER)
        self.tcDTEnd.Bind(wx.EVT_TEXT_ENTER, self.OnEnterKey)
        self.tcDTEnd.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        stpSiz.Add(self.tcDTEnd,
                   pos=(gRow, 1),
                   span=(1, 3),
                   flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                   border=5)

        #        self.tcDTEnd.SetValue('2010-06-14 5pm') # for testing
        self.tcDTEnd.SetValue('timestamp, or blank for last in Channel')

        # add EndTime adjustment buttons
        ebHorizSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.EndDayDnButton = wx.Button(pnl,
                                        ID_EN_DAY_DN_BTN,
                                        '<Da',
                                        style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_EN_DAY_DN_BTN)
        ebHorizSizer.Add(self.EndDayDnButton)

        self.EndHourDnButton = wx.Button(pnl,
                                         ID_EN_HOUR_DN_BTN,
                                         '<Hr',
                                         style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_EN_HOUR_DN_BTN)
        ebHorizSizer.Add(self.EndHourDnButton)

        self.EndHourUpButton = wx.Button(pnl,
                                         ID_EN_HOUR_UP_BTN,
                                         'Hr>',
                                         style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_EN_HOUR_UP_BTN)
        ebHorizSizer.Add(self.EndHourUpButton)

        self.EndDayUpButton = wx.Button(pnl,
                                        ID_EN_DAY_UP_BTN,
                                        'Da>',
                                        style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnTimeAdjustButton, id=ID_EN_DAY_UP_BTN)
        ebHorizSizer.Add(self.EndDayUpButton)

        stpSiz.Add(ebHorizSizer, pos=(gRow, 4), span=(1, 1))

        gRow += 1
        stpSiz.Add(wx.StaticLine(pnl),
                   pos=(gRow, 0),
                   span=(1, iLinespan),
                   flag=wx.EXPAND)

        gRow += 1
        mrbVertSizer = wx.BoxSizer(wx.VERTICAL)

        self.rbMask = wx.RadioButton(pnl,
                                     ID_RB_MASK,
                                     label='Mask',
                                     style=wx.RB_GROUP)
        mrbVertSizer.Add(self.rbMask,
                         proportion=0,
                         flag=wx.ALIGN_LEFT | wx.LEFT)
        self.rbMask.Bind(wx.EVT_RADIOBUTTON, self.giveRBInfo)

        self.rbUnmask = wx.RadioButton(pnl, ID_RB_UNMASK, label='Unmask')
        mrbVertSizer.Add(self.rbUnmask,
                         proportion=0,
                         flag=wx.ALIGN_LEFT | wx.LEFT)
        self.rbUnmask.Bind(wx.EVT_RADIOBUTTON, self.giveRBInfo)

        iRBLeftBorderWd = 30
        stpSiz.Add(mrbVertSizer,
                   pos=(gRow, 0),
                   span=(1, 2),
                   flag=wx.ALIGN_LEFT | wx.LEFT,
                   border=iRBLeftBorderWd)

        self.applyButton = wx.Button(pnl, ID_APPLY_BTN, 'Apply')
        self.Bind(wx.EVT_BUTTON, self.OnApplyBtn, id=ID_APPLY_BTN)
        stpSiz.Add(self.applyButton,
                   pos=(gRow, 3),
                   span=(1, 1),
                   flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                   border=5)

        self.giveRBInfo(
            -1
        )  # have to explictly call this 1st time; -1 is dummy value for event

        pnl.SetSizer(stpSiz)
        pnl.SetAutoLayout(1)
        pnl.SetupScrolling()