source: npl/mediabox/lcdproc_edwin/src/server/menu.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2  menu.c
3
4  Handles server-supplied menus defined by a table.  Read menu.h for
5  more information.
6
7  Menus are similar to "pull-down" menus, but have some extra features.
8  They can contain "normal" menu items, checkboxes, sliders, "movers",
9  etc..
10 
11  I should probably find a more elegant way of doing this in order
12  to handle dynamically-changing menus such as the client list.  Tcl/Tk
13  has neat ways to do it.  Hmm...
14 
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#include <unistd.h>
21
22#include "parse.h"
23#include "sock.h"
24#include "render.h"
25#include "main.h"
26
27#include "drivers/lcd.h"
28#include "menu.h"
29
30// FIXME: Implement this where it is supposed to be...
31#include <time.h>
32void framedelay()
33{
34   sock_poll_clients();
35   parse_all_client_messages();
36
37   usleep(TIME_UNIT);
38}
39
40static void draw_heartbeat()
41{
42   static int timer = 0;
43   
44   if(heartbeat)
45   {
46         // Set this to pulsate like a real heart beat...
47         // (binary is fun...  :)
48         lcd.icon(!((timer+4)&5), 0);
49         lcd.chr(lcd.wid, 1, 0);
50   }
51   lcd.flush();
52
53   timer++;
54   timer &= 0x0f;
55}
56
57static int PAD = 255;
58
59
60
61typedef struct menu_info
62{
63  int selected;
64  int length;
65} menu_info;
66
67
68
69static int draw_menu(Menu menu, menu_info *info);
70static int fill_menu_info(Menu menu, menu_info *info);
71static int menu_handle_action(menu_item *item);
72
73static int slid_func(menu_item *item);
74
75
76int do_menu(Menu menu)
77{
78  menu_info info;
79  int key=0;
80  int status=MENU_OK;
81  int done=0;
82
83  int (*func)();
84  int (*readfunc)(int);
85 
86
87  if(!menu) return MENU_ERROR;
88
89  fill_menu_info(menu, &info);
90
91
92  while(!done)
93  {
94     // Keep the cursor off titles... (?)
95     while(menu[info.selected].type == TYPE_TITL)
96     {
97        info.selected++;
98        // If the title is the last thing in the menu...
99        if(!menu[info.selected].text) info.selected -= 2;
100     }
101   
102     
103     draw_menu(menu, &info);
104
105     // FIXME: This should use a better keypress interface, which
106     // FIXME: handles things according to keybindings...
107
108     for(key = lcd.getkey(); key==0; key = lcd.getkey())
109     {
110        // sleep for 1/8th second...
111        framedelay();
112        // do the heartbeat...
113        draw_heartbeat();
114        // Check for client input...
115     }
116     
117   
118     // Handle the key according to the keybindings...
119     switch(key)
120     {
121        case 'D': done=1; break;
122        case 'B': if(info.selected > 0) info.selected--;
123           while(menu[info.selected].type == TYPE_TITL)
124           {
125              if(info.selected > 0)
126                 info.selected--;
127              else break;
128           }
129           break;
130        case 'C': if(menu[info.selected+1].text) info.selected++; break;
131        case 'A':
132           switch(menu[info.selected].type)
133           {
134              case TYPE_MENU: status = do_menu(menu[info.selected].data);
135                 break;
136              case TYPE_FUNC:
137                 func = menu[info.selected].data;
138                 if(func)
139                    status = func();
140                 break;
141              case TYPE_CHEK:
142                 readfunc = menu[info.selected].data;
143                 if(readfunc)
144                    status = readfunc(MENU_CHECK);
145                 status &= 0xffff0000;
146                 break;
147              case TYPE_SLID:
148                 func = menu[info.selected].data;
149                 if(func)
150                    status = slid_func(&menu[info.selected]);
151                 break;
152              default:
153                 break;
154           }
155           
156           switch(status)
157           {
158              case MENU_OK:
159                 break;
160              case MENU_CLOSE:
161                 return MENU_OK;
162              case MENU_QUIT:
163                 return MENU_QUIT;
164//        case MENU_KILL:
165//          return MENU_KILL;
166              case MENU_ERROR:
167                 return MENU_ERROR;
168           }
169           
170           // status = menu_handle_action(&menu[info.selected]);
171           // TODO: It should now do special stuff for "mover" widgets,
172           // TODO: and handle the return code appropriately.
173           break;
174        default: break;
175     }
176     
177  }
178 
179  return status;
180 
181}
182
183static int draw_menu(Menu menu, menu_info *info)
184{
185  int i;
186  int x=1, y=1;
187  int top=0, bottom=0;
188
189  int (*readfunc)(int);
190 
191  // these should maybe be removed:
192  int wid=lcd.wid, hgt=lcd.hgt;
193 
194
195  if(!menu) return MENU_ERROR;
196
197  lcd.clear();
198
199 
200  // Scroll down until the selected item is centered, if possible...
201  top = info->selected - (hgt/2);
202  if(top<0) top=0; 
203  bottom = top+hgt;
204  if(bottom > info->length) bottom=info->length;
205  top = bottom-hgt;
206  if(top<0) top=0; 
207 
208 
209
210  // Draw all visible items...
211  for(i=top; i<bottom; i++, y++)
212  {
213    if(i == info->selected) lcd.chr(2,y,'>');
214   
215    switch(menu[i].type)
216    {
217      case TYPE_TITL:
218        lcd.chr(1,y,PAD);
219        lcd.chr(2,y,PAD);
220        lcd.string(4,y,menu[i].text);
221        for(x=strlen(menu[i].text)+5; x <= wid; x++)
222          lcd.chr(x,y,PAD);
223        break;
224      case TYPE_MENU:
225        lcd.string(3,y,menu[i].text);
226        lcd.chr(wid,y,'>');
227        break;
228      case TYPE_FUNC:
229        lcd.string(3,y,menu[i].text);
230        break;
231      case TYPE_CHEK:
232        if(menu[i].data)
233        {
234          readfunc = menu[i].data;
235          if(readfunc(MENU_READ))
236            lcd.chr(wid,y,'Y');
237          else
238            lcd.chr(wid,y,'N');
239        }
240        lcd.string(3,y,menu[i].text);
241        break;
242      case TYPE_SLID:
243        lcd.string(3,y,menu[i].text);
244        break;
245      case TYPE_MOVE:
246        break;
247      default:
248        break;
249    }
250  }
251
252  if(top != 0)
253    lcd.chr(1,1,'^');
254  if(bottom < info->length)
255    lcd.chr(1,hgt,'v');
256 
257 
258  draw_heartbeat();
259  //lcd.flush();
260
261  return 0;
262}
263
264
265static int fill_menu_info(Menu menu, menu_info *info)
266{
267  int i;
268
269  info->selected = 0;
270 
271  // count the entries in the menu
272  for(i=0; menu[i].text; i++);
273 
274  info->length = i;
275 
276  return 0;
277 
278}
279
280static int menu_handle_action(menu_item *item)
281{
282  return MENU_OK;
283}
284
285
286static int slid_func(menu_item *item)
287{
288   char str[16];
289   int key = 0;
290   int value = 0;
291   int x, y=1;
292   int (*readfunc)(int);
293   
294   readfunc = item->data;
295
296   lcd.init_hbar();
297   
298   while(key != 'A' && key != 'D')
299   {
300      // Draw the title...
301      lcd.clear();
302      lcd.chr(1,y,PAD);
303      lcd.chr(2,y,PAD);
304      lcd.string(4,y,item->text);
305      for(x=strlen(item->text)+5; x <= lcd.wid; x++)
306         lcd.chr(x,y,PAD);
307
308      // Draw the slider now...
309      value = readfunc(MENU_READ);
310      if(value < 0  ||  value >= MENU_CLOSE)
311         return value;
312      sprintf(str, "%i", value);
313      if(lcd.hgt >= 4)
314      {
315         lcd.string(8, 4, str);
316         value = (lcd.wid * lcd.cellwid * value / 256);
317         lcd.hbar(1, 3, value);
318      }
319      else
320      {
321         lcd.string(17, 2, str);
322         value = ((lcd.wid-4) * lcd.cellwid * value / 256);
323         lcd.hbar(1, 2, value);
324      }
325      //lcd.flush();
326     
327      for(key = lcd.getkey(); key==0; key = lcd.getkey())
328      {
329         // do the heartbeat...
330         draw_heartbeat();
331         // sleep for 1/8th second...
332         framedelay();
333         // Check for client input...
334      }
335     
336      switch(key)
337      {
338         case 'B':
339            value = readfunc(MENU_MINUS);
340            break;
341         case 'C':
342            value = readfunc(MENU_PLUS);
343            break;
344      }
345
346      if(value >= MENU_CLOSE
347         || value < 0
348         || key == 'A'
349         || key == 'D')
350         return value;
351   }
352   
353   return MENU_OK;
354}
355
Note: See TracBrowser for help on using the repository browser.