/*************************************************************************** guibutton.cpp ------------------- created : Fri Aug 13 22:18:21 CEST 1999 copyright : (C) 1999 by Eric Espie email : torcs@free.fr version : $Id: guibutton.cpp,v 1.3 2005/02/01 15:55:55 berniw Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** @file GUI Buttons Management. @author Eric Espie @version $Id: guibutton.cpp,v 1.3 2005/02/01 15:55:55 berniw Exp $ @ingroup gui */ #include #include #ifdef WIN32 #include #endif #include #include "gui.h" #include "guifont.h" void gfuiButtonInit(void) { } /** Add a graphical button to a screen. @ingroup gui @param scr Screen @param disabled filename of the image when the button is disabled @param enabled filename of the image when the button is enabled @param focused filename of the image when the button is focused @param pushed filename of the image when the button is pushed @param x X position on screen @param y Y position on screen (0 = bottom) @param align Button alignment @param mouse Mouse behavior:
GFUI_MOUSE_UP Action performed when the mouse right button is released
GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed @param userDataOnPush Parameter to the Push callback @param onPush Push callback function @param userDataOnFocus Parameter to the Focus (and lost) callback @param onFocus Focus callback function @param onFocusLost Focus Lost callback function @return Button Id
-1 Error */ int GfuiGrButtonCreate(void *scr, char *disabled, char *enabled, char *focused, char *pushed, int x, int y, int align, int mouse, void *userDataOnPush, tfuiCallback onPush, void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost) { tGfuiGrButton *button; tGfuiObject *object; tGfuiScreen *screen = (tGfuiScreen*)scr; int width, height; object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject)); object->widget = GFUI_GRBUTTON; object->focusMode = GFUI_FOCUS_MOUSE_MOVE; object->id = screen->curId++; object->visible = 1; button = &(object->u.grbutton); button->state = GFUI_BTN_RELEASED; button->userDataOnPush = userDataOnPush; button->onPush = onPush; button->userDataOnFocus = userDataOnFocus; button->onFocus = onFocus; button->onFocusLost = onFocusLost; button->mouseBehaviour = mouse; button->disabled = GfImgReadPng(disabled, &width, &height, 1.0); button->enabled = GfImgReadPng(enabled, &width, &height, 1.0); button->focused = GfImgReadPng(focused, &width, &height, 1.0); button->pushed = GfImgReadPng(pushed, &width, &height, 1.0); switch (align) { case GFUI_ALIGN_HR_VB: object->xmin = x - width; object->xmax = x; object->ymin = y; object->ymax = y + height; break; case GFUI_ALIGN_HR_VC: object->xmin = x - width; object->xmax = x; object->ymin = y - height / 2; object->ymax = y + height / 2; break; case GFUI_ALIGN_HR_VT: object->xmin = x - width; object->xmax = x; object->ymin = y - height; object->ymax = y; break; case GFUI_ALIGN_HC_VB: object->xmin = x - width / 2; object->xmax = x + width / 2; object->ymin = y; object->ymax = y + height; break; case GFUI_ALIGN_HC_VC: object->xmin = x - width / 2; object->xmax = x + width / 2; object->ymin = y - height / 2; object->ymax = y + height / 2; break; case GFUI_ALIGN_HC_VT: object->xmin = x - width / 2; object->xmax = x + width / 2; object->ymin = y - height; object->ymax = y; break; case GFUI_ALIGN_HL_VB: object->xmin = x; object->xmax = x + width; object->ymin = y; object->ymax = y + height; break; case GFUI_ALIGN_HL_VC: object->xmin = x; object->xmax = x + width; object->ymin = y - height / 2; object->ymax = y + height / 2; break; case GFUI_ALIGN_HL_VT: object->xmin = x; object->xmax = x + width; object->ymin = y - height; object->ymax = y; break; default: break; } button->width = width; button->height = height; gfuiAddObject(screen, object); return object->id; } /** Add a state button to a screen. @ingroup gui @param scr Screen @param text Button label @param font Font id @param x X position on screen @param y Y position on screen (0 = bottom) @param width width of the button (0 = text size) @param align Button alignment:
GFUI_ALIGN_HR_VB horizontal right, vertical bottom
GFUI_ALIGN_HR_VC horizontal right, vertical center
GFUI_ALIGN_HR_VT horizontal right, vertical top
GFUI_ALIGN_HC_VB horizontal center, vertical bottom
GFUI_ALIGN_HC_VC horizontal center, vertical center
GFUI_ALIGN_HC_VT horizontal center, vertical top
GFUI_ALIGN_HL_VB horizontal left, vertical bottom
GFUI_ALIGN_HL_VC horizontal left, vertical center
GFUI_ALIGN_HL_VT horizontal left, vertical top @param mouse Mouse behavior:
GFUI_MOUSE_UP Action performed when the mouse right button is released
GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed @param userDataOnPush Parameter to the Push callback @param onPush Push callback function @param userDataOnFocus Parameter to the Focus (and lost) callback @param onFocus Focus callback function @param onFocusLost Focus Lost callback function @return Button Id
-1 Error */ int GfuiButtonStateCreate(void *scr, char *text, int font, int x, int y, int width, int align, int mouse, void *userDataOnPush, tfuiCallback onPush, void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost) { int id; tGfuiButton *button; tGfuiObject *curObject; tGfuiScreen *screen = (tGfuiScreen*)scr; id = GfuiButtonCreate(scr, text, font, x, y, width, align, mouse, userDataOnPush, onPush, userDataOnFocus, onFocus, onFocusLost); curObject = screen->objects; if (curObject != NULL) { do { curObject = curObject->next; if (curObject->id == id) { if (curObject->widget == GFUI_BUTTON) { button = &(curObject->u.button); button->buttonType = GFUI_BTN_STATE; } return id; } } while (curObject != screen->objects); } return id; } /** Add a button to a screen. @ingroup gui @param scr Screen @param text Button label @param font Font id @param x X position on screen @param y Y position on screen (0 = bottom) @param width width of the button (0 = text size) @param align Button alignment:
GFUI_ALIGN_HR_VB horizontal right, vertical bottom
GFUI_ALIGN_HR_VC horizontal right, vertical center
GFUI_ALIGN_HR_VT horizontal right, vertical top
GFUI_ALIGN_HC_VB horizontal center, vertical bottom
GFUI_ALIGN_HC_VC horizontal center, vertical center
GFUI_ALIGN_HC_VT horizontal center, vertical top
GFUI_ALIGN_HL_VB horizontal left, vertical bottom
GFUI_ALIGN_HL_VC horizontal left, vertical center
GFUI_ALIGN_HL_VT horizontal left, vertical top @param mouse Mouse behavior:
GFUI_MOUSE_UP Action performed when the mouse right button is released
GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed @param userDataOnPush Parameter to the Push callback @param onPush Push callback function @param userDataOnFocus Parameter to the Focus (and lost) callback @param onFocus Focus callback function @param onFocusLost Focus Lost callback function @return Button Id
-1 Error */ int GfuiButtonCreate(void *scr, char *text, int font, int x, int y, int width, int align, int mouse, void *userDataOnPush, tfuiCallback onPush, void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost) { tGfuiButton *button; tGfuiLabel *label; tGfuiObject *object; tGfuiScreen *screen = (tGfuiScreen*)scr; object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject)); object->widget = GFUI_BUTTON; object->focusMode = GFUI_FOCUS_MOUSE_MOVE; object->id = screen->curId++; object->visible = 1; button = &(object->u.button); button->state = GFUI_BTN_RELEASED; button->userDataOnPush = userDataOnPush; button->onPush = onPush; button->userDataOnFocus = userDataOnFocus; button->onFocus = onFocus; button->onFocusLost = onFocusLost; button->mouseBehaviour = mouse; button->buttonType = GFUI_BTN_PUSH; button->bgColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]); button->bgColor[1] = &(GfuiColor[GFUI_BGBTNENABLED][0]); button->bgColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]); button->bgFocusColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]); button->bgFocusColor[1] = &(GfuiColor[GFUI_BGBTNFOCUS][0]); button->bgFocusColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]); button->fgColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]); button->fgColor[1] = &(GfuiColor[GFUI_BTNENABLED][0]); button->fgColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]); button->fgFocusColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]); button->fgFocusColor[1] = &(GfuiColor[GFUI_BTNFOCUS][0]); button->fgFocusColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]); label = &(button->label); label->text = (char*)calloc(1, 100); strncpy(label->text, text, 100); label->font = gfuiFont[font]; label->maxlen = 99; if (width == 0) { width = gfuiFont[font]->getWidth((const char *)text); } label->align = align; switch(align&0xF0) { case 0x00 /* LEFT */: label->x = object->xmin = x; label->y = y - 2 * gfuiFont[font]->getDescender(); object->ymin = y; object->xmax = x + width; object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender(); break; case 0x10 /* CENTER */: object->xmin = x - width / 2; label->x = x - gfuiFont[font]->getWidth((const char *)text) / 2; label->y = y - 2 * gfuiFont[font]->getDescender(); object->ymin = y; object->xmax = x + width / 2; object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender(); break; case 0x20 /* RIGHT */: label->x = object->xmin = x - width; label->y = y - 2 * gfuiFont[font]->getDescender(); object->ymin = y; object->xmax = x; object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender(); break; } #define HORIZ_MARGIN 10 object->xmin -= HORIZ_MARGIN; object->xmax += HORIZ_MARGIN; gfuiAddObject(screen, object); return object->id; } /** Change the label of a button. @ingroup gui @param scr Screen @param id Button Id @param text New label of the button */ void GfuiButtonSetText(void *scr, int id, char *text) { tGfuiObject *curObject; tGfuiScreen *screen = (tGfuiScreen*)scr; int oldmin, oldmax; curObject = screen->objects; if (curObject != NULL) { do { curObject = curObject->next; if (curObject->id == id) { if (curObject->widget == GFUI_BUTTON) { oldmax = curObject->xmax; oldmin = curObject->xmin; gfuiSetLabelText(curObject, &(curObject->u.button.label), text); curObject->xmax = oldmax; curObject->xmin = oldmin; } return; } } while (curObject != screen->objects); } } /** Get the Id of the button focused in the current screen. @ingroup gui @return Button Id
-1 if no button or no screen or the focus is not on a button */ int GfuiButtonGetFocused(void) { tGfuiObject *curObject; if (GfuiScreen != NULL) { curObject = GfuiScreen->objects; if (curObject != NULL) { do { curObject = curObject->next; if (curObject->focus) { if (curObject->widget == GFUI_BUTTON) { return curObject->id; } return -1; } } while (curObject != GfuiScreen->objects); } } return -1; } void gfuiDrawButton(tGfuiObject *obj) { tGfuiLabel *label; tGfuiButton *button; float *fgColor; float *bgColor; button = &(obj->u.button); if (obj->state == GFUI_DISABLE) { button->state = GFUI_BTN_DISABLE; } if (obj->focus) { fgColor = button->fgFocusColor[button->state]; bgColor = button->bgFocusColor[button->state]; } else { fgColor = button->fgColor[button->state]; bgColor = button->bgColor[button->state]; } if (bgColor[3] != 0.0) { glColor4fv(bgColor); glBegin(GL_QUADS); glVertex2i(obj->xmin, obj->ymin); glVertex2i(obj->xmin, obj->ymax); glVertex2i(obj->xmax, obj->ymax); glVertex2i(obj->xmax, obj->ymin); glEnd(); glColor4fv(fgColor); glBegin(GL_LINE_STRIP); glVertex2i(obj->xmin, obj->ymin); glVertex2i(obj->xmin, obj->ymax); glVertex2i(obj->xmax, obj->ymax); glVertex2i(obj->xmax, obj->ymin); glVertex2i(obj->xmin, obj->ymin); glEnd(); } label = &(button->label); glColor4fv(fgColor); gfuiPrintString(label->x, label->y, label->font, label->text); } void gfuiDrawGrButton(tGfuiObject *obj) { int sw, sh, vw, vh; tGfuiGrButton *button; unsigned char *img; button = &(obj->u.grbutton); if (obj->state == GFUI_DISABLE) { img = button->disabled; } else if (button->state == GFUI_BTN_PUSHED) { img = button->pushed; } else if (obj->focus) { img = button->focused; } else { img = button->enabled; } GfScrGetSize(&sw, &sh, &vw, &vh); glRasterPos2i(obj->xmin, obj->ymin); glPixelZoom((float)vw / (float)GfuiScreen->width, (float)vh / (float)GfuiScreen->height); glDrawPixels(button->width, button->height, GL_RGBA, GL_UNSIGNED_BYTE, img); } void gfuiGrButtonAction(int action) { tGfuiGrButton *button; button = &(GfuiScreen->hasFocus->u.grbutton); switch (button->buttonType) { case GFUI_BTN_PUSH: if (action == 2) { /* enter key */ if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else if (action == 1) { /* mouse up */ if (button->state != GFUI_BTN_RELEASED) { button->state = GFUI_BTN_RELEASED; if (button->mouseBehaviour == GFUI_MOUSE_UP) { if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } } } else { /* mouse down */ if (button->state != GFUI_BTN_PUSHED) { button->state = GFUI_BTN_PUSHED; if (button->mouseBehaviour == GFUI_MOUSE_DOWN) { if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } } } break; case GFUI_BTN_STATE: if (action == 2) { /* enter key */ if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } else if (action == 1) { /* mouse up */ if (button->mouseBehaviour == GFUI_MOUSE_UP) { if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } } else { /* mouse down */ if (button->mouseBehaviour == GFUI_MOUSE_DOWN) { if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } } break; } } void gfuiButtonAction(int action) { tGfuiButton *button; button = &(GfuiScreen->hasFocus->u.button); switch (button->buttonType) { case GFUI_BTN_PUSH: if (action == 2) { /* enter key */ if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else if (action == 1) { /* mouse up */ button->state = GFUI_BTN_RELEASED; if (button->mouseBehaviour == GFUI_MOUSE_UP) { if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } } else { /* mouse down */ button->state = GFUI_BTN_PUSHED; if (button->mouseBehaviour == GFUI_MOUSE_DOWN) { if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } } break; case GFUI_BTN_STATE: if (action == 2) { /* enter key */ if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } else if (action == 1) { /* mouse up */ if (button->mouseBehaviour == GFUI_MOUSE_UP) { if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } } else { /* mouse down */ if (button->mouseBehaviour == GFUI_MOUSE_DOWN) { if (button->state == GFUI_BTN_RELEASED) { button->state = GFUI_BTN_PUSHED; if (button->onPush != NULL) { button->onPush(button->userDataOnPush); } } else { button->state = GFUI_BTN_RELEASED; } } } break; } } void gfuiReleaseButton(tGfuiObject *obj) { tGfuiButton *button; tGfuiLabel *label; button = &(obj->u.button); label = &(button->label); freez(button->userDataOnFocus); free(label->text); free(obj); } void gfuiReleaseGrButton(tGfuiObject *obj) { tGfuiGrButton *button; button = &(obj->u.grbutton); free(button->disabled); free(button->enabled); free(button->focused); free(button->pushed); free(obj); }