Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members

menu.cc

00001 /***
00002  * This file is part of OpenHome, an open source home automation system.
00003  * Copyright (C) 2003 Jan Klötzke
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  * VisibleObject
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  * Container
00154  */
00155 
00160 Container::Container(void)
00161 {
00162         childs = new (VisibleObject*)[MAX_CHILDS]; // malloc(MAX_CHILDS*2);
00163 }
00164 
00171 bool Container::Activate(void)
00172 {
00173         // only call if child exists
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         // only call if child exists
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                 // create new object
00214                 newObj = menu_factory(tag>>3);
00215                 AddChild(newObj);
00216 
00217                 // feed new object with it's properties
00218                 while (((tag = prs_get_tag()) & P_TYPE_MASK) != P_TYPE_COMPOUND_CLOSE)
00219                         newObj->LoadProperties(tag);
00220         } else {
00221                 // tag not handled here
00222                 VisibleObject::LoadProperties(tag);
00223         }
00224 }
00225 
00233 bool Container::Shift(uint8_t dir)
00234 {
00235         VisibleObject *child;
00236         uint8_t ind;
00237 
00238         // call child
00239         child = childs[current];
00240         if (child->Shift(dir)) return true;
00241 
00242         // change focus locally or revert to higher level
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  * Label
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  * Icon
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  * Global functions.
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         // create new root object
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 }

Generated on Thu Oct 16 13:13:41 2003 for OpenHomeMainPanel by doxygen 1.3.3