HP Forums
Code snippet: drawmenu with catching user action - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP Prime Software Library (/forum-15.html)
+--- Thread: Code snippet: drawmenu with catching user action (/thread-760.html)



Code snippet: drawmenu with catching user action - Stefan - 02-24-2014 06:26 PM

Here is a code snippet which someone might find useful. I adapted an earlier example of veeblefester, and made it a little bit shorter.
It can be used as a drop-in replacement for the drawmenu() function: The function takes as argument a list with the labels for the 6 softbuttons. It returns the ID of the button which was pressed.

Edit: Thanks to Han a better version is available in my post below. I removed the old code.


RE: Code snippet: drawmenu with catching user action - Han - 03-01-2014 05:04 AM

There is a brief example of how to capture ALL input types in the intro to programming article. You can easily adapt it to your case. Basically, it uses the WAIT(-1) command instead (which is better than doing a while loop).


RE: Code snippet: drawmenu with catching user action - Stefan - 03-03-2014 10:08 PM

Thank you Han! That works much better and is even simpler now. Here is my reworked code:

Code:

EXPORT DrawMenuSelect(buttonlabellist)
// Parameters: menustringlist is a list which should contain at most 6 strings for the button labels
// Returns: The ID (1 to 6) of the button that was pressed
BEGIN
 LOCAL selection, mouselist;
 DRAWMENU(buttonlabellist);
 mouselist:=WAIT(-1); // Wait until screen is touched
 selection := -1; //preinitialize with -1 which is returned if none of the buttons is pressed
 // Check whether one of the on-screen buttons was pressed:
 IF (mouselist(1)==3 AND mouselist(3) >= #DD:-16h) THEN
  selection:=CEILING((mouselist(2)+1)*6/320); // Screen is 320px wide. There are six buttons. hence divide
// mouse value by 320/6. To avoid getting a value of zero when the user presses exactly at the left 
//border a 1 is added to the mouse value
 END;

 RETURN selection;
END;



RE: Code snippet: drawmenu with catching user action - Tim Wessman - 03-03-2014 10:37 PM

What happens if the user presses a key instead of touching the screen?


RE: Code snippet: drawmenu with catching user action - Han - 03-04-2014 03:43 AM

(03-03-2014 10:37 PM)Tim Wessman Wrote:  What happens if the user presses a key instead of touching the screen?

As Tim pointed out, you do have to address this instance -- this is why I had to check the TYPE of the result from WAIT(-1). You must use TYPE(), and it must be done separately from the mouse event type check (i.e. don't use AND). Otherwise a keyboard event will generate an error.


RE: Code snippet: drawmenu with catching user action - patrice - 03-04-2014 04:52 AM

(03-03-2014 10:08 PM)Stefan Wrote:  
Code:
 // Check whether one of the on-screen buttons was pressed:
 IF (mouselist(1)==3 AND mouselist(3) >= #DD:-16h) THEN
You even have to split this test in 2.
Because you can be unlucky and get a "mouse up" event with no coordinate.


RE: Code snippet: drawmenu with catching user action - Stefan - 03-04-2014 03:36 PM

Thanks everyone for finding the mentioned error sources! Here is the reworked version.

Important note for everyone who has used the code before: I changed the return value for the case where no on-screen button was pressed to "0" instead of "-1", because of the following change:
Now the code also checks whether the button which was pressed is in the list of labels. If this is not the case the negative of the button ID is returned.

Example: DrawMenuSelect({"one", "two"})
If user presses button 4, returns "-4"
If user presses button 2, returns "2"
If user presses none of the on-screen buttons (e.g. by pressing the screen elsewhere, or typing the keyboard) returns "0"

Code:

EXPORT DrawMenuSelect(buttonlabellist)
// Parameters: buttonlabellist is a list which should contain at most 6 strings for the button labels
// Returns: 
//  * If one of the buttons in "buttonlabellist" was pressed returns the ID (1 to 6) of the button.
//  * If a button is pressed which is not labeled by "buttonlabellist" returns negative ID of the button (-6 to -1)
//  * If none of the on screen buttons was pressed returns 0
BEGIN
 LOCAL selection, mouselist;
 DRAWMENU(buttonlabellist);
 selection := 0; //preinitialize with 0 which is returned if none of the buttons is pressed
 mouselist:=WAIT(-1); // Wait until screen is touched
 // Check whether one of the on-screen buttons was pressed:
 IF (TYPE(mouselist)==6) THEN // Check whether we have a touch event (==list)
  IF (mouselist(1)==3) THEN // Check whether a button was pressed
   IF (mouselist(3) >= #DD:-16h) THEN // check whether it was one of the 6 buttons at the bottom
    selection:=CEILING((mouselist(2)+1)*6/320); // Screen is 320px wide. There are six buttons. hence divide
// mouse value by 320/6. To avoid getting a value of zero when the user presses exactly at the left 
//border a 1 is added to the mouse value
    IF (selection > length(buttonlabellist)) THEN // Check whether a valid button was pressed.
     selection := -selection;
    END;
   END;
  END;
 END;

 RETURN selection;
END;

@Han: You mention in your article that a mouse click actually causes three events. Can you explain this a bit more? If I use wait(-1) I only get one list as return value. Are there cases in which I could get a list of lists with more than 1 event? Or is this just an issue if I loop over WAIT(-1), where I would catch the same user action three times?


RE: Code snippet: drawmenu with catching user action - Han - 03-04-2014 04:02 PM

(03-04-2014 03:36 PM)Stefan Wrote:  @Han: You mention in your article that a mouse click actually causes three events. Can you explain this a bit more? If I use wait(-1) I only get one list as return value.

Correct.

Quote:Are there cases in which I could get a list of lists with more than 1 event?

Not that I am aware of.

Quote:Or is this just an issue if I loop over WAIT(-1), where I would catch the same user action three times?

Correct. If you issue a loop over WAIT(-1), then you would catch the same user action three times (as a mouse down, mouse up, and a "click"). Since your handler only checks for the click event, the other two are simply ignored.