ui: Some experimental code snippets i cobbled together several months ago.
This commit is contained in:
parent
1198f35283
commit
dcc3a41036
|
@ -0,0 +1,11 @@
|
|||
|
||||
This is some exploratory and experimental code related
|
||||
to the development of a proper lcd-based ui.
|
||||
|
||||
It has been written by Ingo Albrecht <prom@berlin.ccc.de>
|
||||
and, lacking further arrangements, should be considered to
|
||||
be licensed under the GNU GPL v2 or later.
|
||||
|
||||
I have placed this here due to general interest. All of it
|
||||
can safely be removed once we have a proper ui.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#ifndef _UI_DISPLAY_H
|
||||
#define _UI_DISPLAY_H
|
||||
|
||||
#include <ui/pixel.h>
|
||||
#include <ui/image.h>
|
||||
|
||||
/**
|
||||
* Displays - physical display devices
|
||||
*
|
||||
* This layer is introduced tentatively, expecting use
|
||||
* of OSMOCOM on multi-display phones, most likely
|
||||
* with a main screen and a cover screen.
|
||||
*
|
||||
*/
|
||||
struct display {
|
||||
const char *name;
|
||||
|
||||
pxtype_t pixeltype;
|
||||
pxsize_t width;
|
||||
pxsize_t height;
|
||||
|
||||
/* We always operate on an in-memory frame buffer that
|
||||
* can be put on display using damage functions provided
|
||||
* by the image class.
|
||||
*/
|
||||
struct image *fbuf;
|
||||
|
||||
/*
|
||||
* We display a top-level widget.
|
||||
*/
|
||||
struct widget *widget;
|
||||
|
||||
/*
|
||||
* We hold a graphics context, configured for the target
|
||||
* pixel format.
|
||||
*/
|
||||
struct graphics *graphics;
|
||||
|
||||
|
||||
void (*draw) (struct display *display);
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,166 @@
|
|||
|
||||
#ifndef _UI_IMAGE_H
|
||||
#define _UI_IMAGE_H
|
||||
|
||||
/* for exit() */
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ui/pixel.h>
|
||||
#include <ui/font.h>
|
||||
|
||||
struct image {
|
||||
pxtype_t type;
|
||||
pxdims_t size;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
|
||||
struct image font_img_v = {
|
||||
.type = PXTYPE_MONO_V8,
|
||||
.size = {8, 2048},
|
||||
.data = &fontdata_r8x8,
|
||||
};
|
||||
|
||||
struct image font_img_h = {
|
||||
.type = PXTYPE_MONO_H8,
|
||||
.size = {8, 2048},
|
||||
.data = &fontdata_r8x8_horiz,
|
||||
};
|
||||
|
||||
px_t
|
||||
image_get_pixel(struct image *img, pxoff_t x, pxoff_t y) {
|
||||
unsigned stride, base, offset;
|
||||
const uint8_t *p8;
|
||||
const uint16_t *p16;
|
||||
|
||||
switch(img->type) {
|
||||
case PXTYPE_MONO_V8:
|
||||
stride = img->size.w;
|
||||
base = y / 8;
|
||||
offset = y % 8;
|
||||
p8 = (uint8_t*)(img->data + x + base * stride);
|
||||
return px_from_mono(((*p8) >> offset) & 1);
|
||||
case PXTYPE_MONO_H8:
|
||||
stride = img->size.w / 8;
|
||||
base = x / 8;
|
||||
offset = x % 8;
|
||||
p8 = (uint8_t*)(img->data + base + y * stride);
|
||||
return px_from_mono(((*p8) >> offset) & 1);
|
||||
case PXTYPE_RGB444:
|
||||
stride = img->size.w * 2;
|
||||
p16 = (uint16_t*)(img->data + x * 2 + y * stride);
|
||||
return px_from_rgb444(*p16);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
image_set_pixel(struct image *img, pxoff_t x, pxoff_t y, px_t v) {
|
||||
unsigned stride, base, offset;
|
||||
uint8_t *p8;
|
||||
uint16_t *p16;
|
||||
|
||||
switch(img->type) {
|
||||
case PXTYPE_MONO_V8:
|
||||
stride = img->size.w;
|
||||
base = y / 8;
|
||||
offset = y % 8;
|
||||
p8 = (uint8_t*)(img->data + x + base * stride);
|
||||
*p8 |= (px_to_mono(v) << offset);
|
||||
break;
|
||||
case PXTYPE_MONO_H8:
|
||||
stride = img->size.w / 8;
|
||||
base = x / 8;
|
||||
offset = x % 8;
|
||||
p8 = (uint8_t*)(img->data + base + y * stride);
|
||||
*p8 |= (px_to_mono(v) << offset);
|
||||
break;
|
||||
case PXTYPE_RGB444:
|
||||
stride = img->size.w * 2;
|
||||
p16 = (uint16_t*)(img->data + x * 2 + y * stride);
|
||||
*p16 = px_to_rgb444(v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
image_blit(struct image *dst, pxposn_t dstp,
|
||||
struct image *src, pxposn_t srcp,
|
||||
pxdims_t d)
|
||||
{
|
||||
unsigned x, y, s;
|
||||
|
||||
printf("blit %dx%d from %dx%d to %dx%d\n", d.w, d.h, srcp.x, srcp.y, dstp.x, dstp.y);
|
||||
|
||||
// *cough* slow.
|
||||
for(y = 0; y < d.h; y++) {
|
||||
for(x = 0; x < d.w; x++) {
|
||||
px_t p = image_get_pixel(src, srcp.x + x, srcp.y + y);
|
||||
image_set_pixel(dst, dstp.x + x, dstp.y + y, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
image_draw_char(struct image *dst, pxposn_t p, char chr) {
|
||||
unsigned char c = (unsigned char)chr;
|
||||
pxposn_t pf = {0,c*8};
|
||||
pxdims_t d = {8,8};
|
||||
image_blit(dst, p, &font_img_h, pf, d);
|
||||
}
|
||||
|
||||
void
|
||||
image_draw_string(struct image *dst, pxposn_t p, char *str) {
|
||||
while(*str) {
|
||||
image_draw_char(dst, p, *str);
|
||||
p.x += 8;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
image_fill_rect_rgb444(struct image *dst, pxrect_t rect, uint16_t color) {
|
||||
unsigned x, y, s;
|
||||
uint16_t *p;
|
||||
|
||||
unsigned stride = dst->size.w * 2;
|
||||
|
||||
for(y = rect.p.y; y < rect.p.y + rect.d.h; y++) {
|
||||
for(x = rect.p.x; x < rect.p.x + rect.d.w; x++) {
|
||||
p = (uint16_t*)&dst->data[x * 2 + y * stride];
|
||||
*p = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
image_fill_rect(struct image *dst, pxrect_t rect, px_t color)
|
||||
{
|
||||
switch(dst->type) {
|
||||
case PXTYPE_MONO_V8:
|
||||
break;
|
||||
case PXTYPE_MONO_H8:
|
||||
break;
|
||||
case PXTYPE_RGB444:
|
||||
image_fill_rect_rgb444(dst, rect, px_to_rgb444(color));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
image_draw_hline(struct image *dst, pxposn_t posn, pxoff_t len, px_t color)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
image_draw_vline(struct image *dst, pxposn_t posn, pxoff_t len, px_t color)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
image_draw_rect(struct image *dst, pxrect_t rect, px_t color)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
/**
|
||||
* Menus - menus and menu items
|
||||
*
|
||||
* We represent both menus and menu items in a single structure.
|
||||
*
|
||||
* They share the properties of having a title as well as having
|
||||
* interaction callbacks such as on_select.
|
||||
*
|
||||
* Menus have a child item array that is indexed by menu position.
|
||||
* The position of items in this array is used for numeric menu navigation.
|
||||
*
|
||||
*/
|
||||
struct menu {
|
||||
const char *title;
|
||||
void (*on_select)(void);
|
||||
struct menu *children[10];
|
||||
};
|
|
@ -0,0 +1,113 @@
|
|||
|
||||
#ifndef _UI_PIXEL_H
|
||||
#define _UI_PIXEL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/** Supported pixel types */
|
||||
typedef enum {
|
||||
_PXTYPE_INVALID,
|
||||
|
||||
/** "Generic" pixel type (24/32bit RGB) */
|
||||
PXTYPE_GENERIC,
|
||||
|
||||
/** 8 horizontal mono pixels per byte */
|
||||
PXTYPE_MONO_H8,
|
||||
|
||||
/** 8 vertical mono pixels per byte */
|
||||
PXTYPE_MONO_V8,
|
||||
|
||||
/** 12bit RGB444 colors */
|
||||
PXTYPE_RGB444,
|
||||
|
||||
} pxtype_t;
|
||||
|
||||
|
||||
/** Generic pixel type */
|
||||
typedef uint32_t px_t;
|
||||
|
||||
#define PX_R(p) ((uint8_t)((v) >> 16 & 0xFF))
|
||||
#define PX_G(p) ((uint8_t)((v) >> 8 & 0xFF))
|
||||
#define PX_B(p) ((uint8_t)((v) >> 0 / 0xFF))
|
||||
|
||||
#define PX_RGB(r,g,b) ((px_t)((r)<<16|(g)<<8|(b)))
|
||||
|
||||
#define PX_BLACK ((px_t)0x000000)
|
||||
#define PX_RED ((px_t)0xFF0000)
|
||||
#define PX_GREEN ((px_t)0x00FF00)
|
||||
#define PX_BLUE ((px_t)0x0000FF)
|
||||
#define PX_WHITE ((px_t)0xFFFFFF)
|
||||
|
||||
|
||||
/* Mono types */
|
||||
typedef uint8_t px_mono_t;
|
||||
|
||||
#define PX_MONO_BLACK ((px_mono_t)0)
|
||||
#define PX_MONO_WHITE ((px_mono_t)1)
|
||||
|
||||
inline px_t
|
||||
px_from_mono(uint8_t v) {
|
||||
return v ? PX_WHITE : PX_BLACK;
|
||||
}
|
||||
|
||||
inline uint8_t
|
||||
px_to_mono(px_t v) {
|
||||
uint16_t a = (PX_R(v) + PX_G(v) + PX_B(v)) / 3;
|
||||
return (a >= 0x7f) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* RGB444 */
|
||||
typedef uint16_t px_rgb444_t;
|
||||
|
||||
#define PX_RGB444_R(p) ((p) >> 8 & 0xf)
|
||||
#define PX_RGB444_G(p) ((p) >> 4 & 0xf)
|
||||
#define PX_RGB444_B(p) ((p) >> 0 & 0xf)
|
||||
|
||||
#define PX_RGB444_RGB(r,g,b) ((px_rgb444_t)((r)<<8|(g)<<4|(b)))
|
||||
|
||||
inline px_t
|
||||
px_from_rgb444(px_rgb444_t v) {
|
||||
return
|
||||
PX_RGB444_R(v) << 16 | PX_RGB444_R(v) << 20
|
||||
| PX_RGB444_G(v) << 8 | PX_RGB444_G(v) << 12
|
||||
| PX_RGB444_B(v) << 0 | PX_RGB444_B(v) << 4;
|
||||
}
|
||||
|
||||
inline uint16_t
|
||||
px_to_rgb444(px_t v) {
|
||||
uint8_t r = (v >> 20) & 0xF;
|
||||
uint8_t g = (v >> 12) & 0xF;
|
||||
uint8_t b = (v >> 4) & 0xF;
|
||||
|
||||
uint16_t res = (r<< 8) | (g << 4) | (b << 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/** Size in pixels */
|
||||
typedef uint16_t pxsize_t;
|
||||
|
||||
/** Offset in pixels */
|
||||
typedef int16_t pxoff_t;
|
||||
|
||||
/** 2D position in pixels */
|
||||
typedef struct {
|
||||
pxoff_t x;
|
||||
pxoff_t y;
|
||||
} pxposn_t;
|
||||
|
||||
/** 2D dimensions in pixels */
|
||||
typedef struct {
|
||||
pxsize_t w;
|
||||
pxsize_t h;
|
||||
} pxdims_t;
|
||||
|
||||
/** 2D rectangle in pixels */
|
||||
typedef struct {
|
||||
pxposn_t p;
|
||||
pxdims_t d;
|
||||
} pxrect_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <SDL_image.h>
|
||||
|
||||
enum {
|
||||
FORMAT_NONE,
|
||||
FORMAT_C
|
||||
};
|
||||
|
||||
void
|
||||
version(const char *name) {
|
||||
puts(name);
|
||||
//printf("%s rev %s\n", name, REVISION);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void
|
||||
usage(const char *name) {
|
||||
printf("Usage: %s [-hv] [-f outfmt] [-s outsym] <infile> <outfile>\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
int opt, outfmt;
|
||||
const char *outsym = NULL;
|
||||
SDL_Surface *img;
|
||||
|
||||
while((opt = getopt(argc, argv, "f:s:hv")) != -1) {
|
||||
switch(opt) {
|
||||
case 'f':
|
||||
if(!strcmp(optarg, "c")) {
|
||||
outfmt = FORMAT_C;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
outsym = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
version(argv[0]);
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
/**
|
||||
* Screens - full-screen dialogs
|
||||
*
|
||||
* These compose the first level of interaction in the UI.
|
||||
*
|
||||
* There is always exactly one active screen, which is in
|
||||
* control of the entire display on which it is displayed.
|
||||
*
|
||||
* Screen activations are stacked, providing interaction depth.
|
||||
*
|
||||
*/
|
||||
struct screen {
|
||||
const char *name;
|
||||
void (*on_enter)(void);
|
||||
void (*on_leave)(void);
|
||||
void (*on_render)(void);
|
||||
void (*on_key_press)(void);
|
||||
void (*on_key_release)(void);
|
||||
};
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
|
||||
#include <ui/display.h>
|
||||
#include <ui/image.h>
|
||||
#include <ui/sdl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#define SDL_PRIV(d) ((struct sdl_display*)(d)->priv)
|
||||
|
||||
#define REFRESH_INTERVAL_MSEC 50
|
||||
|
||||
struct sdl_display {
|
||||
SDL_Surface *display;
|
||||
SDL_TimerID refresh;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned scale;
|
||||
};
|
||||
|
||||
static Uint32 sdl_redraw_callback(Uint32 interval, void *param) {
|
||||
struct display *display = (struct display*)param;
|
||||
|
||||
display->draw(display);
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
void
|
||||
sdl_init(struct display *display,
|
||||
unsigned width, unsigned height, unsigned scale)
|
||||
{
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)) {
|
||||
printf("Failed to initialize SDL: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
atexit(&SDL_Quit);
|
||||
|
||||
struct sdl_display *priv = SDL_PRIV(display);
|
||||
|
||||
priv->width = width;
|
||||
priv->height = height;
|
||||
priv->scale = scale;
|
||||
|
||||
priv->display = SDL_SetVideoMode(width * scale, height * scale, 32, 0);
|
||||
if(!priv->display) {
|
||||
printf("Failed to set SDL video mode: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
priv->refresh = SDL_AddTimer(REFRESH_INTERVAL_MSEC,
|
||||
&sdl_redraw_callback, display);
|
||||
if(!priv->refresh) {
|
||||
printf("Failed to add refresh timer: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdl_draw(struct display *display)
|
||||
{
|
||||
struct sdl_display *priv = SDL_PRIV(display);
|
||||
|
||||
struct image *img = display->fbuf;
|
||||
|
||||
SDL_Rect r;
|
||||
|
||||
r.w = priv->scale;
|
||||
r.h = priv->scale;
|
||||
|
||||
if(img->type == PXTYPE_RGB444) {
|
||||
unsigned stride = img->size.w * 2;
|
||||
|
||||
unsigned x, y;
|
||||
for(y = 0; y < img->size.h; y++) {
|
||||
for(x = 0; x < img->size.w; x++) {
|
||||
px_t color = image_get_pixel(img, x, y);
|
||||
|
||||
r.x = x * priv->scale;
|
||||
r.y = y * priv->scale;
|
||||
|
||||
SDL_FillRect(priv->display, &r, color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
puts("Unsupported framebuffer type for SDL emulator.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_UpdateRect(priv->display, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static struct sdl_display display_sdl_priv;
|
||||
|
||||
uint8_t sdl_fbuf[96*64*2];
|
||||
|
||||
struct image display_sdl_fbuf = {
|
||||
.type = PXTYPE_RGB444,
|
||||
.size = {96, 64},
|
||||
.data = &sdl_fbuf
|
||||
};
|
||||
|
||||
struct display display_sdl = {
|
||||
.name = "Main Display",
|
||||
.fbuf = &display_sdl_fbuf,
|
||||
.priv = &display_sdl_priv,
|
||||
.draw = &sdl_draw
|
||||
};
|
||||
|
||||
uint16_t fnord_buf[] = {
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF,
|
||||
0x0F00,
|
||||
0x00F0,
|
||||
0x000F,
|
||||
0x00FF
|
||||
|
||||
};
|
||||
|
||||
struct image fnord = {
|
||||
.type = PXTYPE_RGB444,
|
||||
.size = {8,4},
|
||||
.data = &fnord_buf
|
||||
};
|
||||
|
||||
uint8_t fubar_img[] = {
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x0c,
|
||||
0x0d, 0x0e, 0x0f, 0x0f
|
||||
|
||||
};
|
||||
|
||||
struct image fubar = {
|
||||
.type = PXTYPE_MONO_V8,
|
||||
.size = {8,16},
|
||||
.data = &fubar_img
|
||||
};
|
||||
|
||||
void
|
||||
sdl_run(void)
|
||||
{
|
||||
int r;
|
||||
SDL_Event e;
|
||||
|
||||
while((r = SDL_WaitEvent(&e))) {
|
||||
|
||||
if(e.type == SDL_KEYDOWN) {
|
||||
if(e.key.keysym.sym == SDLK_ESCAPE) {
|
||||
puts("Bloody quitter!");
|
||||
break;
|
||||
}
|
||||
if(e.key.keysym.sym == SDLK_SPACE) {
|
||||
pxposn_t dp = {0,0};
|
||||
pxposn_t sp = {0,0};
|
||||
pxdims_t d = {8,4};
|
||||
|
||||
image_blit(&display_sdl_fbuf, dp,
|
||||
&fnord, sp,
|
||||
d);
|
||||
|
||||
sp.x = 0;
|
||||
sp.y = 0;
|
||||
dp.x = 5;
|
||||
dp.y = 10;
|
||||
d.w = 8;
|
||||
d.h = 16;
|
||||
|
||||
image_blit(&display_sdl_fbuf, dp,
|
||||
&fubar, sp,
|
||||
d);
|
||||
|
||||
pxrect_t r = {{12,0},{40,20}};
|
||||
image_fill_rect(&display_sdl_fbuf,
|
||||
r,
|
||||
0xFF00FF);
|
||||
|
||||
|
||||
#if 0
|
||||
dp.x = 0;
|
||||
dp.y = 0;
|
||||
|
||||
image_draw_string(&display_sdl_fbuf, dp,
|
||||
"ABCDEFGHI");
|
||||
|
||||
dp.y += 10;
|
||||
|
||||
image_draw_string(&display_sdl_fbuf, dp,
|
||||
"abcdefghi");
|
||||
|
||||
#endif
|
||||
|
||||
sdl_draw(&display_sdl);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
switch(e.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
printf("Key %d %d\n", e.key.keysym.sym, e.key.state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!r) {
|
||||
printf("Failed to wait for SDL event: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
sdl_init(&display_sdl, 96, 64, 4);
|
||||
|
||||
sdl_run();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
#ifndef _UI_SDL_H
|
||||
#define _UI_SDL_H
|
||||
|
||||
#include <ui/display.h>
|
||||
|
||||
extern struct display display_sdl;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
/****** MESSAGING MENU ******/
|
||||
|
||||
struct menu menu_message_compose = {
|
||||
.title = "Compose",
|
||||
.help = "Write a new text message."
|
||||
};
|
||||
|
||||
struct menu menu_message_inbox = {
|
||||
.title = "Inbox",
|
||||
.help = "Incoming text messages"
|
||||
};
|
||||
|
||||
struct menu menu_message_outbox = {
|
||||
.title = "Outbox",
|
||||
.help = "Outgoing text messages"
|
||||
};
|
||||
|
||||
struct menu menu_message_sent = {
|
||||
.title = "Sent",
|
||||
.help = "Previously sent text messages"
|
||||
};
|
||||
|
||||
struct menu menu_messages = {
|
||||
.title = "Messages",
|
||||
.help = "Short message service options",
|
||||
.children = {
|
||||
[0] = &menu_message_compose,
|
||||
[1] = &menu_message_inbox,
|
||||
[2] = &menu_message_outbox,
|
||||
[3] = &menu_message_sent
|
||||
}
|
||||
};
|
||||
|
||||
/****** NETWORK MENU ******/
|
||||
|
||||
struct menu menu_network_about = {
|
||||
.title = "About this network",
|
||||
.help = "Information about your current network",
|
||||
};
|
||||
|
||||
struct menu menu_network = {
|
||||
.title = "Network",
|
||||
.help = "Network interaction options",
|
||||
.children = {
|
||||
}
|
||||
};
|
||||
|
||||
/****** SETTINGS MENU ******/
|
||||
|
||||
struct menu menu_settings = {
|
||||
.title = "Settings",
|
||||
.help = "Configure your phone",
|
||||
.children = {
|
||||
}
|
||||
};
|
||||
|
||||
/****** MAIN MENU ******/
|
||||
|
||||
struct menu menu_about = {
|
||||
.title = "About",
|
||||
.help = "Information about this phone",
|
||||
};
|
||||
|
||||
struct menu menu_main = {
|
||||
.title = "Main Menu",
|
||||
.children = {
|
||||
[0] = &menu_messages,
|
||||
[7] = &menu_network,
|
||||
[8] = &menu_settings,
|
||||
[9] = &menu_about,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(void) {
|
||||
&menu_main;
|
||||
return 0;
|
||||
};
|
Loading…
Reference in New Issue