Programming:  How to add a button

The program adds a button in the middle of the screen and increments a counter everytime the button is clicked.

#include	<stdrom.h>
#include	"define.h"
#include	"libc.h"

Here, we define the position and geometry of the button (center).

#define BUTTON_X  65
#define BUTTON_Y  74
#define BUTTON_W  37
#define BUTTON_H  16

We have to provide the bitmap for the button. The bitmap is an array of bytes. The first 4 bytes define the width (37) and height (16) of the image. We let the SDK's macro GSIZE convert the 2 words into 4 bytes. Every 8 pixels in a row are packed into a byte from left to right. We deal with monochrome bitmaps and only need a bit to represent the state of a pixel. We must always make the width a multiple of the byte padding with zero's if the case. In our example the width is 37, it means we have 4 bytes and 5 bits, so we use 5 bytes for each row.

/***********************/
/*  ICON Graphics Data  
/***********************/
byte BUTTON_BITMAP[4 + 5 * 16] = 
{
	GSIZE(37, 16),
	0xFF, 0xFF, 0xFF, 0xFF, 0xF7,
	0x80, 0x00, 0x00, 0x00, 0x1F,
	0x80, 0x00, 0x00, 0x00, 0x1F,
	0x87, 0xC0, 0x00, 0x30, 0x1F,
	0x86, 0x60, 0x00, 0x30, 0x1F,
	0x86, 0x6C, 0xCF, 0x3E, 0x1F,
	0x86, 0x6C, 0xD9, 0xB3, 0x1F,
	0x87, 0xCC, 0xDE, 0x33, 0x1F,
	0x86, 0x0C, 0xC7, 0xB3, 0x1F,
	0x86, 0x0C, 0xD9, 0xB3, 0x1F,
	0x86, 0x07, 0xCF, 0x33, 0x1F,
	0x80, 0x00, 0x00, 0x00, 0x1F,
	0x80, 0x00, 0x00, 0x00, 0x1F,
	0x80, 0x00, 0x00, 0x00, 0x1F,
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
	0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
};

We have to define an ID for every object we want the system to manage. We are free to choose one in the range 0x8000-0xFFFF. Every other ID is system defined. So we choose 0xc011.

#define OBJ_BUTTON 0xc011

We have to define a touch table. It is filled up with info about every object on which we want to be notified. In our case we have 2 entries. The last entry is a dummy one, it marks the end of the table. The other entry is for the button. The first 4 parameters define the position (x1, y1, x2, y2). The 5th parameter is the kind of action we are interested in (the button must act as an icon). The 6th one tells the system which object this entry is for.

TCHTBL TchList[2] = 
{
	/* Button */
		BUTTON_X, BUTTON_Y, 
		BUTTON_X + BUTTON_W, BUTTON_Y + BUTTON_H,
		ACT_ICON,
		OBJ_BUTTON,
		0x0000,

	/* End */
		0, 0, 0, 0,
		ACT_NONE,
		OBJ_END,
		0x0000
};

Now we physically define the button. We associate the button to its entry in the touch table (1st parameter), and tell what is the bitmap it has to wear.

T_ICON IconButton = {&TchList[0], BUTTON_BITMAP, NULL, 0x01};

This function gets called when the button is clicked. It increments a counter and displays its value.

void ButtonAction()
{
	static int c;
	char tmp[32];

	c++;

	sprintf(tmp, "Count: %d", c);
	LibStringDsp(tmp, 0, 0, 100, IB_PFONT2); 

	LibPutDisp();

}

The system returns us info about the events we register by filling the instance of the TCHSTS structure... the point on the screen where the action happened, the ID of the object touched, the kind of action, and so on.

void main()
{
	TCHSTS tsts;
	bool bExit = FALSE;

We register an event by pushing its touch table pointer onto a stack. We start up by clearing the stack (LibTchStackClr). Always put a dummy table (NULL), this lets the system know the end of the stack. In our example we put the HardIcon table and the table we defined above. The HardIcon table notifies us on buttons like OFF, MENU, MBAR, ESC...

	LibTchStackClr();
	LibTchStackPush(NULL);

	LibTchStackPush(TchHardIcon);
	LibTchStackPush(&TchList[0]);

Let's clear the screen, and print the button, don't forget LibPutDisp copies the graphic buffer onto the screen.

	LibClrDisp();

	LibIconPrint(&IconButton);
	LibPutDisp();

LibTchInit this initializes the touch system. The program goes on until we set bExit to TRUE. LibTchWait is the heart of touch system. It blocks the execution of our program and waits until an event happens, fills up the tsts structure with the event info, then returns.

	LibTchInit();

	for (;bExit == FALSE;)
	{
		LibTchWait(&tsts);           

At this point an event happened, let's check it out... We test the obj field to see which objects the event refers to. OBJ_HIC_ESC is a reserved code to identify the ESC button, if we press ESC we exit the loop. OBJ_BUTTON is our button, if we want show some animation (button pressed and released) we must call LibIconClick, the we do something (we actually call our callback function)

		switch (tsts.obj)
		{
			case OBJ_HIC_ESC:        
				bExit = TRUE;
			break;

			case OBJ_BUTTON:   
			{
				if (LibIconClick(&IconButton,
					&tsts)) ButtonAction();
			}
			break;	

		}
	}

Time to say goodbye, be polite and leave the touch stack clear, then show the main menu.

	LibTchStackClr();
	LibJumpMenu();

}