mirror of
https://github.com/markqvist/OpenModem.git
synced 2025-12-16 00:43:59 -05:00
Working
This commit is contained in:
commit
c898b090dd
1049 changed files with 288572 additions and 0 deletions
105
bertos/gui/levelbar.c
Normal file
105
bertos/gui/levelbar.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* \file
|
||||
* Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
|
||||
*
|
||||
*
|
||||
* \brief Graphics user interface element to display a level bar.
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*/
|
||||
|
||||
#include "levelbar.h"
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the LevelBar widget with the bitmap associated,
|
||||
* the value range and the coordinates in the bitmap.
|
||||
* \note The levelbar should be at least 5 pixels wide and high
|
||||
* for correct borders drawing. No check is done on this.
|
||||
*/
|
||||
void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos,
|
||||
coord_t x1, coord_t y1, coord_t x2, coord_t y2)
|
||||
{
|
||||
lb->bitmap = bmp;
|
||||
lb->type = type;
|
||||
lb->min = min;
|
||||
lb->max = max;
|
||||
lb->pos = pos;
|
||||
lb->x1 = x1;
|
||||
lb->y1 = y1;
|
||||
lb->x2 = x2;
|
||||
lb->y2 = y2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the level.
|
||||
*/
|
||||
void lbar_setLevel(struct LevelBar *lb, int level)
|
||||
{
|
||||
if (level < lb->min)
|
||||
level = lb->min;
|
||||
if (level > lb->max)
|
||||
level = lb->max;
|
||||
|
||||
lb->pos = level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current level.
|
||||
*/
|
||||
int lbar_getLevel(struct LevelBar *lb)
|
||||
{
|
||||
return lb->pos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change level with respect to previous value
|
||||
* (delta can be negative).
|
||||
*/
|
||||
void lbar_changeLevel(struct LevelBar *lb, int delta)
|
||||
{
|
||||
lbar_setLevel(lb, lb->pos + delta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the top limit.
|
||||
*/
|
||||
void lbar_setMax(struct LevelBar *lb, int max)
|
||||
{
|
||||
lb->max = max;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the LevelBar on the bitmap.
|
||||
*/
|
||||
void lbar_draw(struct LevelBar *lb)
|
||||
{
|
||||
#define BORDERW 1
|
||||
#define BORDERH 1
|
||||
|
||||
/* Compute filled bar length in pixels */
|
||||
int totlen = (lb->type & LBAR_HORIZONTAL) ? lb->x2 - lb->x1 - BORDERW*4 : lb->y2 - lb->y1 - BORDERH*4;
|
||||
int range = lb->max - lb->min;
|
||||
int barlen = ((long)(lb->pos - lb->min) * (long)totlen + range - 1) / range;
|
||||
|
||||
// Draw border
|
||||
gfx_rectDraw(lb->bitmap, lb->x1, lb->y1, lb->x2, lb->y2);
|
||||
|
||||
// Clear inside
|
||||
gfx_rectClear(lb->bitmap, lb->x1 + BORDERW, lb->y1 + BORDERH, lb->x2 - BORDERW, lb->y2 - BORDERH);
|
||||
|
||||
// Draw bar
|
||||
if (lb->type & LBAR_HORIZONTAL)
|
||||
gfx_rectFill(lb->bitmap,
|
||||
lb->x1 + BORDERW*2, lb->y1 + BORDERH*2,
|
||||
lb->x1 + BORDERW*2 + barlen, lb->y2 - BORDERH*2);
|
||||
else
|
||||
gfx_rectFill(lb->bitmap,
|
||||
lb->x1 + BORDERW*2, lb->y2 - BORDERH*2 - barlen,
|
||||
lb->x2 - BORDERW*2, lb->y2 - BORDERH*2);
|
||||
}
|
||||
39
bertos/gui/levelbar.h
Normal file
39
bertos/gui/levelbar.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* \file
|
||||
* Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
|
||||
*
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*
|
||||
* \brief Graphics level bar widget
|
||||
*/
|
||||
|
||||
#ifndef GUI_LEVELBAR_H
|
||||
#define GUI_LEVELBAR_H
|
||||
|
||||
#include <gfx/gfx.h>
|
||||
|
||||
|
||||
/** Type of levelbar */
|
||||
#define LBAR_HORIZONTAL 1
|
||||
#define LBAR_VERTICAL 2
|
||||
|
||||
typedef struct LevelBar
|
||||
{
|
||||
struct Bitmap *bitmap;
|
||||
int type;
|
||||
int pos; ///< Current level
|
||||
int min; ///< Minimum level
|
||||
int max; ///< Maximum level
|
||||
coord_t x1, y1, x2, y2; ///< Position of widget in the bitmap
|
||||
} LevelBar;
|
||||
|
||||
void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos,
|
||||
coord_t x1, coord_t y1, coord_t x2, coord_t y2);
|
||||
void lbar_setLevel(struct LevelBar *lb, int level);
|
||||
int lbar_getLevel(struct LevelBar *lb);
|
||||
void lbar_changeLevel(struct LevelBar *lb, int delta);
|
||||
void lbar_setMax(struct LevelBar *lb, int max);
|
||||
void lbar_draw(struct LevelBar *lb);
|
||||
|
||||
#endif /* GUI_LEVELBAR_H */
|
||||
321
bertos/gui/leveledit.c
Normal file
321
bertos/gui/leveledit.c
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
|
||||
*
|
||||
* -->
|
||||
*
|
||||
* \brief Generic editor for (volume/gain/contrast/...) setting.
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*/
|
||||
|
||||
#include "leveledit.h"
|
||||
|
||||
#include "cfg/cfg_menu.h"
|
||||
#include <cfg/macros.h> /* MAX() */
|
||||
|
||||
#include <drv/kbd.h>
|
||||
#include <drv/timer.h>
|
||||
|
||||
#include <gui/levelbar.h>
|
||||
|
||||
#include <cpu/pgm.h>
|
||||
|
||||
#include <gfx/text.h>
|
||||
#include <gfx/font.h>
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
#include <gui/menubar.h>
|
||||
#endif
|
||||
|
||||
#warning FIXME: Revise me!
|
||||
|
||||
#define LBAR_HEIGHT 16
|
||||
|
||||
/**
|
||||
* Allow user to change level.
|
||||
*/
|
||||
void level_edit(struct LevelEdit *lev)
|
||||
{
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
/* Labels for menubars */
|
||||
enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 };
|
||||
const_iptr_t labels[] =
|
||||
{
|
||||
(const_iptr_t)LABEL_BACK,
|
||||
(const_iptr_t)LABEL_MINUS,
|
||||
(const_iptr_t)LABEL_PLUS,
|
||||
(const_iptr_t)LABEL_EMPTY
|
||||
};
|
||||
struct MenuBar mb;
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
|
||||
struct LevelBar bar1, bar2;
|
||||
keymask_t keys, old_rpt_mask;
|
||||
int step, rep_step;
|
||||
|
||||
rep_step = MAX(lev->step, ((lev->max - lev->min) / 200));
|
||||
step = lev->step;
|
||||
|
||||
// Allow keys repetition.
|
||||
old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
|
||||
|
||||
text_clear(lev->bitmap);
|
||||
//text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE);
|
||||
text_puts(lev->title, lev->bitmap);
|
||||
//text_style(0, STYLEF_UNDERLINE);
|
||||
|
||||
if (lev->type & LEVELEDIT_DOUBLE)
|
||||
{
|
||||
int chn = 0; /* edit both channels */
|
||||
|
||||
/* Levelbars init */
|
||||
lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
|
||||
lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23);
|
||||
lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL,
|
||||
lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23);
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
labels[3] = (const_iptr_t)ch_labels[chn];
|
||||
mbar_init(&mb, lev->bitmap, labels, countof(labels));
|
||||
mbar_draw(&mb);
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
|
||||
/* Input loop for double level setting */
|
||||
for (;;)
|
||||
{
|
||||
#if CONFIG_LEVELEDIT_TIMEOUT != 0
|
||||
ticks_t idle_timeout = timer_clock();
|
||||
#endif
|
||||
do
|
||||
{
|
||||
if (lev->display_hook)
|
||||
lev->display_hook(lev);
|
||||
else
|
||||
{
|
||||
text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit);
|
||||
PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val);
|
||||
PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val);
|
||||
|
||||
lbar_setLevel(&bar1, *lev->ch1_val);
|
||||
lbar_setLevel(&bar2, *lev->ch2_val);
|
||||
lbar_draw(&bar1);
|
||||
lbar_draw(&bar2);
|
||||
}
|
||||
|
||||
#if CONFIG_LEVELEDIT_TIMEOUT != 0
|
||||
if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT))
|
||||
{
|
||||
/* Accept input implicitly */
|
||||
keys = K_OK;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
while (!(keys = kbd_peek()));
|
||||
|
||||
if (keys & K_CANCEL)
|
||||
break;
|
||||
|
||||
if (keys & K_OK)
|
||||
{
|
||||
chn = (chn + 1) % 3;
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
labels[3] = (const_iptr_t)ch_labels[chn];
|
||||
mbar_draw(&mb);
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
}
|
||||
|
||||
/* Increment step to achieve greater accelerations on larger values */
|
||||
if (keys & K_REPEAT)
|
||||
step = MIN(rep_step, step + 1);
|
||||
else
|
||||
step = lev->step;
|
||||
|
||||
if (keys & (K_UP | K_DOWN))
|
||||
{
|
||||
if (keys & K_UP)
|
||||
{
|
||||
/* If changing both channels (chn == 0), don't change
|
||||
* level if one of two is at min or max */
|
||||
if (chn != 0 ||
|
||||
(*lev->ch1_val + step <= lev->max
|
||||
&& *lev->ch2_val + step <= lev->max))
|
||||
{
|
||||
/* If chn == 0 change both channels */
|
||||
if (chn != 2)
|
||||
{
|
||||
*lev->ch1_val += step;
|
||||
if (*lev->ch1_val > lev->max)
|
||||
*lev->ch1_val = lev->max;
|
||||
}
|
||||
if (chn != 1)
|
||||
{
|
||||
*lev->ch2_val += step;
|
||||
if (*lev->ch2_val > lev->max)
|
||||
*lev->ch2_val = lev->max;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (chn != 0 ||
|
||||
(*lev->ch1_val - step >= lev->min
|
||||
&& *lev->ch2_val - step >= lev->min))
|
||||
{
|
||||
if (chn != 2)
|
||||
{
|
||||
*lev->ch1_val -= step;
|
||||
if (*lev->ch1_val < lev->min)
|
||||
*lev->ch1_val = lev->min;
|
||||
}
|
||||
if (chn != 1)
|
||||
{
|
||||
*lev->ch2_val -= step;
|
||||
if (*lev->ch2_val < lev->min)
|
||||
*lev->ch2_val = lev->min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lev->set_hook)
|
||||
lev->set_hook();
|
||||
}
|
||||
} // end for(;;)
|
||||
}
|
||||
else
|
||||
{
|
||||
const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
|
||||
|
||||
/*
|
||||
const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit),
|
||||
PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit));
|
||||
|
||||
const coord_t barlen = lev->bitmap->width - 6 - textw;
|
||||
*/
|
||||
const coord_t barlen = lev->bitmap->width;
|
||||
const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height;
|
||||
lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
|
||||
lev->min, lev->max, *lev->ch1_val,
|
||||
0, barvtop, barlen, barvtop + LBAR_HEIGHT);
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
mbar_init(&mb, lev->bitmap, labels, countof(labels));
|
||||
mbar_draw(&mb);
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
|
||||
/* Input loop for single level setting */
|
||||
for (;;)
|
||||
{
|
||||
#if CONFIG_LEVELEDIT_TIMEOUT != 0
|
||||
ticks_t idle_timeout = timer_clock();
|
||||
#endif
|
||||
do
|
||||
{
|
||||
if (lev->display_hook)
|
||||
lev->display_hook(lev);
|
||||
else
|
||||
{
|
||||
if (lev->type != LEVELEDIT_NOBAR)
|
||||
{
|
||||
lbar_setLevel(&bar1, *lev->ch1_val);
|
||||
lbar_draw(&bar1);
|
||||
}
|
||||
PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height,
|
||||
TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit);
|
||||
}
|
||||
|
||||
#if CONFIG_LEVELEDIT_TIMEOUT != 0
|
||||
if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT)
|
||||
{
|
||||
/* Accept input implicitly */
|
||||
keys = K_CANCEL;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
while (!(keys = kbd_peek()));
|
||||
|
||||
if (keys & K_CANCEL)
|
||||
break;
|
||||
|
||||
/* Increment step to achieve greater accelerations on larger values */
|
||||
if (keys & K_REPEAT)
|
||||
step = MIN(rep_step, step + 1);
|
||||
else
|
||||
step = lev->step;
|
||||
|
||||
if (keys & K_UP)
|
||||
{
|
||||
*lev->ch1_val += step;
|
||||
if (*lev->ch1_val > lev->max)
|
||||
*lev->ch1_val = lev->max;
|
||||
}
|
||||
|
||||
if (keys & K_DOWN)
|
||||
{
|
||||
*lev->ch1_val -= step;
|
||||
if (*lev->ch1_val < lev->min)
|
||||
*lev->ch1_val = lev->min;
|
||||
}
|
||||
|
||||
if (lev->set_hook)
|
||||
lev->set_hook();
|
||||
}
|
||||
}
|
||||
|
||||
kbd_setRepeatMask(old_rpt_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* LevelEdit structure initialization.
|
||||
* Init data structure and init LevelEdit widgets.
|
||||
*/
|
||||
void level_init(struct LevelEdit *lev,
|
||||
int type,
|
||||
struct Bitmap *bmp, const char *title, const char *unit,
|
||||
int min, int max, int step,
|
||||
int *ch1_val, int *ch2_val,
|
||||
level_set_callback *set_hook, display_callback *display_hook)
|
||||
{
|
||||
lev->type = type;
|
||||
lev->bitmap = bmp;
|
||||
lev->title = title;
|
||||
lev->unit = unit;
|
||||
lev->min = min;
|
||||
lev->max = max;
|
||||
lev->step = step;
|
||||
|
||||
lev->ch1_val = ch1_val;
|
||||
lev->ch2_val = ch2_val;
|
||||
lev->set_hook = set_hook;
|
||||
lev->display_hook = display_hook;
|
||||
}
|
||||
87
bertos/gui/leveledit.h
Normal file
87
bertos/gui/leveledit.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
|
||||
*
|
||||
* -->
|
||||
*
|
||||
* \brief Generic editor for (volume/gain/contrast/...) setting.
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*/
|
||||
#ifndef GUI_LEVELEDIT_H
|
||||
#define GUI_LEVELEDIT_H
|
||||
|
||||
//#include <gui/levelbar.h>
|
||||
|
||||
/* Type for level_init */
|
||||
#define LEVELEDIT_NOBAR 0 /**< Edit number only, without bar nor units */
|
||||
#define LEVELEDIT_SINGLE 1 /**< Single channel editing */
|
||||
#define LEVELEDIT_DOUBLE 2 /**< Double channel editing */
|
||||
|
||||
|
||||
|
||||
/* Fwd decl */
|
||||
struct Bitmap;
|
||||
struct LevelEdit;
|
||||
|
||||
/** Type for callback used to set meter levels */
|
||||
typedef void level_set_callback(void);
|
||||
|
||||
/** Type for callback used to customize display of units */
|
||||
typedef void display_callback(struct LevelEdit *);
|
||||
|
||||
/**
|
||||
* State of a level meter
|
||||
*/
|
||||
typedef struct LevelEdit {
|
||||
int type; /*<! Type of level edititing mode (see prev defines) */
|
||||
const char *title; /*<! Title on top of screen */
|
||||
const char *unit; /*<! Unit of quantity changed by this LevelEdit */
|
||||
int min; /*<! Minimum level */
|
||||
int max; /*<! Maximum level */
|
||||
int step; /*<! Value of a single increment/decrement */
|
||||
|
||||
level_set_callback *set_hook; /*<! Callback called when a value is changed */
|
||||
display_callback *display_hook; /*<! Callback for complex unit display */
|
||||
int *ch1_val; /*<! (left) Value edited by this leveledit */
|
||||
int *ch2_val; /*<! Right channel edited */
|
||||
|
||||
struct Bitmap *bitmap; /*<! Bitmap where the whole thing is rendered */
|
||||
} LevelEdit;
|
||||
|
||||
|
||||
void level_init(struct LevelEdit *lev,
|
||||
int type,
|
||||
struct Bitmap *bmp, const char *title, const char *unit,
|
||||
int min, int max, int step,
|
||||
int *ch1_val, int *ch2_val,
|
||||
level_set_callback *change_hook, display_callback *display_hook);
|
||||
void level_edit(struct LevelEdit *lev);
|
||||
|
||||
#endif /* GUI_LEVELEDIT_H */
|
||||
582
bertos/gui/menu.c
Normal file
582
bertos/gui/menu.c
Normal file
|
|
@ -0,0 +1,582 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2003, 2004, 2006, 2010 Develer S.r.l. (http://www.develer.com/)
|
||||
* Copyright 2000 Bernie Innocenti <bernie@codewiz.org>
|
||||
*
|
||||
* -->
|
||||
*
|
||||
* \author Bernie Innocenti <bernie@codewiz.org>
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*
|
||||
* \brief General pourpose menu handling functions
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
#include "cfg/cfg_menu.h"
|
||||
#include "cfg/cfg_arch.h"
|
||||
|
||||
#include <cfg/compiler.h>
|
||||
#include <cfg/debug.h>
|
||||
|
||||
#include <gfx/gfx.h>
|
||||
#include <gfx/font.h>
|
||||
#include <gfx/text.h>
|
||||
|
||||
#include <cpu/power.h>
|
||||
|
||||
#include <drv/kbd.h>
|
||||
|
||||
#include <string.h> /* strcpy() */
|
||||
|
||||
#if CPU_HARVARD
|
||||
#include <avr/pgmspace.h> /* strncpy_P() */
|
||||
#endif
|
||||
|
||||
#if (CONFIG_MENU_TIMEOUT != 0)
|
||||
#include <drv/timer.h>
|
||||
#endif
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
#include "menubar.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LOCALE) && (CONFIG_LOCALE == 1)
|
||||
#include "msg.h"
|
||||
#else
|
||||
#define PTRMSG(x) ((const char *)x)
|
||||
#endif
|
||||
|
||||
|
||||
/* Temporary fake defines for ABORT stuff... */
|
||||
#define abort_top 0
|
||||
#define PUSH_ABORT false
|
||||
#define POP_ABORT do {} while(0)
|
||||
#define DO_ABORT do {} while(0)
|
||||
|
||||
|
||||
/**
|
||||
* Return the total number of items in in a menu.
|
||||
*/
|
||||
static int menu_count(const struct Menu *menu)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
for (cnt = 0; /*NOP*/; ++cnt)
|
||||
{
|
||||
const MenuItem *item = &menu->items[cnt];
|
||||
#if CPU_HARVARD
|
||||
MenuItem ram_item;
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
memcpy_P(&ram_item, item, sizeof(ram_item));
|
||||
item = &ram_item;
|
||||
}
|
||||
#endif
|
||||
if (!(item->label || item->hook))
|
||||
break;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
|
||||
/**
|
||||
* Update the menu bar according to the selected item and redraw it.
|
||||
*/
|
||||
static void menu_update_menubar(
|
||||
const struct Menu *menu,
|
||||
struct MenuBar *mb,
|
||||
int selected)
|
||||
{
|
||||
int item_flags;
|
||||
#if CPU_HARVARD
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
ASSERT(sizeof(menu->items[selected].flags) == sizeof(int));
|
||||
item_flags = pgm_read_int(&menu->items[selected].flags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
item_flags = menu->items[selected].flags;
|
||||
|
||||
const_iptr_t newlabel = (const_iptr_t)LABEL_OK;
|
||||
|
||||
if (item_flags & MIF_DISABLED)
|
||||
newlabel = (const_iptr_t)LABEL_EMPTY;
|
||||
else if (item_flags & MIF_TOGGLE)
|
||||
newlabel = (const_iptr_t)LABEL_SEL;
|
||||
else if (item_flags & MIF_CHECKIT)
|
||||
{
|
||||
newlabel = (item_flags & MIF_CHECKED) ?
|
||||
(const_iptr_t)LABEL_EMPTY : (const_iptr_t)LABEL_SEL;
|
||||
}
|
||||
|
||||
mb->labels[3] = newlabel;
|
||||
mbar_draw(mb);
|
||||
}
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
|
||||
|
||||
static void menu_defaultRenderHook(struct Bitmap *bm, int ypos, bool selected, const struct MenuItem *item)
|
||||
{
|
||||
if (item->flags & MIF_CHECKIT)
|
||||
{
|
||||
gfx_rectClear(bm, 0, ypos,
|
||||
bm->font->height, ypos + bm->font->height);
|
||||
|
||||
if (item->flags & MIF_TOGGLE)
|
||||
gfx_rectDraw(bm, 2, ypos + 2,
|
||||
bm->font->height - 2, ypos + bm->font->height - 2);
|
||||
if (item->flags & MIF_CHECKED)
|
||||
{
|
||||
gfx_line(bm,
|
||||
3, ypos + 3,
|
||||
bm->font->height - 3, ypos + bm->font->height - 3);
|
||||
gfx_line(bm,
|
||||
bm->font->height - 3, ypos + 3,
|
||||
3, ypos + bm->font->height - 3);
|
||||
}
|
||||
}
|
||||
|
||||
#if CPU_HARVARD
|
||||
((item->flags & MIF_RAMLABEL) ? text_xyprintf : text_xyprintf_P)
|
||||
#else
|
||||
text_xyprintf
|
||||
#endif
|
||||
(
|
||||
bm, (item->flags & MIF_CHECKIT) ? bm->font->height : 0, ypos,
|
||||
selected ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL,
|
||||
PTRMSG(item->label)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a menu on the display.
|
||||
*/
|
||||
static void menu_layout(
|
||||
const struct Menu *menu,
|
||||
int first_item,
|
||||
int selected,
|
||||
bool redraw)
|
||||
{
|
||||
coord_t ypos;
|
||||
int i;
|
||||
const char * PROGMEM title = PTRMSG(menu->title);
|
||||
Bitmap *bm = menu->bitmap;
|
||||
|
||||
ypos = bm->cr.ymin;
|
||||
|
||||
if (redraw)
|
||||
{
|
||||
/* Clear screen */
|
||||
text_clear(menu->bitmap);
|
||||
}
|
||||
|
||||
if (title)
|
||||
{
|
||||
if (redraw)
|
||||
text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title);
|
||||
ypos += bm->font->height;
|
||||
}
|
||||
|
||||
#if CONFIG_MENU_SMOOTH
|
||||
static coord_t yoffset = 0;
|
||||
static int old_first_item = 0;
|
||||
static int speed;
|
||||
coord_t old_ymin = bm->cr.ymin;
|
||||
|
||||
/* Clip drawing inside menu items area */
|
||||
gfx_setClipRect(bm,
|
||||
bm->cr.xmin, bm->cr.ymin + ypos,
|
||||
bm->cr.xmax, bm->cr.ymax);
|
||||
|
||||
if (old_first_item != first_item)
|
||||
{
|
||||
/* Speed proportional to distance */
|
||||
speed = ABS(old_first_item - first_item) * 3;
|
||||
|
||||
if (old_first_item > first_item)
|
||||
{
|
||||
yoffset += speed;
|
||||
if (yoffset > bm->font->height)
|
||||
{
|
||||
yoffset = 0;
|
||||
--old_first_item;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yoffset -= speed;
|
||||
if (yoffset < -bm->font->height)
|
||||
{
|
||||
yoffset = 0;
|
||||
++old_first_item;
|
||||
}
|
||||
}
|
||||
first_item = MIN(old_first_item, menu_count(menu));
|
||||
|
||||
ypos += yoffset;
|
||||
redraw = true;
|
||||
}
|
||||
#endif /* CONFIG_MENU_SMOOTH */
|
||||
|
||||
if (redraw) for (i = first_item; /**/; ++i)
|
||||
{
|
||||
const MenuItem *item = &menu->items[i];
|
||||
#if CPU_HARVARD
|
||||
MenuItem ram_item;
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
memcpy_P(&ram_item, item, sizeof(ram_item));
|
||||
item = &ram_item;
|
||||
}
|
||||
#endif /* CPU_HARVARD */
|
||||
|
||||
/* Check for end of room */
|
||||
if (ypos > bm->cr.ymax)
|
||||
break;
|
||||
|
||||
/* Check for end of menu */
|
||||
if (!(item->label || item->hook))
|
||||
break;
|
||||
|
||||
/* Only print visible items */
|
||||
if (!(item->flags & MIF_HIDDEN))
|
||||
{
|
||||
#warning __FILTER_NEXT_WARNING__
|
||||
RenderHook renderhook = (item->flags & MIF_RENDERHOOK) ? (RenderHook)item->label : menu_defaultRenderHook;
|
||||
|
||||
/* Render menuitem */
|
||||
renderhook(menu->bitmap, ypos++, (i == selected), item);
|
||||
|
||||
ypos += bm->font->height;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_MENU_SMOOTH
|
||||
if (redraw)
|
||||
{
|
||||
/* Clear rest of area */
|
||||
gfx_rectClear(bm, bm->cr.xmin, ypos, bm->cr.xmax, bm->cr.ymax);
|
||||
|
||||
menu->lcd_blitBitmap(bm);
|
||||
}
|
||||
|
||||
/* Restore old cliprect */
|
||||
gfx_setClipRect(bm,
|
||||
bm->cr.xmin, old_ymin,
|
||||
bm->cr.xmax, bm->cr.ymax);
|
||||
|
||||
#endif /* CONFIG_MENU_SMOOTH */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle menu item selection
|
||||
*/
|
||||
static iptr_t menu_doselect(const struct Menu *menu, struct MenuItem *item)
|
||||
{
|
||||
iptr_t result = 0;
|
||||
|
||||
/* Exclude other items */
|
||||
int mask, i;
|
||||
for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i)
|
||||
{
|
||||
if (mask & 1)
|
||||
menu->items[i].flags &= ~MIF_CHECKED;
|
||||
}
|
||||
|
||||
if (item->flags & MIF_DISABLED)
|
||||
return MENU_DISABLED;
|
||||
|
||||
/* Handle checkable items */
|
||||
if (item->flags & MIF_TOGGLE)
|
||||
item->flags ^= MIF_CHECKED;
|
||||
else if (item->flags & MIF_CHECKIT)
|
||||
item->flags |= MIF_CHECKED;
|
||||
|
||||
/* Handle items with callback hooks */
|
||||
if (item->hook)
|
||||
{
|
||||
/* Push a jmp buffer to abort the operation with the STOP/CANCEL key */
|
||||
if (!PUSH_ABORT)
|
||||
{
|
||||
result = item->hook(item->userdata);
|
||||
POP_ABORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = item->userdata;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the next visible item (rolls back to the first item)
|
||||
*/
|
||||
static int menu_next_visible_item(const struct Menu *menu, int index)
|
||||
{
|
||||
int total = menu_count(menu);
|
||||
int item_flags;
|
||||
|
||||
do
|
||||
{
|
||||
if (++index >= total)
|
||||
index = 0;
|
||||
|
||||
#if CPU_HARVARD
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
ASSERT(sizeof(menu->items[index].flags) == sizeof(int));
|
||||
item_flags = pgm_read_int(&menu->items[index].flags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
item_flags = menu->items[index].flags;
|
||||
}
|
||||
while (item_flags & MIF_HIDDEN);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the previous visible item (rolls back to the last item)
|
||||
*/
|
||||
static int menu_prev_visible_item(const struct Menu *menu, int index)
|
||||
{
|
||||
int total = menu_count(menu);
|
||||
int item_flags;
|
||||
|
||||
do
|
||||
{
|
||||
if (--index < 0)
|
||||
index = total - 1;
|
||||
|
||||
#if CPU_HARVARD
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
ASSERT(sizeof(menu->items[index].flags) == sizeof(int));
|
||||
item_flags = pgm_read_int(&menu->items[index].flags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
item_flags = menu->items[index].flags;
|
||||
}
|
||||
while (item_flags & MIF_HIDDEN);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a menu and invoke hook functions for the selected menu items.
|
||||
*/
|
||||
iptr_t menu_handle(const struct Menu *menu)
|
||||
{
|
||||
uint8_t items_per_page;
|
||||
uint8_t first_item = 0;
|
||||
uint8_t selected;
|
||||
iptr_t result = 0;
|
||||
bool redraw = true;
|
||||
|
||||
#if (CONFIG_MENU_TIMEOUT != 0)
|
||||
ticks_t now, menu_idle_time = timer_clock();
|
||||
#endif
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
struct MenuBar mb;
|
||||
const_iptr_t labels[] =
|
||||
{
|
||||
(const_iptr_t)LABEL_BACK,
|
||||
(const_iptr_t)LABEL_UPARROW,
|
||||
(const_iptr_t)LABEL_DOWNARROW,
|
||||
(const_iptr_t)0
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize menu bar
|
||||
*/
|
||||
if (menu->flags & MF_TOPLEVEL)
|
||||
labels[0] = (const_iptr_t)LABEL_EMPTY;
|
||||
|
||||
mbar_init(&mb, menu->bitmap, labels, countof(labels));
|
||||
#endif /* CONFIG_MENU_MENUBAR */
|
||||
|
||||
|
||||
items_per_page =
|
||||
(menu->bitmap->height / menu->bitmap->font->height - 1)
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
- 1 /* menu bar labels */
|
||||
#endif
|
||||
- (menu->title ? 1 : 0);
|
||||
|
||||
/* Selected item should be a visible entry */
|
||||
//first_item = selected = menu_next_visible_item(menu, menu->selected - 1);
|
||||
selected = menu->selected;
|
||||
first_item = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
keymask_t key;
|
||||
|
||||
/*
|
||||
* Keep selected item visible
|
||||
*/
|
||||
while (selected < first_item)
|
||||
first_item = menu_prev_visible_item(menu, first_item);
|
||||
while (selected >= first_item + items_per_page)
|
||||
first_item = menu_next_visible_item(menu, first_item);
|
||||
|
||||
menu_layout(menu, first_item, selected, redraw);
|
||||
redraw = false;
|
||||
|
||||
#if CONFIG_MENU_MENUBAR
|
||||
menu_update_menubar(menu, &mb, selected);
|
||||
#endif
|
||||
|
||||
#if CONFIG_MENU_SMOOTH || (CONFIG_MENU_TIMEOUT != 0)
|
||||
key = kbd_peek();
|
||||
cpu_relax();
|
||||
#else
|
||||
key = kbd_get();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_MENU_TIMEOUT != 0)
|
||||
/* Reset idle timer on key press. */
|
||||
now = timer_clock();
|
||||
if (key)
|
||||
menu_idle_time = now;
|
||||
#endif
|
||||
|
||||
if (key & K_OK)
|
||||
{
|
||||
struct MenuItem *item = &(menu->items[selected]);
|
||||
#if CPU_HARVARD
|
||||
MenuItem ram_item;
|
||||
if (menu->flags & MF_ROMITEMS)
|
||||
{
|
||||
memcpy_P(&ram_item, item, sizeof(ram_item));
|
||||
item = &ram_item;
|
||||
}
|
||||
#endif
|
||||
result = menu_doselect(menu, item);
|
||||
redraw = true;
|
||||
|
||||
/* Return immediately */
|
||||
if (!(menu->flags & MF_STICKY))
|
||||
break;
|
||||
|
||||
#if (CONFIG_MENU_TIMEOUT != 0)
|
||||
/* Chain timeout */
|
||||
if ((result == MENU_TIMEOUT) && !(menu->flags & MF_TOPLEVEL))
|
||||
break;
|
||||
|
||||
/* Reset timeout */
|
||||
menu_idle_time = timer_clock();
|
||||
#endif
|
||||
}
|
||||
else if (key & K_UP)
|
||||
{
|
||||
selected = menu_prev_visible_item(menu, selected);
|
||||
redraw = true;
|
||||
}
|
||||
else if (key & K_DOWN)
|
||||
{
|
||||
selected = menu_next_visible_item(menu, selected);
|
||||
redraw = true;
|
||||
}
|
||||
else if (!(menu->flags & MF_TOPLEVEL))
|
||||
{
|
||||
if (key & K_CANCEL)
|
||||
{
|
||||
result = MENU_CANCEL;
|
||||
break;
|
||||
}
|
||||
|
||||
#if CONFIG_MENU_TIMEOUT != 0
|
||||
if (now - menu_idle_time > ms_to_ticks(CONFIG_MENU_TIMEOUT))
|
||||
{
|
||||
result = MENU_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Store currently selected item before leaving. */
|
||||
if (menu->flags & MF_SAVESEL)
|
||||
#warning __FILTER_NEXT_WARNING__
|
||||
CONST_CAST(struct Menu *, menu)->selected = selected;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set flags on a menuitem.
|
||||
*
|
||||
* \param menu Menu owner of the item to change.
|
||||
* \param idx Index of the menu item.
|
||||
* \param flags Bit mask of the flags to set.
|
||||
*
|
||||
* \return Old flags.
|
||||
*/
|
||||
int menu_setFlags(struct Menu *menu, int idx, int flags)
|
||||
{
|
||||
ASSERT(idx < menu_count(menu));
|
||||
ASSERT(!(menu->flags & MF_ROMITEMS));
|
||||
|
||||
int old = menu->items[idx].flags;
|
||||
menu->items[idx].flags |= flags;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear flags on a menuitem.
|
||||
*
|
||||
* \param menu Menu owner of the item to change.
|
||||
* \param idx Index of the menu item.
|
||||
* \param flags Bit mask of the flags to clear.
|
||||
*
|
||||
* \return Old flags.
|
||||
*/
|
||||
int menu_clearFlags(struct Menu *menu, int idx, int flags)
|
||||
{
|
||||
ASSERT(idx < menu_count(menu));
|
||||
ASSERT(!(menu->flags & MF_ROMITEMS));
|
||||
|
||||
int old = menu->items[idx].flags;
|
||||
menu->items[idx].flags &= ~flags;
|
||||
return old;
|
||||
}
|
||||
135
bertos/gui/menu.h
Normal file
135
bertos/gui/menu.h
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2003, 2004, 2006, 2010 Develer S.r.l. (http://www.develer.com/)
|
||||
* Copyright 2000 Bernie Innocenti <bernie@codewiz.org>
|
||||
* All Rights Reserved.
|
||||
* -->
|
||||
*
|
||||
* \defgroup menu Menu handling module
|
||||
* \ingroup gui
|
||||
* \{
|
||||
* \author Bernie Innocenti <bernie@codewiz.org>
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*
|
||||
* \brief Common menu handling API
|
||||
*
|
||||
* $WIZ$ module_name = "menu"
|
||||
* $WIZ$ module_depends = "text", "gfx", "timer", "kbd"
|
||||
*/
|
||||
|
||||
#ifndef GUI_MENU_H
|
||||
#define GUI_MENU_H
|
||||
|
||||
#include <cfg/compiler.h>
|
||||
|
||||
#include <gfx/gfx.h>
|
||||
|
||||
/** Menu callback function */
|
||||
typedef iptr_t (*MenuHook)(iptr_t userdata);
|
||||
typedef void (*BlitBitmap)(const Bitmap *bm);
|
||||
|
||||
/**
|
||||
* Menu item description.
|
||||
*/
|
||||
typedef struct MenuItem
|
||||
{
|
||||
const_iptr_t label; /**< Item label (ID or ptr to string, 0 to disable) */
|
||||
int flags; /**< See MIF_#? definitions below */
|
||||
MenuHook hook; /**< Callback function (NULL to terminate item list) */
|
||||
iptr_t userdata; /**< User data to be passed back to the hook */
|
||||
} MenuItem;
|
||||
|
||||
/** Render hook callback function prototype */
|
||||
typedef void (*RenderHook)(struct Bitmap *bitmap, int ypos, bool selected, const struct MenuItem *item);
|
||||
|
||||
/**
|
||||
* \name Flags for MenuItem.flags.
|
||||
* \{
|
||||
*/
|
||||
#define MIF_EXCLUDE_MASK 0x00FF /**< Mask for mutual exclusion map (shared with priority). */
|
||||
#define MIF_PRI_MASK 0x00FF /**< Mask for priority value (shared with mutual exclusion). */
|
||||
#define MIF_PRI(x) ((x) & MIF_PRI_MASK) /**< Set menu item priority. */
|
||||
#define MIF_EXCLUDE_0 BV(0) /**< Exclude item 0 when this item is checked */
|
||||
#define MIF_EXCLUDE_1 BV(1) /**< Exclude item 1 when this item is checked */
|
||||
#define MIF_EXCLUDE_2 BV(2) /**< Exclude item 2 when this item is checked */
|
||||
#define MIF_EXCLUDE_3 BV(3) /**< Exclude item 3 when this item is checked */
|
||||
#define MIF_EXCLUDE_4 BV(4) /**< Exclude item 4 when this item is checked */
|
||||
#define MIF_EXCLUDE_5 BV(5) /**< Exclude item 5 when this item is checked */
|
||||
#define MIF_EXCLUDE_6 BV(6) /**< Exclude item 6 when this item is checked */
|
||||
#define MIF_EXCLUDE_7 BV(7) /**< Exclude item 7 when this item is checked */
|
||||
#define MIF_CHECKED BV(8) /**< Item is currently checked */
|
||||
#define MIF_CHECKIT BV(9) /**< Automatically check this item when selected */
|
||||
#define MIF_TOGGLE BV(10) /**< Toggle MIF_CHECKED when item is selected */
|
||||
#define MIF_HIDDEN BV(11) /**< This menu item is not visible */
|
||||
#define MIF_DISABLED BV(12) /**< This menu item is not visible */
|
||||
#define MIF_RAMLABEL BV(13) /**< Item label is stored in RAM, not in program memory */
|
||||
#define MIF_RENDERHOOK BV(14) /**< Menu render function is passed in label field */
|
||||
/* \} */
|
||||
|
||||
/**
|
||||
* Menu description.
|
||||
*/
|
||||
typedef struct Menu
|
||||
{
|
||||
MenuItem *items; /**< Array of items (end with a NULL hook) */
|
||||
const_iptr_t title; /**< Menu title (ID or ptr to string, 0 to disable) */
|
||||
int flags; /**< See MF_#? definitions below */
|
||||
struct Bitmap *bitmap; /**< Bitmap where the menu is rendered */
|
||||
int selected; /**< Initial selection (written to if MF_SAVESEL is set). */
|
||||
BlitBitmap lcd_blitBitmap; /**< Callback to call to do smooth the display */
|
||||
} Menu;
|
||||
|
||||
/**
|
||||
* \name Flags for Menu.flags.
|
||||
* \{
|
||||
*/
|
||||
#define MF_STICKY BV(0) /**< Stay in the menu when the items called return */
|
||||
#define MF_TOPLEVEL BV(1) /**< Top-level menu (do not display "back" label) */
|
||||
#define MF_ROMITEMS BV(2) /**< Menu items are stored in ROM (default is RAM) */
|
||||
#define MF_SAVESEL BV(3) /**< Remember the selected item across invocations. */
|
||||
/* \} */
|
||||
|
||||
/**
|
||||
* \name Special result codes for menu_handle().
|
||||
* \{
|
||||
*/
|
||||
#define MENU_OK ((iptr_t)0)
|
||||
#define MENU_CANCEL ((iptr_t)-1)
|
||||
#define MENU_TIMEOUT ((iptr_t)-2)
|
||||
#define MENU_ABORT ((iptr_t)-3)
|
||||
#define MENU_DISABLED ((iptr_t)-4)
|
||||
/* \} */
|
||||
|
||||
/* Function prototypes */
|
||||
iptr_t menu_handle(const struct Menu *menu);
|
||||
int menu_setFlags(struct Menu *menu, int idx, int flags);
|
||||
int menu_clearFlags(struct Menu *menu, int idx, int flags);
|
||||
|
||||
/** \} */ //defgroup menu
|
||||
#endif /* GUI_MENU_H */
|
||||
177
bertos/gui/menubar.c
Normal file
177
bertos/gui/menubar.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
|
||||
* All Rights Reserved.
|
||||
* -->
|
||||
*
|
||||
* \brief Graphics Menu bar widget
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
* \author Francesco Sacchi <batt@develer.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "menubar.h"
|
||||
|
||||
#include <gfx/gfx.h>
|
||||
#include <gfx/text.h>
|
||||
#include <gfx/font.h>
|
||||
#include <cfg/compiler.h>
|
||||
|
||||
#warning FIXME:This module is obsolete, you must refactor it!
|
||||
|
||||
#if 0
|
||||
#if CPU_AVR
|
||||
#include <avr/pgmspace.h> /* strlen_P() */
|
||||
#else
|
||||
#define strlen_P(s) strlen(s)
|
||||
#define text_puts_P(s, b) text_puts(s, b)
|
||||
#define pgm_read_uint16_t(addr) (*(addr))
|
||||
#endif
|
||||
|
||||
#include <string.h> /* strlen, memcpy */
|
||||
|
||||
|
||||
/** Predefined labels */
|
||||
static const pgm_char lab_1[] = "";
|
||||
static const pgm_char lab_2[] = "mute";
|
||||
static const pgm_char lab_3[] = "menu";
|
||||
static const pgm_char lab_4[] = "back";
|
||||
static const pgm_char lab_5[] = " ok ";
|
||||
static const pgm_char lab_6[] = "Ch 1";
|
||||
static const pgm_char lab_7[] = "Ch 2";
|
||||
static const pgm_char lab_8[] = "C1+2";
|
||||
static const pgm_char lab_9[] = " "UP_ARROW" ";
|
||||
static const pgm_char lab_10[] = " "DOWN_ARROW" ";
|
||||
static const pgm_char lab_11[] = " - ";
|
||||
static const pgm_char lab_12[] = " + ";
|
||||
static const pgm_char lab_13[] = "sel ";
|
||||
static const pgm_char lab_14[] = "lock";
|
||||
static const pgm_char lab_15[] = "unlock";
|
||||
static const pgm_char lab_16[] = "more";
|
||||
static const pgm_char lab_17[] = "edit";
|
||||
static const pgm_char lab_18[] = "fast";
|
||||
static const pgm_char lab_19[] = LEFT_ARROW" ";
|
||||
static const pgm_char lab_20[] = " "RIGHT_ARROW;
|
||||
static const pgm_char lab_21[] = "slow";
|
||||
static const pgm_char lab_22[] = "yes";
|
||||
static const pgm_char lab_23[] = "no";
|
||||
|
||||
|
||||
static const pgm_char * PROGMEM label_strings[LABEL_CNT] = {
|
||||
lab_1, lab_2, lab_3, lab_4, lab_5, lab_6, lab_7, lab_8, lab_9,
|
||||
lab_10, lab_11, lab_12, lab_13, lab_14, lab_15, lab_16, lab_17,
|
||||
lab_18, lab_19, lab_20, lab_21, lab_22, lab_23
|
||||
};
|
||||
|
||||
/**
|
||||
* Macro to access a label iptr_t: if a char pointer get the string pointed to
|
||||
* in program memory, otherwise return the corrispondent predefined string
|
||||
* (see label_strings in menubar.c)
|
||||
*/
|
||||
#define PTRLBL(x) ((unsigned int)(x) < 256 ? \
|
||||
(const pgm_char *)pgm_read_uint16_t(label_strings + (unsigned int)(x)) \
|
||||
: (const pgm_char *)(x))
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the MenuBar widget with the bitmap associated,
|
||||
* the label names and the number of labels.
|
||||
*/
|
||||
void mbar_init(
|
||||
struct MenuBar *mb,
|
||||
struct Bitmap *bmp,
|
||||
const_iptr_t labels[],
|
||||
int num_labels)
|
||||
{
|
||||
mb->bitmap = bmp;
|
||||
mb->labels = labels;
|
||||
mb->num_labels = num_labels;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the MenuBar on the bitmap.
|
||||
*/
|
||||
void mbar_draw(const struct MenuBar *mb)
|
||||
{
|
||||
uint8_t oldstyle;
|
||||
int i;
|
||||
size_t maxlen = 0; /* Length of the longest label */
|
||||
coord_t x1, x2, y1, y2, label_padding;
|
||||
|
||||
/* Maximum space available for a label */
|
||||
coord_t slot_width = mb->bitmap->width / mb->num_labels;
|
||||
|
||||
/* Find longest label */
|
||||
for (i = 0; i < mb->num_labels; i++)
|
||||
if (strlen_P(PTRLBL(mb->labels[i])) > maxlen)
|
||||
maxlen = strlen_P(PTRLBL(mb->labels[i]));
|
||||
|
||||
oldstyle = text_style(mb->bitmap, STYLEF_INVERT, STYLEF_MASK);
|
||||
|
||||
/* y coords for menubar: bottom of the bitmap */
|
||||
y1 = mb->bitmap->height - FONT_HEIGHT;
|
||||
y2 = mb->bitmap->height;
|
||||
|
||||
/* Clear menubar area */
|
||||
gfx_rectClear(mb->bitmap, 0, y1, mb->bitmap->width, y2);
|
||||
|
||||
for (i = 0; i < mb->num_labels; i++)
|
||||
{
|
||||
size_t lablen = strlen_P(PTRLBL(mb->labels[i]));
|
||||
|
||||
/* Don't draw empty labels */
|
||||
if (mb->labels[i] == (const_iptr_t)LABEL_EMPTY)
|
||||
continue;
|
||||
|
||||
/* x coords: magic formula for equal distribution of the
|
||||
* labels along bitmap
|
||||
*/
|
||||
label_padding = slot_width - (FONT_WIDTH * lablen + 2);
|
||||
x1 = i * (slot_width + (label_padding / (mb->num_labels - 1)));
|
||||
x2 = x1 + lablen * FONT_WIDTH + 1;
|
||||
|
||||
/* Draw vertical line before.
|
||||
* Uncomment +1 for "rounded" menubars */
|
||||
gfx_line(mb->bitmap, x1, y1 /* + 1 */, x1, y2);
|
||||
|
||||
/* Draw text */
|
||||
text_setCoord(mb->bitmap, x1 + 1, y1);
|
||||
text_puts_P(PTRLBL(mb->labels[i]), mb->bitmap);
|
||||
|
||||
/* Draw vertical line after
|
||||
* Uncomment +1 for "rounded" menubars */
|
||||
gfx_line(mb->bitmap, x2, y1 /* + 1 */, x2, y2);
|
||||
}
|
||||
|
||||
text_style(mb->bitmap, oldstyle, STYLEF_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
97
bertos/gui/menubar.h
Normal file
97
bertos/gui/menubar.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* \file
|
||||
* <!--
|
||||
* This file is part of BeRTOS.
|
||||
*
|
||||
* Bertos 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*
|
||||
* Copyright 2004, 2005, 2008 Develer S.r.l. (http://www.develer.com/)
|
||||
* All Rights Reserved.
|
||||
* -->
|
||||
*
|
||||
* \brief Graphic menu bar widget.
|
||||
*
|
||||
* \author Stefano Fedrigo <aleph@develer.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GUI_MENUBAR_H
|
||||
#define GUI_MENUBAR_H
|
||||
|
||||
#include <cfg/compiler.h>
|
||||
|
||||
/** Predefined labels ids */
|
||||
enum LabelId
|
||||
{
|
||||
LABEL_EMPTY, /* empty label */
|
||||
LABEL_MUTE,
|
||||
LABEL_MENU,
|
||||
LABEL_BACK,
|
||||
LABEL_OK,
|
||||
LABEL_CH_1,
|
||||
LABEL_CH_2,
|
||||
LABEL_C1PLUS2,
|
||||
LABEL_UPARROW,
|
||||
LABEL_DOWNARROW,
|
||||
LABEL_MINUS,
|
||||
LABEL_PLUS,
|
||||
LABEL_SEL,
|
||||
LABEL_LOCK,
|
||||
LABEL_UNLOCK,
|
||||
LABEL_MORE,
|
||||
LABEL_EDIT,
|
||||
LABEL_FAST,
|
||||
LABEL_PREV,
|
||||
LABEL_NEXT,
|
||||
LABEL_SLOW,
|
||||
LABEL_YES,
|
||||
LABEL_NO,
|
||||
|
||||
|
||||
LABEL_CNT
|
||||
};
|
||||
|
||||
#define UP_ARROW "\x18"
|
||||
#define DOWN_ARROW "\x19"
|
||||
#define RIGHT_ARROW "\xC4\x1A"
|
||||
#define LEFT_ARROW "\x10\xC4"
|
||||
|
||||
/* Forward decl */
|
||||
struct Bitmap;
|
||||
|
||||
typedef struct MenuBar
|
||||
{
|
||||
struct Bitmap *bitmap;
|
||||
const_iptr_t *labels;
|
||||
int num_labels;
|
||||
} MenuBar;
|
||||
|
||||
void mbar_init(
|
||||
struct MenuBar *mb,
|
||||
struct Bitmap *bmp,
|
||||
const_iptr_t *labels,
|
||||
int num_labels);
|
||||
void mbar_draw(const struct MenuBar *mb);
|
||||
|
||||
#endif /* GUI_MENUBAR_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue