Index: apps/gui/yesno_touchscreen.c =================================================================== --- apps/gui/yesno_touchscreen.c (Revision 0) +++ apps/gui/yesno_touchscreen.c (Revision 0) @@ -0,0 +1,376 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: yesno.c 22633 2009-09-05 18:10:41Z kugel $ + * + * 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 + * 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 "config.h" +#include "yesno.h" +#include "system.h" +#include "kernel.h" +#include "misc.h" +#include "lang.h" +#include "action.h" +#include "talk.h" +#include "settings.h" +#include "viewport.h" +#include "stdio.h" +#include "touchscreen.h" +#include "font.h" +#include + +struct buttons{ + struct button yes; + struct button no; +}; + +struct gui_yesno +{ + const struct text_message * main_message; + const struct text_message * result_message[2]; + + struct viewport *vp; + struct screen * display; +}; + +static void talk_text_message(const struct text_message * message, bool enqueue) +{ + int line; + if(message) + { + for(line=0; linenb_lines; line++) + { + long id = P2ID((unsigned char *)message->message_lines[line]); + if(id>=0) + { + talk_id(id, enqueue); + enqueue = true; + } + } + } +} + +#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 put_message(struct screen *display, + struct viewport *vp, + const struct text_message * message, + int start, int max_y) +{ + int w, h, i; + + 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_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 = 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 + { + put_message(display, vp, yn->main_message, + 0, vp_lines); + } + + display->update_viewport(); +} + +/* + * Draws the yesno result + * - yn : the yesno structure + * - result : the result tha must be displayed : + * YESNO_NO if no + * YESNO_YES if yes + */ +static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result) +{ + const struct text_message * message=yn->result_message[result]; + struct viewport *vp = yn->vp; + struct screen * display=yn->display; + short nb_lines = yn->main_message->nb_lines; + short vp_lines = viewport_get_nb_lines(vp); + short line_shift = 0; + + if(message==NULL) + return false; + display->set_viewport(vp); + display->clear_viewport(); + + if(nb_lines+3< vp_lines) + line_shift=1; + put_message(yn->display, vp, message, line_shift, viewport_get_nb_lines(vp)); + + display->update_viewport(); + return(true); +} + +enum yesno_res gui_syncyesno_run(const struct text_message * main_message, + const struct text_message * yes_message, + const struct text_message * no_message) +{ + int i; + int button; + int result=-1; + bool result_displayed; + struct gui_yesno yn[NB_SCREENS]; + struct viewport vp[NB_SCREENS]; + long talked_tick = 0; + int button_touchscreen; + short touch_x = 0, touch_y = 0; + struct buttons btns; + + touchscreen_set_mode(TOUCHSCREEN_POINT); + + FOR_NB_SCREENS(i) + { + yn[i].main_message=main_message; + yn[i].result_message[YESNO_YES]=yes_message; + 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].set_viewport(yn[i].vp); + screens[i].stop_scroll(); + 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; + } + else{ + yn[i].vp->font = FONT_SYSFIXED; + } + } + + btns.yes.txt = str(LANG_SET_BOOL_YES); + btns.no.txt = str(LANG_SET_BOOL_NO); + btns.yes.vp = btns.no.vp = yn[SCREEN_MAIN].vp; + btns.yes.clicked = btns.no.clicked = false; + + FOR_NB_SCREENS(i) + { + gui_yesno_draw(&screens[i], &(yn[i]), &btns); + } + + while (result==-1) + { + /* Repeat the question every 5secs (more or less) */ + if (global_settings.talk_menu + && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5))) + { + talked_tick = current_tick; + talk_text_message(main_message, false); + } + button = get_action(CONTEXT_YESNOSCREEN, HZ*5); + + if (button != BUTTON_NONE) + { + FOR_NB_SCREENS(i) { + gui_yesno_draw(&screens[i], &(yn[i]), &btns); + } + } + + switch (button) + { + 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; + case ACTION_YESNO_ACCEPT: + result=YESNO_YES; + break; + case ACTION_NONE: + case SYS_CHARGER_DISCONNECTED: + /* ignore some SYS events that can happen */ + continue; + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) + return(YESNO_USB); + result = YESNO_NO; + } + } + + FOR_NB_SCREENS(i) + result_displayed=gui_yesno_draw_result(&(yn[i]), result); + + if (global_settings.talk_menu) + { + talk_text_message((result == YESNO_YES) ? yes_message + : no_message, false); + talk_force_enqueue_next(); + } + if(result_displayed) + sleep(HZ); + + FOR_NB_SCREENS(i) /* stop scrolling before getting out */ + { + screens[i].scroll_stop(yn[i].vp); + screens[i].set_viewport(NULL); + } + + touchscreen_set_mode(global_settings.touch_mode); + 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); Index: apps/SOURCES =================================================================== --- apps/SOURCES (Revision 23718) +++ apps/SOURCES (Arbeitskopie) @@ -84,7 +84,12 @@ #ifdef HAVE_LCD_BITMAP gui/statusbar-skinned.c #endif +#ifdef HAVE_TOUCHSCREEN +gui/touchscreen.c +gui/yesno_touchscreen.c +#else gui/yesno.c +#endif gui/viewport.c gui/skin_engine/skin_buffer.c