rockbox/apps/gui/yesno.c

282 lines
8.5 KiB
C
Raw Normal View History

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Kevin Ferrare
*
* 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 "appevents.h"
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; line<message->nb_lines; line++)
{
long id = P2ID((unsigned char *)message->message_lines[line]);
if(id>=0)
{
talk_id(id, enqueue);
enqueue = true;
}
}
}
}
static int put_message(struct screen *display,
const struct text_message * message,
int start, int max_y)
{
int i;
for(i=0; i<message->nb_lines && i+start<max_y; i++)
{
display->puts_scroll(0, i+start,
P2STR((unsigned char *)message->message_lines[i]));
}
return i;
}
/*
* Draws the yesno
* - yn : the yesno structure
*/
static void gui_yesno_draw(struct gui_yesno * yn)
{
struct screen * display=yn->display;
struct viewport *vp = yn->vp;
int nb_lines, vp_lines, line_shift=0;
LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
2020-10-07 06:01:35 +00:00
struct viewport *last_vp;
LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
2020-10-07 06:01:35 +00:00
last_vp = display->set_viewport(vp);
display->clear_viewport();
nb_lines = yn->main_message->nb_lines;
vp_lines = viewport_get_nb_lines(vp);
if(nb_lines+3< vp_lines)
line_shift=1;
line_shift += put_message(display, yn->main_message,
line_shift, vp_lines);
#ifdef HAVE_TOUCHSCREEN
if (display->screen_type == SCREEN_MAIN)
{
int w,h;
int rect_w = vp->width/2, rect_h = vp->height/2;
int old_pattern = vp->fg_pattern;
vp->fg_pattern = LCD_RGBPACK(0,255,0);
display->drawrect(0, rect_h, rect_w, rect_h);
display->getstringsize(str(LANG_SET_BOOL_YES), &w, &h);
display->putsxy((rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_YES));
vp->fg_pattern = LCD_RGBPACK(255,0,0);
display->drawrect(rect_w, rect_h, rect_w, rect_h);
display->getstringsize(str(LANG_SET_BOOL_NO), &w, &h);
display->putsxy(rect_w + (rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_NO));
vp->fg_pattern = old_pattern;
}
#else
/* Space remaining for yes / no text ? */
if(line_shift+2 <= vp_lines)
{
if(line_shift+3 <= vp_lines)
line_shift++;
display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON));
display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY));
}
#endif
display->update_viewport();
LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
2020-10-07 06:01:35 +00:00
display->set_viewport(last_vp);
}
/*
* 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;
if(message==NULL)
return false;
LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
2020-10-07 06:01:35 +00:00
struct viewport *last_vp = display->set_viewport(vp);
display->clear_viewport();
put_message(yn->display, message, 0, viewport_get_nb_lines(vp));
display->update_viewport();
LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
2020-10-07 06:01:35 +00:00
display->set_viewport(last_vp);
return(true);
}
static void gui_yesno_ui_update(unsigned short id, void *event_data, void *user_data)
{
(void)id;
(void)event_data;
struct gui_yesno* yn = (struct gui_yesno*)user_data;
FOR_NB_SCREENS(i)
gui_yesno_draw(&yn[i]);
}
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 button;
int result=-1;
bool result_displayed;
struct gui_yesno yn[NB_SCREENS];
struct viewport vp[NB_SCREENS];
long talked_tick = 0;
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];
viewportmanager_theme_enable(i, true, yn[i].vp);
screens[i].scroll_stop();
gui_yesno_draw(&(yn[i]));
}
#ifdef HAVE_TOUCHSCREEN
/* switch to point mode because that's more intuitive */
enum touchscreen_mode old_mode = touchscreen_get_mode();
touchscreen_set_mode(TOUCHSCREEN_POINT);
#endif
/* make sure to eat any extranous keypresses */
action_wait_for_release();
button_clear_queue();
/* hook into UI update events to avoid the dialog disappearing
* in case the skin decides to do a full refresh */
add_event_ex(GUI_EVENT_NEED_UI_UPDATE, false, gui_yesno_ui_update, &yn[0]);
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);
switch (button)
{
#ifdef HAVE_TOUCHSCREEN
case ACTION_TOUCHSCREEN:
{
short int x, y;
if (action_get_touchscreen_press_in_vp(&x, &y, yn[0].vp) == BUTTON_REL)
{
if (y > yn[0].vp->height/2)
{
if (x <= yn[0].vp->width/2)
result = YESNO_YES;
else
result = YESNO_NO;
}
}
}
break;
#endif
case ACTION_YESNO_ACCEPT:
result=YESNO_YES;
break;
case ACTION_NONE:
case ACTION_UNKNOWN:
case SYS_CHARGER_DISCONNECTED:
case SYS_BATTERY_UPDATE:
case SYS_TIMEOUT:
#if CONFIG_CHARGING
case SYS_CHARGER_CONNECTED:
#endif
/* ignore some SYS events that can happen */
continue;
default:
if(default_event_handler(button) == SYS_USB_CONNECTED) {
result = YESNO_USB;
goto exit;
}
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)
{
screens[i].scroll_stop_viewport(yn[i].vp);
viewportmanager_theme_undo(i, true);
}
exit:
remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]);
#ifdef HAVE_TOUCHSCREEN
touchscreen_set_mode(old_mode);
#endif
return result;
}
/* Function to manipulate all yesno dialogues.
This function needs the output text as an argument. */
bool yesno_pop(const char* text)
{
const char *lines[]={text};
const struct text_message message={lines, 1};
bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
FOR_NB_SCREENS(i)
screens[i].clear_viewport();
return ret;
}