Add menubar.
[bertos.git] / bertos / gui / menubar.c
1 /**
2  * \file
3  * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
4  * All Rights Reserved.
5  *
6  * \version $Id$
7  *
8  * \author Stefano Fedrigo <aleph@develer.com>
9  * \author Francesco Sacchi <batt@develer.com>
10  *
11  * \brief Graphics Menu bar widget
12  */
13
14 #include "menubar.h"
15
16 #include <gfx/gfx.h>
17 #include <gfx/text.h>
18 #include <gfx/font.h>
19 #include <cfg/compiler.h>
20
21 #if CPU_AVR
22         #include <avr/pgmspace.h> /* strlen_P() */
23 #else
24         #define strlen_P(s)             strlen(s)
25         #define text_puts_P(s, b)       text_puts(s, b)
26         #define pgm_read_uint16_t(addr) (*(addr))
27 #endif
28
29 #include <string.h> /* strlen, memcpy */
30
31
32 /** Predefined labels */
33 static const pgm_char lab_1[]  = "";
34 static const pgm_char lab_2[]  = "mute";
35 static const pgm_char lab_3[]  = "menu";
36 static const pgm_char lab_4[]  = "back";
37 static const pgm_char lab_5[]  = " ok ";
38 static const pgm_char lab_6[]  = "Ch 1";
39 static const pgm_char lab_7[]  = "Ch 2";
40 static const pgm_char lab_8[]  = "C1+2";
41 static const pgm_char lab_9[]  = " "UP_ARROW" ";
42 static const pgm_char lab_10[] = " "DOWN_ARROW" ";
43 static const pgm_char lab_11[] = " - ";
44 static const pgm_char lab_12[] = " + ";
45 static const pgm_char lab_13[] = "sel ";
46 #if OEM_BRAND == OEM_CLAIRBROS
47 static const pgm_char lab_14[] = "gain";
48 #else
49 static const pgm_char lab_14[] = "lock";
50 #endif
51 static const pgm_char lab_15[] = "unlock";
52 static const pgm_char lab_16[] = "more";
53 static const pgm_char lab_17[] = "edit";
54 static const pgm_char lab_18[] = "fast";
55 static const pgm_char lab_19[] = LEFT_ARROW" ";
56 static const pgm_char lab_20[] = " "RIGHT_ARROW;
57 static const pgm_char lab_21[] = "slow";
58 static const pgm_char lab_22[] = "yes";
59 static const pgm_char lab_23[] = "no";
60
61
62 static const pgm_char * PROGMEM label_strings[LABEL_CNT] = {
63         lab_1, lab_2, lab_3, lab_4, lab_5, lab_6, lab_7, lab_8, lab_9,
64         lab_10, lab_11, lab_12, lab_13, lab_14, lab_15, lab_16, lab_17,
65         lab_18, lab_19, lab_20, lab_21, lab_22, lab_23
66 };
67
68 /**
69  * Macro to access a label iptr_t: if a char pointer get the string pointed to
70  * in program memory, otherwise return the corrispondent predefined string
71  * (see label_strings in menubar.c)
72  */
73 #define PTRLBL(x) ((unsigned int)(x) < 256 ? \
74         (const pgm_char *)pgm_read_uint16_t(label_strings + (unsigned int)(x)) \
75         : (const pgm_char *)(x))
76
77
78 /**
79  * Initialize the MenuBar widget with the bitmap associated,
80  * the label names and the number of labels.
81  */
82 void mbar_init(
83                 struct MenuBar *mb,
84                 struct Bitmap *bmp,
85                 const_iptr_t labels[],
86                 int num_labels)
87 {
88         mb->bitmap     = bmp;
89         mb->labels     = labels;
90         mb->num_labels = num_labels;
91 }
92
93
94 /**
95  * Render the MenuBar on the bitmap.
96  */
97 void mbar_draw(const struct MenuBar *mb)
98 {
99         uint8_t oldstyle;
100         int i;
101         size_t maxlen = 0;  /* Length of the longest label */
102         coord_t x1, x2, y1, y2, label_padding;
103
104         /* Maximum space available for a label */
105         coord_t slot_width = mb->bitmap->width / mb->num_labels;
106
107         /* Find longest label */
108         for (i = 0; i < mb->num_labels; i++)
109                 if (strlen_P(PTRLBL(mb->labels[i])) > maxlen)
110                         maxlen = strlen_P(PTRLBL(mb->labels[i]));
111
112         oldstyle = text_style(mb->bitmap, STYLEF_INVERT, STYLEF_MASK);
113
114         /* y coords for menubar: bottom of the bitmap */
115         y1 = mb->bitmap->height - FONT_HEIGHT;
116         y2 = mb->bitmap->height;
117
118         /* Clear menubar area */
119         gfx_rectClear(mb->bitmap, 0, y1, mb->bitmap->width, y2);
120
121         for (i = 0; i < mb->num_labels; i++)
122         {
123                 size_t lablen = strlen_P(PTRLBL(mb->labels[i]));
124
125                 /* Don't draw empty labels */
126                 if (mb->labels[i] == (const_iptr_t)LABEL_EMPTY)
127                         continue;
128
129                 /* x coords: magic formula for equal distribution of the
130                  * labels along bitmap
131                  */
132                 label_padding = slot_width - (FONT_WIDTH * lablen + 2);
133                 x1 = i * (slot_width + (label_padding / (mb->num_labels - 1)));
134                 x2 = x1 + lablen * FONT_WIDTH + 1;
135
136                 /* Draw vertical line before.
137                  * Uncomment +1 for "rounded" menubars */
138                 gfx_line(mb->bitmap, x1, y1 /* + 1 */, x1, y2);
139
140                 /* Draw text */
141                 text_setCoord(mb->bitmap, x1 + 1, y1);
142                 text_puts_P(PTRLBL(mb->labels[i]), mb->bitmap);
143
144                 /* Draw vertical line after
145                  * Uncomment +1 for "rounded" menubars */
146                 gfx_line(mb->bitmap, x2, y1 /* + 1 */, x2, y2);
147         }
148
149         text_style(mb->bitmap, oldstyle, STYLEF_MASK);
150 }