Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

TouchPanelPageSelector.cpp

Committer:
jmitc91516
Date:
2017-07-20
Revision:
1:a5258871b33d
Parent:
0:47c880c1463d
Child:
4:6840cf2b153a

File content as of revision 1:a5258871b33d:

#include "TouchPanelPageSelector.h"

#include "EasyGUITouchAreaIndices.h"
#include "ServiceInterval.h"
#include "ColumnDHAutoCalibrationPageHandler.h"
#include "DetectorIgnitionHandler.h"


//#define FORCE_DIRECTLY_HEATED_COLUMN // For testing/debugging - pretend we have a directly heated column
                                     // (regardless of what we actually have)

#define USE_DH_COLUMN_AUTO_CALIBRATION_PAGE // Otherwise (i.e. if commented out) use manual calibration page

/*
    TouchPanelPageSelector class
*/

/*
    static members
*/
bool TouchPanelPageSelector::pageChangeEnabled = true;

    
// The default constructor exists purely to satisfy the compiler - it is not intended to be used
TouchPanelPageSelector::TouchPanelPageSelector()
{
    panelIndex = -1;
    
    pageNumber = -1;
}

TouchPanelPageSelector::TouchPanelPageSelector(int index, int page)
{
    panelIndex = index;
    
    pageNumber = page;
}


/*
    TouchPanelDetectorPageSelector class
*/

// The default constructor exists purely to satisfy the compiler - it is not intended to be used
TouchPanelDetectorPageSelector::TouchPanelDetectorPageSelector() : TouchPanelPageSelector()
{
}

// We do not use the base class' page number in this class - we calculate it 'on the fly' - see below
TouchPanelDetectorPageSelector::TouchPanelDetectorPageSelector(int index) : TouchPanelPageSelector(index, -1)
{
}

/*
    For the detector, the page number varies according to the detector type.
    This function calculates the correct page number, and returns it.
    
    Params: USBDeviceConnected and USBHostGC corresponding to the GC
*/
int TouchPanelDetectorPageSelector::GetPageNumber(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
{
    switch(GetDetectorType(usbDevice, usbHostGC)) {
        case FID_DETECTOR:
            return GuiStruct_DetectorFIDPage_4;
        case TCD_DETECTOR:
            return GuiStruct_DetectorTCDPage_11;
        case ECD_DETECTOR:
            return GuiStruct_DetectorECDPage_12;
        case TXL_DETECTOR:
            return GuiStruct_DetectorTXLPage_27;
        // case 4 is "None" - leave for default
        case NPD_DETECTOR:
            return GuiStruct_DetectorNPDPage_28;
        case PID_DETECTOR:
            return GuiStruct_DetectorPIDPage_29;
        case FPD_DETECTOR:
            return GuiStruct_DetectorFPDPage_14;
        case SPDID_DETECTOR:
            return GuiStruct_DetectorSPDIDPage_30;
        default: // i.e. all other types (including "None")
            break; // Return default (see below)
    }
    
    // Default return code
    return GuiStruct_DetectorNonePage_31;
}

/*
    Gets the detector type from the GC, and returns it as a DetectorType enumeration.
    
    Params: USBDeviceConnected and USBHostGC corresponding to the GC
*/
DetectorType TouchPanelDetectorPageSelector::GetDetectorType(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) 
{
    char response[50];
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, "GDTY", response);

    // We expect a response like this: "DDTY0000" for FID, "DDTY0001" for TCD,
    // "DDTY0002" for ECD, "DDTY0003" for TXL, "DDTY0004" for "None", "DDTY0005" for NPD, 
    // "DDTY0006" for PID, "DDTY0007" for FPD, "DDTY0008" for SPDID. 
    // We assume any other "DDTY00nn" value means "None".
    
    // We convert the final two digits to an integer
    int type;
    sscanf(&response[6], "%d", &type);
    
    // Now we convert the integer value to a DetectorType
    DetectorType detectorType;
    if((type < MIN_DETECTOR_TYPE) || (type > MAX_DETECTOR_TYPE)) {
        detectorType = NO_DETECTOR;
    } else {
        detectorType = (DetectorType) type;
    }
    
    return detectorType;
}


/*
    TouchPanelColumnPageSelector class
*/

// The default constructor exists purely to satisfy the compiler - it is not intended to be used
TouchPanelColumnPageSelector::TouchPanelColumnPageSelector() : TouchPanelPageSelector()
{
}

// We do not use the base class' page number in this class - we calculate it 'on the fly' - see below
TouchPanelColumnPageSelector::TouchPanelColumnPageSelector(int index) : TouchPanelPageSelector(index, -1)
{
}

/*
    For the column, the page number varies according to the column type.
    This function calculates the correct page number, and returns it.
    
    Note that we are assuming that the caller only wants to display column page 1, not page 2, etc -
    this works since page 1 (conventional or DH) is the only column page accessible 
    from the home page - all the others are accessed using the left and right arrows 
    on each of the column pages.
    
    Params: USBDeviceConnected and USBHostGC corresponding to the GC
*/
int TouchPanelColumnPageSelector::GetPageNumber(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
{
    if(GetColumnType(usbDevice, usbHostGC) == DIRECTLY_HEATED_COLUMN) {
        return GuiStruct_ColumnDHPage1_40;
    } 
    
    // 'else'...
    return GuiStruct_ColumnPage1_2;
}

/*
    Gets the column type from the GC, and returns it as a ColumnType enumeration.
    
    Params: USBDeviceConnected and USBHostGC corresponding to the GC
*/
ColumnType TouchPanelColumnPageSelector::GetColumnType(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) 
{
#ifdef FORCE_DIRECTLY_HEATED_COLUMN
    return DIRECTLY_HEATED_COLUMN;
#else
    char response[50];
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, "GCTY", response);

    // We expect a response like this: "DCTY0000" for None, "DCTY0001" for Conventional,
    // "DCTY0002" for Directly Heated
    
    // Convert the final two digits to an integer
    int type;
    sscanf(&response[6], "%d", &type);
    
    // Now we convert the integer value to a ColumnType
    ColumnType columnType;
    if((type < MIN_COLUMN_TYPE) || (type > MAX_COLUMN_TYPE)) {
        columnType = NO_COLUMN;
    } else {
        columnType = (ColumnType) type;
    }
    
    return columnType;
#endif
}


/*
    TouchPanelAbortRunPageSelector class
*/

// The default constructor exists purely to satisfy the compiler - it is not intended to be used
TouchPanelAbortRunPageSelector::TouchPanelAbortRunPageSelector() : TouchPanelPageSelector()
{
}

// We do not use the base class' page number in this class - we calculate it 'on the fly' - see below
TouchPanelAbortRunPageSelector::TouchPanelAbortRunPageSelector(int index) : TouchPanelPageSelector(index, -1)
{
}

/*
    When the user aborts the run, we will normally display the Home page. But if any components 
    now require servicing (since even an aborted run counts as one 'cycle', and some components 
    require servicing after a particular number of cycles), we want to display 
    the 'Servicing Required' page instead. This function decides which page to display, 
    and returns its number.
    
    Params: USBDeviceConnected and USBHostGC corresponding to the GC
            (these are not used in this class)
*/
int TouchPanelAbortRunPageSelector::GetPageNumber(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
{
    if(ServiceInterval::AtLeastOneServiceIntervalHasExpired()) {
        return GuiStruct_ServicingRequired_Def;
    }
    
    // 'else'...
    return GuiStruct_HomePage_1;
}



    


/*
    TouchPanelReturnPageSelector class
*/

// The default constructor exists purely to satisfy the compiler - it is not intended to be used
TouchPanelReturnPageSelector::TouchPanelReturnPageSelector() : TouchPanelPageSelector()
{
    thisIsTheReturnInstance = false;
}

/*
    In this constructor, 'index' is the number of the easyGUI touch area to which this instance corresponds, 'pageToDisplayNow' is the easyGUI page("structure") number to which this instance corresponds, 
    and 'thisWillBeTheReturnInstance' is a boolean that, if false, says that this instance's 'GetPageNumber' function records 'pageToReturnTo' as the page to be returned to, 
    then tells the caller 'go to pageToDisplayNow' - or, if true, says that this instance's 'GetPageNumber' function returns the number of the page to be returned to.
*/
TouchPanelReturnPageSelector::TouchPanelReturnPageSelector(int index, int pageToReturnTo, int pageToDisplayNow, bool thisWillBeTheReturnInstance) : TouchPanelPageSelector(index, pageToDisplayNow)
{
    thisReturnPage = pageToReturnTo;
    
    thisIsTheReturnInstance = thisWillBeTheReturnInstance;
}

int TouchPanelReturnPageSelector::GetPageNumber(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
{
    if(thisIsTheReturnInstance) {
        if(theReturnPage == -1) {
            // Return page not yet set - as a default, return the page number we were given when we were constructed
            return thisReturnPage;
        }
        // 'else' we have a return page number
        return theReturnPage;
    }
    
    // 'else' this is a 'calling' instance - record our return page 
    // as the one to return to, then return (to the caller) the page to display now
    
    theReturnPage = thisReturnPage;
        
    return GetBasePageNumber();
}

// Static variable - all instances of TouchPanelReturnPageSelector share the same return page.
// (Note that this is only one variable, not a stack - if we want 'overlapping' return pages
//  at some point, this will have to be changed.)
int TouchPanelReturnPageSelector::theReturnPage = -1;


/*
    TouchPanelPageSelectors class
*/

// TouchPanelPageSelectors constructor - set up the array of page selectors
TouchPanelPageSelectors::TouchPanelPageSelectors()
{
    // Note that the touch area indexes, etc, below
    // are hardcoded to match those set up in easyGUI. 
    // There seems to be no way to get these values from easyGUI at runtime.
    // See EasyGUITouchAreaIndices.h for the actual numerical values.
    
    // Note also that we have two touch areas each for the Column, Injector,
    // Detector and Gas (which overlap in each case - see the easyGUI project). 
    // This is so that we can (nearly) fill the relevant rectangle on the Home Page 
    // with touch areas, without overlapping the Run button at the centre.
    
    // The TouchCallback function (main.cpp) is the main user of this. As well as getting, from this class, 
    // the page to be displayed in response to the user touching a particular touch area, it also performs 
    // any other actions (e.g. telling the GC to abort the run, etc) that may be required before we can display the new page. 
    
    // Another note - there are multiple Abort Run pages, which are all identical apart from the touch index of the No button (this is of course invisible to the user). 
    // Each one is invoked from the Abort Run button on a different 'Running xxx' page, where 'xxx' is one of the components (Column, Injector, etc).
    // This is so that we know which page to return to if the user presses 'No' - the index of the 'No' button tells us which Abort Run page the user is on,
    // therefore which page he pressed the 'Abort Run' button on - and that is the page we need to return to. Otherwise (i.e. if we had a single Abort Run page),
    // the code here would be much more complicated.
    
    // And another... The Column and Detector pages are different for the different column/detector types. This is why, for these pages, we use 
    // the TouchPanelColumnPageSelector and TouchPanelDetectorPageSelector classes, derived from TouchPanelPageSelector, 
    // which find out the column/detector type at runtime, and return the corresponding page numbers.
    
    tppsArray[0]  = new TouchPanelPageSelector(HOME_BUTTON,   GuiStruct_HomePage_1);
    tppsArray[1]  = new TouchPanelPageSelector(SETTINGS_BUTTON,   GuiStruct_SettingsPage_5);
//    tppsArray[2]  = new TouchPanelPageSelector(3,   GuiStruct_ColumnPage1_2);  
    tppsArray[2]  = new TouchPanelColumnPageSelector(COLUMN_TOUCH_AREA_1);
    tppsArray[3]  = new TouchPanelPageSelector(INJECTOR_TOUCH_AREA_1,   GuiStruct_InjectorPage1_3);
//    tppsArray[4]  = new TouchPanelPageSelector(5,   GuiStruct_DefaultDetectorPage1_4);
    tppsArray[4]  = new TouchPanelDetectorPageSelector(DETECTOR_TOUCH_AREA_1); 
    tppsArray[5]  = new TouchPanelPageSelector(GAS_TOUCH_AREA_1,   GuiStruct_GasInformationPage_6);
//    tppsArray[6]  = new TouchPanelPageSelector(7,   GuiStruct_ColumnPage1_2);
    tppsArray[6]  = new TouchPanelColumnPageSelector(COLUMN_TOUCH_AREA_2);      // Second (overlapping) 'Column' touch area on Home page
    tppsArray[7]  = new TouchPanelPageSelector(INJECTOR_TOUCH_AREA_2,   GuiStruct_InjectorPage1_3); // Second (overlapping) 'Injector' touch area on Home page
//    tppsArray[8]  = new TouchPanelPageSelector(9,   GuiStruct_DefaultDetectorPage1_4);
    tppsArray[8]  = new TouchPanelDetectorPageSelector(DETECTOR_TOUCH_AREA_2);                     // Second (overlapping) 'Detector' touch area on Home page
    tppsArray[9]  = new TouchPanelPageSelector(GAS_TOUCH_AREA_2,  GuiStruct_GasInformationPage_6);     // Second (overlapping) 'Gas' touch area on Home page
   
    tppsArray[10] = new TouchPanelReturnPageSelector(RUNNING_PAGE1_ABORT_RUN, GuiStruct_RunningPage1_7, GuiStruct_AbortRunPage_19, false);
    tppsArray[11] = new TouchPanelReturnPageSelector(RUNNING_COLUMN_ABORT_RUN, GuiStruct_RunningColumnPage_25, GuiStruct_AbortRunPage_19, false);
    tppsArray[12] = new TouchPanelReturnPageSelector(RUNNING_INJECTOR_ABORT_RUN, GuiStruct_RunningInjectorPage_26, GuiStruct_AbortRunPage_19, false);
    tppsArray[13] = new TouchPanelReturnPageSelector(RUNNING_DETECTOR_ABORT_RUN, GuiStruct_RunningDetectorPage_27, GuiStruct_AbortRunPage_19, false);
    tppsArray[14] = new TouchPanelReturnPageSelector(RUNNING_GAS_ABORT_RUN, GuiStruct_RunningGasPage_28, GuiStruct_AbortRunPage_19, false);
    tppsArray[15] = new TouchPanelReturnPageSelector(RUNNING_INJECTOR_PROFILE_ABORT_RUN, GuiStruct_RunningInjectorProfilePage_Def, GuiStruct_AbortRunPage_19, false);
    tppsArray[16] = new TouchPanelAbortRunPageSelector(ABORT_RUN_YES);
    tppsArray[17] = new TouchPanelReturnPageSelector(ABORT_RUN_NO, GuiStruct_AbortRunPage_19, GuiStruct_RunningPage1_7, true);

    tppsArray[18] = new TouchPanelPageSelector(GAS_INFO_LEFT_ARROW, GuiStruct_GasProfilePage_15);
    tppsArray[19] = new TouchPanelPageSelector(GAS_INFO_RIGHT_ARROW, GuiStruct_GasProfilePage_15);
    tppsArray[20] = new TouchPanelPageSelector(GAS_PROFILE_LEFT_ARROW, GuiStruct_GasInformationPage_6);
    tppsArray[21] = new TouchPanelPageSelector(GAS_PROFILE_RIGHT_ARROW, GuiStruct_GasInformationPage_6);

    tppsArray[22] = new TouchPanelPageSelector(GAS_SAVER_RETURN_TO_READY, GuiStruct_HomePage_1);      // 'Return to ready state' touch area on Gas Saver page (covers entire page)

    // Pages for conventional (not directly heated) column
    tppsArray[23] = new TouchPanelPageSelector(COLUMN_PAGE1_LEFT_ARROW, GuiStruct_ColumnTempProfilePage_60);
    tppsArray[24] = new TouchPanelPageSelector(COLUMN_PAGE1_RIGHT_ARROW, GuiStruct_ColumnPage2_9);          
    tppsArray[25] = new TouchPanelPageSelector(COLUMN_PAGE2_LEFT_ARROW, GuiStruct_ColumnPage1_2);   
    tppsArray[26] = new TouchPanelPageSelector(COLUMN_PAGE2_RIGHT_ARROW, GuiStruct_ColumnTempProfilePage_60);
    tppsArray[27] = new TouchPanelPageSelector(COLUMN_PROFILE_LEFT_ARROW, GuiStruct_ColumnPage2_9);
    tppsArray[28] = new TouchPanelPageSelector(COLUMN_PROFILE_RIGHT_ARROW, GuiStruct_ColumnPage1_2);
    
    // Pages for directly heated column
    tppsArray[29] = new TouchPanelPageSelector(COLUMN_DH_PAGE1_LEFT_ARROW, GuiStruct_ColumnDHTempProfilePage_61);
    tppsArray[30] = new TouchPanelPageSelector(COLUMN_DH_PAGE1_RIGHT_ARROW, GuiStruct_ColumnDHPage2_50);
    tppsArray[31] = new TouchPanelPageSelector(COLUMN_DH_PAGE2_LEFT_ARROW, GuiStruct_ColumnDHPage1_40); 
    tppsArray[32] = new TouchPanelPageSelector(COLUMN_DH_PAGE2_RIGHT_ARROW, GuiStruct_ColumnDHTempProfilePage_61);
    tppsArray[33] = new TouchPanelPageSelector(COLUMN_DH_PROFILE_LEFT_ARROW, GuiStruct_ColumnDHPage2_50);         
    tppsArray[34] = new TouchPanelPageSelector(COLUMN_DH_PROFILE_RIGHT_ARROW, GuiStruct_ColumnDHPage1_40);        

    tppsArray[35] = new TouchPanelPageSelector(CLEAR_ERRORS_BUTTON, GuiStruct_HomePage_1);      // 'Clear Errors' button on 'GC in fault state' page

    tppsArray[36] = new TouchPanelPageSelector(INJECTOR_PAGE1_LEFT_ARROW, GuiStruct_InjectorConsumablesPage_20);
    tppsArray[37] = new TouchPanelPageSelector(INJECTOR_PAGE1_RIGHT_ARROW, GuiStruct_InjectorTempProfilePage_25);
    tppsArray[38] = new TouchPanelPageSelector(INJECTOR_PROFILE_LEFT_ARROW, GuiStruct_InjectorPage1_3);          
    tppsArray[39] = new TouchPanelPageSelector(INJECTOR_PROFILE_RIGHT_ARROW, GuiStruct_InjectorGasStatusPage_30);
    tppsArray[40] = new TouchPanelPageSelector(INJECTOR_GAS_STATUS_LEFT_ARROW, GuiStruct_InjectorTempProfilePage_25);
    tppsArray[41] = new TouchPanelPageSelector(INJECTOR_GAS_STATUS_RIGHT_ARROW, GuiStruct_InjectorConsumablesPage_20);
    tppsArray[42] = new TouchPanelPageSelector(INJECTOR_CONSUMABLES_LEFT_ARROW, GuiStruct_InjectorGasStatusPage_30);
    tppsArray[43] = new TouchPanelPageSelector(INJECTOR_CONSUMABLES_RIGHT_ARROW, GuiStruct_InjectorPage1_3);          

    tppsArray[44] = new TouchPanelPageSelector(RUNNING_PAGE1_RIGHT_ARROW, GuiStruct_RunningColumnPage_25);
    tppsArray[45] = new TouchPanelPageSelector(RUNNING_PAGE1_LEFT_ARROW, GuiStruct_RunningGasPage_28);    
    tppsArray[46] = new TouchPanelPageSelector(RUNNING_COLUMN_RIGHT_ARROW, GuiStruct_RunningInjectorPage_26);
    tppsArray[47] = new TouchPanelPageSelector(RUNNING_COLUMN_LEFT_ARROW, GuiStruct_RunningPage1_7);         
    tppsArray[48] = new TouchPanelPageSelector(RUNNING_INJECTOR_RIGHT_ARROW, GuiStruct_RunningInjectorProfilePage_Def);
    tppsArray[49] = new TouchPanelPageSelector(RUNNING_INJECTOR_LEFT_ARROW, GuiStruct_RunningColumnPage_25);   
    tppsArray[50] = new TouchPanelPageSelector(RUNNING_INJECTOR_PROFILE_RIGHT_ARROW, GuiStruct_RunningDetectorPage_27);
    tppsArray[51] = new TouchPanelPageSelector(RUNNING_INJECTOR_PROFILE_LEFT_ARROW, GuiStruct_RunningInjectorPage_26);   
    tppsArray[52] = new TouchPanelPageSelector(RUNNING_DETECTOR_RIGHT_ARROW, GuiStruct_RunningGasPage_28);     
    tppsArray[53] = new TouchPanelPageSelector(RUNNING_DETECTOR_LEFT_ARROW, GuiStruct_RunningInjectorProfilePage_Def); 
    tppsArray[54] = new TouchPanelPageSelector(RUNNING_GAS_RIGHT_ARROW, GuiStruct_RunningPage1_7);         
    tppsArray[55] = new TouchPanelPageSelector(RUNNING_GAS_LEFT_ARROW, GuiStruct_RunningDetectorPage_27); 

    tppsArray[56] = new TouchPanelPageSelector(SETTINGS_TO_NETWORK_PARAMS_BUTTON, GuiStruct_EthernetParametersPage_50); 
    tppsArray[57] = new TouchPanelPageSelector(NETWORK_PARAMS_RETURN_BUTTON, GuiStruct_SettingsPage_5); 

    tppsArray[58] = new TouchPanelPageSelector(SETTINGS_TO_SERVICING_PAGE_BUTTON, GuiStruct_EngineersLockPage_Def); 
    tppsArray[59] = new TouchPanelPageSelector(SERVICING_PAGE_RETURN_BUTTON, GuiStruct_SettingsPage_5); 

    tppsArray[60] = new TouchPanelPageSelector(SERVICING_REQUIRED_PAGE_HOME_BUTTON, GuiStruct_HomePage_1);
    
    tppsArray[61] = new TouchPanelPageSelector(COLUMN_SERVICING_AREA, GuiStruct_ColumnDHAutoCalibrationPage_Def);
    tppsArray[62] = new TouchPanelPageSelector(DETECTOR_SERVICING_AREA, GuiStruct_DetectorNudgeAndDampPage_0);
    tppsArray[63] = new TouchPanelPageSelector(INJECTOR_SERVICING_AREA, GuiStruct_InjectorNudgeAndDampPage_0);
    tppsArray[64] = new TouchPanelPageSelector(GAS_SERVICING_AREA, GuiStruct_GasCalibrationPage_Def);
    tppsArray[65] = new TouchPanelPageSelector(SERVICING_HOME, GuiStruct_ServicingHomePage_Def);

    tppsArray[66] = new TouchPanelPageSelector(COLUMN_DH_AUTO_CALIB_LEFT_ARROW, GuiStruct_FanPowerPage_0);
    tppsArray[67] = new TouchPanelPageSelector(COLUMN_DH_AUTO_CALIB_RIGHT_ARROW, GuiStruct_ColumnDHManualCalibrationPage_Def);
    tppsArray[68] = new TouchPanelPageSelector(COLUMN_DH_MANUAL_CALIB_LEFT_ARROW, GuiStruct_ColumnDHAutoCalibrationPage_Def);
    tppsArray[69] = new TouchPanelPageSelector(COLUMN_DH_MANUAL_CALIB_RIGHT_ARROW, GuiStruct_ColumnDHSensorCalibration_Def);
    tppsArray[70] = new TouchPanelPageSelector(COLUMN_DH_SENSOR_CALIB_LEFT_ARROW, GuiStruct_ColumnDHManualCalibrationPage_Def);
    tppsArray[71] = new TouchPanelPageSelector(COLUMN_DH_SENSOR_CALIB_RIGHT_ARROW, GuiStruct_PSU_DAC_Page_Def);
    tppsArray[72] = new TouchPanelPageSelector(COLUMN_DH_PSU_DAC_LEFT_ARROW, GuiStruct_ColumnDHSensorCalibration_Def);
    tppsArray[73] = new TouchPanelPageSelector(COLUMN_DH_PSU_DAC_RIGHT_ARROW, GuiStruct_ColumnDHOvenFanPage_Def);
    tppsArray[74] = new TouchPanelPageSelector(COLUMN_OVEN_FAN_LEFT_ARROW, GuiStruct_PSU_DAC_Page_Def);
    tppsArray[75] = new TouchPanelPageSelector(COLUMN_OVEN_FAN_RIGHT_ARROW, GuiStruct_ColumnOvenNudgeAndDampPage_0);
    tppsArray[76] = new TouchPanelPageSelector(COLUMN_OVEN_NUDGE_AND_DAMP_LEFT_ARROW, GuiStruct_ColumnDHOvenFanPage_Def);
    tppsArray[77] = new TouchPanelPageSelector(COLUMN_OVEN_NUDGE_AND_DAMP_RIGHT_ARROW, GuiStruct_ColumnDHNudgeAndDampPage_0);
    tppsArray[78] = new TouchPanelPageSelector(COLUMN_DH_NUDGE_AND_DAMP_LEFT_ARROW, GuiStruct_ColumnOvenNudgeAndDampPage_0);
    tppsArray[79] = new TouchPanelPageSelector(COLUMN_DH_NUDGE_AND_DAMP_RIGHT_ARROW, GuiStruct_FanPowerPage_0);
    tppsArray[80] = new TouchPanelPageSelector(FAN_POWER_LEFT_ARROW, GuiStruct_ColumnDHNudgeAndDampPage_0);
    tppsArray[81] = new TouchPanelPageSelector(FAN_POWER_RIGHT_ARROW, GuiStruct_ColumnDHAutoCalibrationPage_Def);

    tppsArray[82] = new TouchPanelPageSelector(DETECTOR_NUDGE_AND_DAMP_LEFT_ARROW, GuiStruct_AuxiliaryNudgeAndDampPage_0);
    tppsArray[83] = new TouchPanelPageSelector(DETECTOR_NUDGE_AND_DAMP_RIGHT_ARROW, GuiStruct_AuxiliaryNudgeAndDampPage_0);
    tppsArray[84] = new TouchPanelPageSelector(AUXILIARY_NUDGE_AND_DAMP_LEFT_ARROW, GuiStruct_DetectorNudgeAndDampPage_0);
    tppsArray[85] = new TouchPanelPageSelector(AUXILIARY_NUDGE_AND_DAMP_RIGHT_ARROW, GuiStruct_DetectorNudgeAndDampPage_0);

    tppsArray[86] = new TouchPanelPageSelector(GAS_CALIB_LEFT_ARROW, GuiStruct_GasChannelDACAndADCPage_Def);
    tppsArray[87] = new TouchPanelPageSelector(GAS_CALIB_RIGHT_ARROW, GuiStruct_GasBackPressureDACPage_Def);
    tppsArray[88] = new TouchPanelPageSelector(GAS_BACKPRESSURE_DAC_LEFT_ARROW, GuiStruct_GasCalibrationPage_Def);
    tppsArray[89] = new TouchPanelPageSelector(GAS_BACKPRESSURE_DAC_RIGHT_ARROW, GuiStruct_GasChannelDACAndADCPage_Def);
    tppsArray[90] = new TouchPanelPageSelector(GAS_CHANNEL_DAC_AND_ADC_LEFT_ARROW, GuiStruct_GasBackPressureDACPage_Def);
    tppsArray[91] = new TouchPanelPageSelector(GAS_CHANNEL_DAC_AND_ADC_RIGHT_ARROW, GuiStruct_GasCalibrationPage_Def);

    tppsArray[92] = new TouchPanelPageSelector(SERVICING_PAGE_GC_CMDS_BUTTON, GuiStruct_DebugCommandsPage_Def);
}
   
TouchPanelPageSelectors::~TouchPanelPageSelectors() 
{
    for (int i = 0; i < SELECTOR_COUNT; ++i) {
        if(tppsArray[i] != NULL) { // We may occasionally set some to NULL while testing new changes
            delete tppsArray[i];
        }
    }
}

/*
    Given a touch area index, returns a pointer to the corresponding page selector,
    or NULL if that index has no page selector. If the pointer is not NULL, caller 
    can then call 'GetPageNumber' on that page selector, to find out which page to display 
    in response to the user touching that touch area. (If the pointer is NULL, that touch area
    does not select a new page.)
*/
TouchPanelPageSelector* TouchPanelPageSelectors::GetTouchPanelPageSelector(int touchAreaIndex)
{
    for (int i = 0; i < SELECTOR_COUNT; ++i) {
        if(tppsArray[i] != NULL) { // We may occasionally set some to NULL while testing new changes
            if( tppsArray[i]->GetIndex() == touchAreaIndex) {
                return tppsArray[i];
            }
        }
    }
    
    // 'else' - not found
    return NULL;        
}

    
/*
    Tells the caller which TouchPanelPageSelector they have - i.e. returns its index
    in our array, or -1 if we cannot find it. (This should be useful for debugging.)
    
    Arguments: pointer to the TouchPanelPageSelector instance in question
    
    Return code: its index in our array, or -1 if not found
*/
int TouchPanelPageSelectors::GetTouchPanelPageSelectorIndex(TouchPanelPageSelector *tppsptr)
{
    for (int i = 0; i < SELECTOR_COUNT; ++i) {
        if(tppsArray[i] == tppsptr) {
            return i;
        }
    }
    
    // 'else' - not found
    return -1;    
}