Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 23708) +++ apps/SOURCES (working copy) @@ -84,6 +84,9 @@ #ifdef HAVE_LCD_BITMAP gui/statusbar-skinned.c #endif +#ifdef HAVE_TOUCHSCREEN +gui/touchscreen.c +#endif gui/yesno.c gui/viewport.c Index: apps/gui/yesno.c =================================================================== --- apps/gui/yesno.c (revision 23708) +++ apps/gui/yesno.c (working copy) @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2005 by Kevin Ferrare + * Copyright (C) 2009 by Kevin Ferrare, Carsten Schreiter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,7 +29,19 @@ #include "settings.h" #include "viewport.h" +#ifdef HAVE_TOUCHSCREEN +#include "stdio.h" +#include "touchscreen.h" +#include "font.h" +#include +struct buttons +{ + struct button yes; + struct button no; +}; +#endif + struct gui_yesno { const struct text_message * main_message; @@ -56,6 +68,160 @@ } } +#ifdef HAVE_TOUCHSCREEN + +#ifdef HAVE_REMOTE_LCD +/* merges two stings and makes sure the merged string is not longer */ +/* than allowed */ +static void merge_msg(char *target, char *source, int target_length) +{ + int i=0; + char *trg = target; + const char *src = source; + + while (*trg != 0) + { + *trg++; + i++; + } + + while (*src != 0 && i < target_length) { + *trg++ = *src++; + i++; + } + trg = "\0"; + return; +} +#endif + +/* puts a message on the screen and returns the y-coordinate of the message end */ +static int ts_put_message(struct screen *display, + struct viewport *vp, + const struct text_message * message, + int start, int max_y) +{ + int w, h, i=0; + + if(message->nb_lines <= viewport_get_nb_lines(vp)) + { + for(i=0; inb_lines && i+startmessage_lines[i]); + display->getstringsize(buf, &w, &h); + if (w > vp->width) + { + display->puts_scroll(0, i+start, buf); + } + else + { + display->putsxy((vp->width - w) / 2, (i+start) * h, buf); + } + } + } +#ifdef HAVE_REMOTE_LCD + else + { /* merge message lines and put the resulting line on the screen */ + /* this is mainly for the Mrobe500 remote */ +#define MSGLEN 200 + + char msg[MSGLEN]=""; + + for (i=0; inb_lines; i++) + { + char *buf = P2STR((unsigned char *)message->message_lines[i]); + merge_msg(msg, buf, MSGLEN); + if (i < message->nb_lines - 1) { + merge_msg(msg, " - ", MSGLEN); + } + } + merge_msg(msg, " ", MSGLEN); + merge_msg(msg, str(LANG_CONFIRM_WITH_BUTTON), MSGLEN); + merge_msg(msg, " - ", MSGLEN); + merge_msg(msg, str(LANG_CANCEL_WITH_ANY), MSGLEN); + display->puts_scroll(0, start , msg); + } +#endif + return (i + start + 1) * h ; +} + +/* + * Draws the yesno + * - yn : the yesno structure + */ +static void gui_yesno_ts_draw(struct screen * screen, + struct gui_yesno * yn, + struct buttons *btns) +{ + struct screen * display=yn->display; + struct viewport *vp = yn->vp; + int nb_lines, vp_lines, line_shift=0; + int w_yes, w_no, h; + + display->set_viewport(vp); + display->clear_viewport(); + nb_lines = yn->main_message->nb_lines; + vp_lines = viewport_get_nb_lines(vp); + + if (screen->screen_type == SCREEN_MAIN) + { + screen->getstringsize(btns->yes.txt, &w_yes, &h); + screen->getstringsize(btns->no.txt, &w_no, &h); + + /* look which text is longer and use to determinde the width of both */ + /* buttons. max button width is 45% of the VP to prevent overlapping */ + if (w_yes > w_no) + { + btns->yes.width = btns->no.width = w_yes * 3; + } + else + { + btns->yes.width = btns->no.width = w_no * 3; + } + + if (btns->yes.width > vp->width * 0.45) { + btns->yes.width = btns->no.width = vp->width * 0.45; + } + + /* place one button at 25 % viewport width (center) and the other one */ + /* at 75 % (center */ + btns->yes.x = vp->width / 4 - btns->yes.width / 2; + if (btns->yes.x < 0) { + btns->yes.width = btns->no.width = btns->yes.width + btns->yes.x; + btns->yes.x = 1; + } + btns->no.x = vp->width * 3 / 4 - btns->no.width / 2; + btns->yes.height = btns->no.height = h * 3; + + if(nb_lines+3< vp_lines) + line_shift=1; + + /* put the message and get the y coordinate of the message end */ + h = ts_put_message(display, vp, yn->main_message, + line_shift, vp_lines); + + /* place the buttons at the horizontal center between the message end */ + /* and the bottom margin of the viewport */ + btns->yes.y = btns->no.y = (vp->height - h - btns->yes.height) / 2 + h; + + if (btns->yes.y + btns->yes.height > vp->height) + { + btns->yes.height = btns->no.height = vp->height - btns->yes.y; + } + + draw_button(screen, &(btns->yes)); + draw_button(screen, &(btns->no)); + } + else + { + ts_put_message(display, vp, yn->main_message, 0, vp_lines); + } + + display->update_viewport(); +} + +#endif /* HAVE_TOUCHSCREEN */ + +/* puts a message on the screen and returns the y-coordinate of the message end */ static int put_message(struct screen *display, const struct text_message * message, int start, int max_y) @@ -116,13 +282,32 @@ const struct text_message * message=yn->result_message[result]; struct viewport *vp = yn->vp; struct screen * display=yn->display; +#ifdef HAVE_TOUCHSCREEN + short nb_lines = yn->main_message->nb_lines; + short vp_lines = viewport_get_nb_lines(vp); + short line_shift = 0; +#endif + if(message==NULL) return false; + display->set_viewport(vp); display->clear_viewport(); + +#ifdef HAVE_TOUCHSCREEN + if (touchscreen_get_mode() == TOUCHSCREEN_POINT) + { + if (nb_lines+3 < vp_lines) + line_shift=1; + + ts_put_message(yn->display, vp, message, + line_shift, viewport_get_nb_lines(vp)); + } + else +#endif put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); + display->update_viewport(); - display->set_viewport(NULL); return(true); } @@ -137,6 +322,17 @@ struct gui_yesno yn[NB_SCREENS]; struct viewport vp[NB_SCREENS]; long talked_tick = 0; + +#ifdef HAVE_TOUCHSCREEN + int button_touchscreen; + short touch_x = 0, touch_y = 0; + struct buttons btns; + + btns.yes.txt = str(LANG_SET_BOOL_YES); + btns.no.txt = str(LANG_SET_BOOL_NO); + btns.yes.clicked = btns.no.clicked = false; +#endif + FOR_NB_SCREENS(i) { yn[i].main_message=main_message; @@ -144,10 +340,39 @@ yn[i].result_message[YESNO_NO]=no_message; yn[i].display=&screens[i]; yn[i].vp = &vp[i]; + viewport_set_defaults(yn[i].vp, i); screens[i].stop_scroll(); + +#ifdef HAVE_TOUCHSCREEN + if (touchscreen_get_mode() == TOUCHSCREEN_POINT) + { + screens[i].set_viewport(yn[i].vp); + screens[i].clear_viewport(); + screens[i].update_viewport(); + + if (screens[i].screen_type == SCREEN_MAIN) + { + yn[i].vp->font = FONT_UI; + yn[i].vp->x += yn[i].vp->width * 0.1; + yn[i].vp->width -= yn[i].vp->width * 0.2; + yn[i].vp->height = yn[i].vp->height * 0.8; + yn[i].vp->y += yn[i].vp->height * 0.1; + + btns.yes.vp = btns.no.vp = yn[SCREEN_MAIN].vp; + } + else + { + yn[i].vp->font = FONT_SYSFIXED; + } + + gui_yesno_ts_draw(&screens[i], &(yn[i]), &btns); + } + else +#endif gui_yesno_draw(&(yn[i])); } + while (result==-1) { /* Repeat the question every 5secs (more or less) */ @@ -158,8 +383,48 @@ talk_text_message(main_message, false); } button = get_action(CONTEXT_YESNOSCREEN, HZ*5); + +#ifdef HAVE_TOUCHSCREEN + if (touchscreen_get_mode() == TOUCHSCREEN_POINT && + button != BUTTON_NONE) + { + FOR_NB_SCREENS(i) + { + gui_yesno_ts_draw(&screens[i], &(yn[i]), &btns); + } + } +#endif + switch (button) { +#ifdef HAVE_TOUCHSCREEN + case ACTION_TOUCHSCREEN: + button_touchscreen = action_get_touchscreen_press(&touch_x, &touch_y); + + if (check_button_click(&btns.yes, touch_x, touch_y)) + { + btns.yes.clicked = true; + if (button_touchscreen & BUTTON_REL) + { + result=YESNO_YES; + break; + } + } + else if (check_button_click(&btns.no, touch_x, touch_y)) + { + btns.no.clicked = true; + if (button_touchscreen & BUTTON_REL) + { + result=YESNO_NO; + break; + } + } + else + { + button = ACTION_NONE; + } + break; +#endif case ACTION_YESNO_ACCEPT: result=YESNO_YES; break; @@ -187,6 +452,10 @@ sleep(HZ); FOR_NB_SCREENS(i) /* stop scrolling before getting out */ + { screens[i].scroll_stop(yn[i].vp); + screens[i].set_viewport(NULL); + } + return(result); } Index: apps/gui/touchscreen.c =================================================================== --- apps/gui/touchscreen.c (revision 0) +++ apps/gui/touchscreen.c (revision 0) @@ -0,0 +1,85 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: touchscreen.c $ + * + * Copyright (C) 2009 by Carsten Schreiter + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "viewport.h" +#include "touchscreen.h" + + +/* draws a button */ +void draw_button(struct screen *screen, struct button *button) +{ + int txt_w, txt_h; + + screen->set_viewport(button->vp); + + /* draw button */ + if (button->clicked){ + screen->fillrect(button->x, button->y, button->width, button->height); + } + else{ + screen->drawrect(button->x, button->y, button->width, button->height); + } + + /* clear corner pixels of button */ + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + screen->drawpixel(button->x, button->y); + screen->drawpixel(button->x + button->width - 1, button->y); + screen->drawpixel(button->x, button->y + button->height - 1); + screen->drawpixel(button->x + button->width -1, button->y + button->height -1); + screen->set_drawmode(DRMODE_SOLID); + + /* draw button text */ + screen->getstringsize(button->txt, &txt_w, &txt_h); + if (button->clicked){ + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + } + else{ + screen->set_drawmode(DRMODE_SOLID); + } + screen->putsxy(button->x + (button->width - txt_w)/2 , + button->y + (button->height - txt_h)/2, button->txt); + screen->set_drawmode(DRMODE_SOLID); + button->clicked = false; + return; +} + +/* checks if a button has been clicked */ +bool check_button_click(struct button *button, short touch_x, short touch_y) +{ + if (viewport_point_within_vp(button->vp, (int)touch_x, (int)touch_y)) + { /* convert touch into VP coordinates */ + touch_x -= button->vp->x; + touch_y -= button->vp->y; + + if (touch_y >= button->y && + touch_y <= button->y + button->height && + touch_x >= button->x && + touch_x <= button->x + button->width) + { + return true; + } + else{ + return false; + } + } + else{ + return false; + } +} Index: apps/gui/touchscreen.h =================================================================== --- apps/gui/touchscreen.h (revision 0) +++ apps/gui/touchscreen.h (revision 0) @@ -0,0 +1,33 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: touchscreen.h + * + * Copyright (C) 2009 by Carsten Schreiter + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +struct button { + struct viewport *vp; + unsigned char *txt; + int x; + int y; + int width; + int height; + bool clicked; +}; + +extern bool check_button_click(struct button *btn, short touch_x, short touch_y); +extern void draw_button(struct screen *screen, struct button *btn);