BeRTOS
leveledit.c
Go to the documentation of this file.
00001 
00038 #include "leveledit.h"
00039 
00040 #include "cfg/cfg_menu.h"
00041 #include <cfg/macros.h> /* MAX() */
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     /* Labels for menubars */
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 /* CONFIG_MENU_MENUBAR */
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     // Allow keys repetition.
00087     old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
00088 
00089     text_clear(lev->bitmap);
00090     //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE);
00091     text_puts(lev->title, lev->bitmap);
00092     //text_style(0, STYLEF_UNDERLINE);
00093 
00094     if (lev->type & LEVELEDIT_DOUBLE)
00095     {
00096         int chn = 0;  /* edit both channels */
00097 
00098         /* Levelbars init */
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 /* CONFIG_MENU_MENUBAR */
00109 
00110         /* Input loop for double level setting */
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                         /* Accept input implicitly */
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 /* CONFIG_MENU_MENUBAR */
00154             }
00155 
00156             /* Increment step to achieve greater accelerations on larger values */
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                     /* If changing both channels (chn == 0), don't change
00167                      * level if one of two is at min or max */
00168                     if (chn != 0 ||
00169                             (*lev->ch1_val + step <= lev->max
00170                              && *lev->ch2_val + step <= lev->max))
00171                     {
00172                         /* If chn == 0 change both channels */
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         } // end for(;;)
00212     }
00213     else
00214     {
00215         const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
00216 
00217 /*
00218         const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit),
00219                         PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit));
00220 
00221         const coord_t barlen = lev->bitmap->width - 6 - textw;
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 /* CONFIG_MENU_MENUBAR */
00233 
00234         /* Input loop for single level setting */
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                         /* Accept input implicitly */
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             /* Increment step to achieve greater accelerations on larger values */
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 }