ftclib/menu.h
author Trc492/3543
Mon Nov 21 01:42:54 2011 -0800 (2011-11-21)
changeset 66 dfec5f741135
parent 51 155d0a30089e
child 95 b9632bfbe87c
permissions -rw-r--r--
Added the missing turn in ParkBack2
     1 #if 0
     2 /// Copyright (c) Titan Robotics Club. All rights reserved.
     3 ///
     4 /// <module name="menu.h" />
     5 ///
     6 /// <summary>
     7 ///     This module contains the library functions for displaying a choice
     8 ///     menu on the NXT LCD screen and allowing the user to scroll through
     9 ///     the menu and pick a choice.
    10 /// </summary>
    11 ///
    12 /// <remarks>
    13 ///     Environment: RobotC for Lego Mindstorms NXT.
    14 /// </remarks>
    15 #endif
    16 
    17 #ifndef _MENU_H
    18 #define _MENU_H
    19 
    20 #pragma systemFile
    21 
    22 #ifdef MOD_ID
    23     #undef MOD_ID
    24 #endif
    25 #define MOD_ID                  MOD_MENU
    26 
    27 //
    28 // Constants
    29 //
    30 #ifndef MAX_NUM_CHOICES
    31     #define MAX_NUM_CHOICES     16
    32 #endif
    33 #define NUM_DISPLAY_LINES       8
    34 #define NUM_PIXELS_PER_LINE     8
    35 #define NUM_LINE_PIXELS         100
    36 
    37 #define MENUF_ENABLED           0x0001
    38 
    39 #define LinePos(n)              (NUM_DISPLAY_LINES*NUM_PIXELS_PER_LINE - 1 - \
    40                                  (n)*NUM_PIXELS_PER_LINE)
    41 #define MenuIsEnabled(m)        ((m.menuFlags & MENUF_ENABLED) != 0)
    42 #define MenuGetUserChoice(m)    (m.userChoice)
    43 
    44 //
    45 // Type definitions.
    46 //
    47 typedef struct
    48 {
    49     string   titleText;
    50     int      menuFlags;
    51     int      numChoices;
    52     string   choices[MAX_NUM_CHOICES];
    53     int      currChoice;
    54     int      firstChoice;
    55     int      userChoice;
    56 } MENU;
    57 
    58 /**
    59  *  This function initializes the choice menu.
    60  *
    61  *  @param menu Points to the MENU structure to be initialized.
    62  *  @param titleText Specifies the title text of the menu.
    63  */
    64 void
    65 MenuInit(
    66     __out MENU &menu,
    67     __in  string titleText
    68     )
    69 {
    70     TFuncName("MenuInit");
    71     TLevel(INIT);
    72     TEnter();
    73 
    74     strcpy(menu.titleText, titleText);
    75     menu.menuFlags = 0;
    76     menu.numChoices = 0;
    77     menu.currChoice = 0;
    78     menu.firstChoice = 0;
    79     menu.userChoice = -1;
    80 
    81     TExit();
    82     return;
    83 }   //MenuInit
    84 
    85 /**
    86  *  This function adds a choice to the menu.
    87  *
    88  *  @param menu Points to the MENU structure to be initialized.
    89  *  @param choiceText Specifies the choice text.
    90  *
    91  *  @return Returns true if the choice is added successful, otherwise the
    92  *          menu is full.
    93  */
    94 bool
    95 MenuAddChoice(
    96     __inout MENU &menu,
    97     __in    string choiceText
    98     )
    99 {
   100     bool fSuccess = false;
   101 
   102     TFuncName("MenuAddChoice");
   103     TLevel(API);
   104     TEnter();
   105 
   106     if (menu.numChoices < MAX_NUM_CHOICES)
   107     {
   108         strcpy(menu.choices[menu.numChoices], choiceText);
   109         menu.numChoices++;
   110         fSuccess = true;
   111     }
   112 
   113     TExit();
   114     return fSuccess;
   115 }   //MenuAddChoice
   116 
   117 /**
   118  *  This function waits for the start signal from the FCS or the enter button
   119  *  is pressed.
   120  */
   121 void
   122 MenuWaitStart()
   123 {
   124     TFuncName("MenuWaitStart");
   125     TLevel(API);
   126     TEnter();
   127 
   128 #if (_TARGET == "Robot")
   129     TButtons prevNxtBtn = nNxtButtonPressed;
   130     TButtons currNxtBtn;
   131 
   132     while (true)
   133     {
   134         getJoystickSettings(joystick);
   135         currNxtBtn = nNxtButtonPressed;
   136         if (!joystick.StopPgm ||
   137             (currNxtBtn != prevNxtBtn) && (currNxtBtn == kEnterButton))
   138         {
   139             break;
   140         }
   141         prevNxtBtn = currNxtBtn;
   142     }
   143 #endif
   144 
   145     TExit();
   146     return;
   147 }   //MenuWaitStart
   148 
   149 /**
   150  *  This function invert the menu line.
   151  *
   152  *  @param lineNum
   153  */
   154 void
   155 MenuInvertLine(
   156     __in int lineNum
   157     )
   158 {
   159     TFuncName("MenuInvertLine");
   160     TLevel(FUNC);
   161     TEnter();
   162 
   163     for (int y = LinePos(lineNum + 1) + 1; y <= LinePos(lineNum); y++)
   164     {
   165         nxtInvertLine(0, y, NUM_LINE_PIXELS -1, y);
   166     }
   167 
   168     TExit();
   169     return;
   170 }   //MenuInvertLine
   171 
   172 /**
   173  *  This function is called to refresh the menu display.
   174  *
   175  *  @param menu Points to the MENU structure.
   176  */
   177 void
   178 MenuDisplay(
   179     __inout MENU &menu
   180     )
   181 {
   182     TFuncName("MenuDisplay");
   183     TLevel(API);
   184     TEnter();
   185 
   186     eraseDisplay();
   187     nxtDisplayTextLine(0, menu.titleText);
   188     for (int choice = menu.firstChoice;
   189          choice < menu.firstChoice + NUM_DISPLAY_LINES - 1;
   190          choice++)
   191     {
   192         nxtDisplayTextLine(choice - menu.firstChoice + 1,
   193                            "%d:%s", choice, menu.choices[choice]);
   194     }
   195     MenuInvertLine(menu.currChoice - menu.firstChoice + 1);
   196 
   197     TExit();
   198     return;
   199 }   //MenuDisplay
   200 
   201 /**
   202  *  This function is called to enable or disable the menu.
   203  *
   204  *  @param menu Points to the MENU structure.
   205  *  @param fEnable If true, display and enable the menu, otherwise erase and
   206  *         disable the menu.
   207  */
   208 void
   209 MenuSetState(
   210     __inout MENU &menu,
   211     __in    bool fEnable
   212     )
   213 {
   214     TFuncName("MenuSetState");
   215     TLevel(API);
   216     TEnterMsg(("fEnable=%d", fEnable));
   217 
   218     if (fEnable)
   219     {
   220         menu.userChoice = -1;
   221         MenuDisplay(menu);
   222         menu.menuFlags |= MENUF_ENABLED;
   223     }
   224     else
   225     {
   226         menu.userChoice = menu.currChoice;
   227         menu.menuFlags &= ~MENUF_ENABLED;
   228         eraseDisplay();
   229     }
   230 
   231     TExit();
   232     return;
   233 }   //MenuSetState
   234 
   235 /**
   236  *  This function set the current choice to next or previous.
   237  *
   238  *  @param menu Points to the MENU structure.
   239  *  @param inc Specifies the increment.
   240  */
   241 void
   242 MenuIncChoice(
   243     __inout MENU &menu,
   244     __in    int inc
   245     )
   246 {
   247     TFuncName("MenuIncChoice");
   248     TLevel(API);
   249     TEnter();
   250 
   251     menu.currChoice += inc;
   252     if (menu.currChoice < 0)
   253     {
   254         menu.currChoice += menu.numChoices;
   255     }
   256     else if (menu.currChoice >= menu.numChoices)
   257     {
   258         menu.currChoice -= menu.numChoices;
   259     }
   260 
   261     int lineNum = menu.currChoice - menu.firstChoice + 1;
   262     if (lineNum >= NUM_DISPLAY_LINES)
   263     {
   264         menu.firstChoice = menu.currChoice - (NUM_DISPLAY_LINES - 2);
   265     }
   266     else if (lineNum < 1)
   267     {
   268         menu.firstChoice = menu.currChoice;
   269     }
   270     MenuDisplay(menu);
   271 
   272     TExit();
   273     return;
   274 }   //MenuIncChoice
   275 
   276 /**
   277  *  This function displays the menu and returns the user choice.
   278  *  Note that this is a blocking function. It should only be called outside
   279  *  of the robot loop (e.g. in RobotInit).
   280  *
   281  *  @param menu Points to the MENU structure to be initialized.
   282  *
   283  *  @return Returns the user choice.
   284  */
   285 int
   286 MenuGetChoice(
   287     __inout MENU &menu
   288     )
   289 {
   290     TButtons prevNxtBtn = nNxtButtonPressed;
   291     TButtons currNxtBtn;
   292 
   293     TFuncName("MenuGetChoice");
   294     TLevel(API);
   295     TEnter();
   296 
   297     MenuSetState(menu, true);
   298     while (true)
   299     {
   300         currNxtBtn = nNxtButtonPressed;
   301         if (currNxtBtn != prevNxtBtn)
   302         {
   303             if (currNxtBtn == kLeftButton)
   304             {
   305                 MenuIncChoice(menu, -1);
   306             }
   307             else if (currNxtBtn == kRightButton)
   308             {
   309                 MenuIncChoice(menu, 1);
   310             }
   311             else if (currNxtBtn == kEnterButton)
   312             {
   313                 break;
   314             }
   315             prevNxtBtn = currNxtBtn;
   316             wait1Msec(NXTBTN_DEBOUNCE_TIME);
   317         }
   318     }
   319     MenuSetState(menu, false);
   320 
   321     TExit();
   322     return menu.userChoice;
   323 }   //MenuGetChoice
   324 
   325 #endif  //ifndef _MENU_H