00001
00038 #include "leveledit.h"
00039
00040 #include "cfg/cfg_menu.h"
00041 #include <cfg/macros.h>
00042
00043 #include <drv/kbd.h>
00044 #include <drv/timer.h>
00045
00046 #include <gui/levelbar.h>
00047
00048 #include <cpu/pgm.h>
00049
00050 #include <gfx/text.h>
00051 #include <gfx/font.h>
00052
00053 #if CONFIG_MENU_MENUBAR
00054 #include <gui/menubar.h>
00055 #endif
00056
00057 #warning FIXME: Revise me!
00058
00059 #define LBAR_HEIGHT 16
00060
00064 void level_edit(struct LevelEdit *lev)
00065 {
00066 #if CONFIG_MENU_MENUBAR
00067
00068 enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 };
00069 const_iptr_t labels[] =
00070 {
00071 (const_iptr_t)LABEL_BACK,
00072 (const_iptr_t)LABEL_MINUS,
00073 (const_iptr_t)LABEL_PLUS,
00074 (const_iptr_t)LABEL_EMPTY
00075 };
00076 struct MenuBar mb;
00077 #endif
00078
00079 struct LevelBar bar1, bar2;
00080 keymask_t keys, old_rpt_mask;
00081 int step, rep_step;
00082
00083 rep_step = MAX(lev->step, ((lev->max - lev->min) / 200));
00084 step = lev->step;
00085
00086
00087 old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
00088
00089 text_clear(lev->bitmap);
00090
00091 text_puts(lev->title, lev->bitmap);
00092
00093
00094 if (lev->type & LEVELEDIT_DOUBLE)
00095 {
00096 int chn = 0;
00097
00098
00099 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
00100 lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23);
00101 lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL,
00102 lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23);
00103
00104 #if CONFIG_MENU_MENUBAR
00105 labels[3] = (const_iptr_t)ch_labels[chn];
00106 mbar_init(&mb, lev->bitmap, labels, countof(labels));
00107 mbar_draw(&mb);
00108 #endif
00109
00110
00111 for (;;)
00112 {
00113 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00114 ticks_t idle_timeout = timer_clock();
00115 #endif
00116 do
00117 {
00118 if (lev->display_hook)
00119 lev->display_hook(lev);
00120 else
00121 {
00122 text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit);
00123 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val);
00124 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val);
00125
00126 lbar_setLevel(&bar1, *lev->ch1_val);
00127 lbar_setLevel(&bar2, *lev->ch2_val);
00128 lbar_draw(&bar1);
00129 lbar_draw(&bar2);
00130 }
00131
00132 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00133 if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT))
00134 {
00135
00136 keys = K_OK;
00137 break;
00138 }
00139 #endif
00140 }
00141 while (!(keys = kbd_peek()));
00142
00143 if (keys & K_CANCEL)
00144 break;
00145
00146 if (keys & K_OK)
00147 {
00148 chn = (chn + 1) % 3;
00149
00150 #if CONFIG_MENU_MENUBAR
00151 labels[3] = (const_iptr_t)ch_labels[chn];
00152 mbar_draw(&mb);
00153 #endif
00154 }
00155
00156
00157 if (keys & K_REPEAT)
00158 step = MIN(rep_step, step + 1);
00159 else
00160 step = lev->step;
00161
00162 if (keys & (K_UP | K_DOWN))
00163 {
00164 if (keys & K_UP)
00165 {
00166
00167
00168 if (chn != 0 ||
00169 (*lev->ch1_val + step <= lev->max
00170 && *lev->ch2_val + step <= lev->max))
00171 {
00172
00173 if (chn != 2)
00174 {
00175 *lev->ch1_val += step;
00176 if (*lev->ch1_val > lev->max)
00177 *lev->ch1_val = lev->max;
00178 }
00179 if (chn != 1)
00180 {
00181 *lev->ch2_val += step;
00182 if (*lev->ch2_val > lev->max)
00183 *lev->ch2_val = lev->max;
00184 }
00185 }
00186 }
00187 else
00188 {
00189 if (chn != 0 ||
00190 (*lev->ch1_val - step >= lev->min
00191 && *lev->ch2_val - step >= lev->min))
00192 {
00193 if (chn != 2)
00194 {
00195 *lev->ch1_val -= step;
00196 if (*lev->ch1_val < lev->min)
00197 *lev->ch1_val = lev->min;
00198 }
00199 if (chn != 1)
00200 {
00201 *lev->ch2_val -= step;
00202 if (*lev->ch2_val < lev->min)
00203 *lev->ch2_val = lev->min;
00204 }
00205 }
00206 }
00207
00208 if (lev->set_hook)
00209 lev->set_hook();
00210 }
00211 }
00212 }
00213 else
00214 {
00215 const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
00216
00217
00218
00219
00220
00221
00222
00223 const coord_t barlen = lev->bitmap->width;
00224 const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height;
00225 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
00226 lev->min, lev->max, *lev->ch1_val,
00227 0, barvtop, barlen, barvtop + LBAR_HEIGHT);
00228
00229 #if CONFIG_MENU_MENUBAR
00230 mbar_init(&mb, lev->bitmap, labels, countof(labels));
00231 mbar_draw(&mb);
00232 #endif
00233
00234
00235 for (;;)
00236 {
00237 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00238 ticks_t idle_timeout = timer_clock();
00239 #endif
00240 do
00241 {
00242 if (lev->display_hook)
00243 lev->display_hook(lev);
00244 else
00245 {
00246 if (lev->type != LEVELEDIT_NOBAR)
00247 {
00248 lbar_setLevel(&bar1, *lev->ch1_val);
00249 lbar_draw(&bar1);
00250 }
00251 PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height,
00252 TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit);
00253 }
00254
00255 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00256 if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT)
00257 {
00258
00259 keys = K_CANCEL;
00260 break;
00261 }
00262 #endif
00263
00264 }
00265 while (!(keys = kbd_peek()));
00266
00267 if (keys & K_CANCEL)
00268 break;
00269
00270
00271 if (keys & K_REPEAT)
00272 step = MIN(rep_step, step + 1);
00273 else
00274 step = lev->step;
00275
00276 if (keys & K_UP)
00277 {
00278 *lev->ch1_val += step;
00279 if (*lev->ch1_val > lev->max)
00280 *lev->ch1_val = lev->max;
00281 }
00282
00283 if (keys & K_DOWN)
00284 {
00285 *lev->ch1_val -= step;
00286 if (*lev->ch1_val < lev->min)
00287 *lev->ch1_val = lev->min;
00288 }
00289
00290 if (lev->set_hook)
00291 lev->set_hook();
00292 }
00293 }
00294
00295 kbd_setRepeatMask(old_rpt_mask);
00296 }
00297
00302 void level_init(struct LevelEdit *lev,
00303 int type,
00304 struct Bitmap *bmp, const char *title, const char *unit,
00305 int min, int max, int step,
00306 int *ch1_val, int *ch2_val,
00307 level_set_callback *set_hook, display_callback *display_hook)
00308 {
00309 lev->type = type;
00310 lev->bitmap = bmp;
00311 lev->title = title;
00312 lev->unit = unit;
00313 lev->min = min;
00314 lev->max = max;
00315 lev->step = step;
00316
00317 lev->ch1_val = ch1_val;
00318 lev->ch2_val = ch2_val;
00319 lev->set_hook = set_hook;
00320 lev->display_hook = display_hook;
00321 }