00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <avr/pgmspace.h>
00021 #include <inttypes.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include "net/presentation.h"
00025 #include "main/menu.h"
00026 #include "main/rom.h"
00027 #include "main/lcd.h"
00028 #include "main/keys.h"
00029 #include "utils.h"
00030
00031 #include "main/switch.h"
00032 #include "main/dimmer.h"
00033
00034 #define MAX_CHILDS 8
00035
00041 class Label : public VisibleObject {
00042 private:
00043 char *text;
00044
00045 public:
00046 bool Activate(void);
00047 void Display(void);
00048 void LoadProperties(uint8_t tag);
00049 };
00050
00051
00057 class Icon : public VisibleObject {
00058 private:
00059 PGM_VOID_P image;
00060
00061 public:
00062 bool Activate(void);
00063 void Display(void);
00064 void LoadProperties(uint8_t tag);
00065 };
00066
00067
00068 static VisibleObject* root;
00069 static VisibleObject* callbacks[6];
00070
00071 static VisibleObject* menu_factory(uint8_t id)
00072 {
00073 switch (id) {
00074 case 0: return new Container;
00075 case 1: return new Label;
00076 case 2: return new Icon;
00077 case 3: return new Switch;
00078 case 4: return new Dimmer;
00079 default: return NULL;
00080 }
00081 }
00082
00083
00084
00085
00086
00093 bool VisibleObject::Activate(void)
00094 {
00095 active = 1;
00096 return true;
00097 }
00098
00102 void VisibleObject::Deactivate(void)
00103 {
00104 active = 0;
00105 }
00106
00116 void VisibleObject::LoadProperties(uint8_t tag)
00117 {
00118 switch (tag) {
00119 case P_TAG_X|P_TYPE_CHAR:
00120 x = prs_get_char();
00121 break;
00122 case P_TAG_Y|P_TYPE_CHAR:
00123 y = prs_get_char();
00124 break;
00125 default:
00126 prs_skip(tag);
00127 break;
00128 }
00129 }
00130
00137 bool VisibleObject::Shift(uint8_t dir)
00138 {
00139 return false;
00140 }
00141
00148 void VisibleObject::KeyCallback(uint8_t key)
00149 {
00150 }
00151
00152
00153
00154
00155
00160 Container::Container(void)
00161 {
00162 childs = new (VisibleObject*)[MAX_CHILDS];
00163 }
00164
00171 bool Container::Activate(void)
00172 {
00173
00174 if (count > 0) {
00175 if (childs[current]->Activate()) {
00176 return VisibleObject::Activate();
00177 } else {
00178 return false;
00179 }
00180 } else {
00181 return false;
00182 }
00183 }
00184
00185 void Container::Deactivate(void)
00186 {
00187 VisibleObject::Deactivate();
00188
00189
00190 if (count > 0) childs[current]->Deactivate();
00191 }
00192
00196 void Container::Display(void)
00197 {
00198 uint8_t n = count;
00199 VisibleObject **child = childs;
00200
00201 while (n > 0) {
00202 (*child)->Display();
00203 child++;
00204 n--;
00205 }
00206 }
00207
00208 void Container::LoadProperties(uint8_t tag)
00209 {
00210 if ((tag&P_TYPE_MASK) == P_TYPE_COMPOUND_OPEN) {
00211 VisibleObject *newObj;
00212
00213
00214 newObj = menu_factory(tag>>3);
00215 AddChild(newObj);
00216
00217
00218 while (((tag = prs_get_tag()) & P_TYPE_MASK) != P_TYPE_COMPOUND_CLOSE)
00219 newObj->LoadProperties(tag);
00220 } else {
00221
00222 VisibleObject::LoadProperties(tag);
00223 }
00224 }
00225
00233 bool Container::Shift(uint8_t dir)
00234 {
00235 VisibleObject *child;
00236 uint8_t ind;
00237
00238
00239 child = childs[current];
00240 if (child->Shift(dir)) return true;
00241
00242
00243 ind = current;
00244 child->Deactivate();
00245 child->Display();
00246 do {
00247 if (dir) {
00248 if (ind >= count-1) {
00249 child = childs[current];
00250 child->Activate();
00251 child->Display();
00252 return false;
00253 } else {
00254 ind++;
00255 }
00256 } else {
00257 if (ind == 0) {
00258 child = childs[current];
00259 child->Activate();
00260 child->Display();
00261 return false;
00262 } else {
00263 ind--;
00264 }
00265 }
00266 child = childs[ind];
00267 } while (!child->Activate());
00268
00269 child->Display();
00270 current = ind;
00271 return true;
00272 }
00273
00274 void Container::AddChild(VisibleObject *child)
00275 {
00276 childs[count++] = child;
00277 }
00278
00279
00280
00281
00282
00286 bool Label::Activate(void)
00287 {
00288 return false;
00289 }
00290
00291 void Label::Display(void)
00292 {
00293 if (text != NULL) lcd_print(x, y, 0, text);
00294 }
00295
00296 void Label::LoadProperties(uint8_t tag)
00297 {
00298 if (tag == (P_TAG_DEFAULT|P_TYPE_STRING)) {
00299 if (text != NULL) free(text);
00300 text = (char*)malloc(strlen(prs_get_str())+1);
00301 strcpy(text, prs_get_str());
00302 } else {
00303 VisibleObject::LoadProperties(tag);
00304 }
00305 }
00306
00307
00308
00309
00310
00314 bool Icon::Activate(void)
00315 {
00316 return false;
00317 }
00318
00319 void Icon::Display(void)
00320 {
00321 if (image != NULL) lcd_put_image(x, y, (PGM_P)image);
00322 }
00323
00324 void Icon::LoadProperties(uint8_t tag)
00325 {
00326 if (tag == (P_TAG_IMAGE|P_TYPE_CHAR)) {
00327 switch (prs_get_char()) {
00328 case 0: image = &i_main_menu; break;
00329 }
00330 } else {
00331 VisibleObject::LoadProperties(tag);
00332 }
00333 }
00334
00335
00336
00337
00338
00345 extern "C" void menu_init(void)
00346 {
00347 uint8_t *buf;
00348 uint8_t tag;
00349
00350 buf = (uint8_t*)malloc(255);
00351 memcpy_P(buf, &e_menu, 255);
00352 prs_init(buf, 255);
00353
00354
00355 tag = prs_get_tag();
00356 root = menu_factory(tag>>3);
00357 while (((tag = prs_get_tag()) & P_TYPE_MASK) != P_TYPE_COMPOUND_CLOSE)
00358 root->LoadProperties(tag);
00359
00360 free(buf);
00361
00362 lcd_put_image(0, 0, i_main_menu);
00363 if (!root->Activate()) root->Shift(1);
00364 root->Display();
00365 }
00366
00372 extern "C" void menu_process(void)
00373 {
00374 if (keys_key_pressed()) {
00375 uint8_t key = keys_get_key();
00376 switch (key) {
00377 case KEY_FUNC_1:
00378 if (callbacks[0] != NULL)
00379 callbacks[0]->KeyCallback(0);
00380 break;
00381 case KEY_FUNC_2:
00382 if (callbacks[1] != NULL)
00383 callbacks[1]->KeyCallback(1);
00384 break;
00385 case KEY_FUNC_3:
00386 if (callbacks[2] != NULL)
00387 callbacks[2]->KeyCallback(2);
00388 break;
00389 case KEY_FUNC_4:
00390 if (callbacks[3] != NULL)
00391 callbacks[3]->KeyCallback(3);
00392 break;
00393 case KEY_FUNC_5:
00394 if (callbacks[4] != NULL)
00395 callbacks[4]->KeyCallback(4);
00396 break;
00397 case KEY_FUNC_6:
00398 if (callbacks[5] != NULL)
00399 callbacks[5]->KeyCallback(5);
00400 break;
00401 case KEY_MENU_UP:
00402 root->Shift(0);
00403 break;
00404 case KEY_MENU_DOWN:
00405 root->Shift(1);
00406 break;
00407 }
00408 }
00409 }
00410
00421 void menu_set_hook(uint8_t index, PGM_VOID_P image, VisibleObject* obj)
00422 {
00423 callbacks[index] = obj;
00424 lcd_put_image(8+index*20, 56, (PGM_P)image);
00425 }
00426
00432 void menu_remove_hook(uint8_t index)
00433 {
00434 callbacks[index] = NULL;
00435 lcd_put_image(8+index*20, 56, i_tray_empty);
00436 }