source: abuse/tags/pd/macabuse/imlib/pmenu.c

Last change on this file was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1#include "pmenu.hpp"
2
3void pmenu::move(int new_x, int new_y)
4{
5  wm->move_window(bar,new_x,new_y);
6}
7
8pmenu::pmenu(int X, int Y, pmenu_item *first, image *screen, window_manager *wmanager)
9{
10  top=first;
11  active=NULL;
12  wm=wmanager;
13
14  short cx1,cy1,cx2,cy2;
15  screen->get_clip(cx1,cy1,cx2,cy2);
16  if (cx1<X) cx1=X;
17  int w=cx2-cx1+1;
18  int h=wm->frame_font()->height()+4;
19
20
21  bar=wm->new_window(X,Y,w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
22                     h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
23  bar->set_moveability(0);  // can't drag this window
24  bar->screen->wiget_bar(0,0,w-1,h-1,wm->bright_color(),wm->medium_color(),
25                    wm->dark_color());
26
27
28
29  int total=0,tx,tw;
30  pmenu_item *p=top;
31  for (;p;p=p->next) total++;
32
33  tw=w/(total+1);
34  tx=tw/2;
35
36  for (p=top;p;p=p->next,tx+=tw)
37    p->draw_self(bar,itemx(p,wm),1,itemw(p,wm),1,wm,p==active);     
38/*  }
39  else
40  {
41    for (p=top;p;p=p->next,tx+=tw)
42      p->draw(bar,itemx(p,wm),1,itemw(p,wm),1,wm,p==active);
43  }*/
44 
45}
46
47pmenu_item::pmenu_item(int ID, char *Name, char *on_off_flag, int Hotkey, pmenu_item *Next)
48{
49  xp=-1;
50  id=ID;
51  hotkey=Hotkey;
52  on_off=on_off_flag;
53  if (Name)
54    n=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),Name);
55  else n=NULL;
56  next=Next;
57  sub=NULL;
58}
59
60pmenu_item::pmenu_item(char *Name, psub_menu *Sub, pmenu_item *Next, int xpos)
61{
62  xp=xpos;
63  id=0; hotkey=-1;
64  next=Next;
65  on_off=NULL;
66  CONDITION(Name,"Sub menu cannot have a NULL name");
67  n=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),Name);
68  sub=Sub;
69}
70
71pmenu_item *pmenu_item::find_id(int search_id)
72{
73  if (id==search_id) return this;
74  else if (sub) return sub->find_id(search_id);
75  else return NULL;
76}
77
78pmenu_item *pmenu_item::find_key(int key)
79{
80  if (key==hotkey && hotkey!=-1) return this;
81  else if (sub) return sub->find_key(key);
82  else return NULL;
83}
84
85pmenu::~pmenu()
86{
87  while (top)
88  {
89    pmenu_item *p=top;
90    top=top->next;
91    delete p;
92  }
93  if (bar) wm->close_window(bar);
94}
95
96psub_menu::~psub_menu()
97{
98  if (win)   
99    wm->close_window(win);
100   
101  while (first)
102  {
103    pmenu_item *tmp=first;
104    first=first->next;
105    delete tmp;
106  }
107}
108
109pmenu_item *psub_menu::find_id(int search_id)
110{
111  for (pmenu_item *f=first;f;f=f->next)
112  {
113    pmenu_item *ret=f->find_id(search_id);
114    if (ret) return ret;
115  }
116  return NULL;
117}
118
119pmenu_item *psub_menu::find_key(int key)
120{
121  for (pmenu_item *f=first;f;f=f->next)
122  {
123    pmenu_item *ret=f->find_key(key);
124    if (ret) return ret;
125  }
126  return NULL;
127}
128
129
130void psub_menu::hide(jwindow *parent, int x, int y, window_manager* wm)
131{
132  int w,h;
133  calc_size(w,h,wm);
134  short cx1,cy1,cx2,cy2;
135  screen->get_clip(cx1,cy1,cx2,cy2);
136  if (w+x>cx2)
137    x=cx2-w;
138
139
140  if (win)
141  {
142    if (active!=-1)
143    {
144      int w,h;
145      calc_size(w,h,wm);
146      item_num(active)->draw(win,x+3,y+3+active*(wm->frame_font()->height()+1),w-6,0,wm,0);
147    }
148    wm->close_window(win);
149    win=NULL;
150  }
151}
152
153void psub_menu::calc_size(int &w, int &h, window_manager *wm)
154{
155  int tw=wm->frame_font()->width(),th=wm->frame_font()->height();
156  w=h=0;
157  for (pmenu_item *p=first;p;p=p->next)
158  {
159    if (p->name())
160    {
161      int l=strlen(p->name())*tw+8;
162      if (p->on_off) l+=tw*4;
163      if (l>w) w=l;   
164    }
165    h++;
166  }
167  h=h*(th+1)+8;
168}
169
170void psub_menu::draw(jwindow *parent, int x, int y, window_manager *wmanager)
171{
172  if (win) wm->close_window(win);
173  wm=wmanager;
174
175
176  int w,h,i=0;
177  calc_size(w,h,wm);
178  short cx1,cy1,cx2,cy2;
179  screen->get_clip(cx1,cy1,cx2,cy2);
180  if (parent->x+w+x>cx2)
181    x=cx2-w-parent->x;
182  if (h+y+parent->y>cy2)
183    if (parent->y+parent->h+wm->frame_font()->height()>cy2)
184      y=-h;
185     else y=y-h+wm->frame_font()->height()+5;
186     
187
188  win=wm->new_window(parent->x+x,parent->y+y,
189                     w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
190                     h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
191  win->set_moveability(0);
192  win->screen->wiget_bar(0,0,w-1,h-1,wm->bright_color(),wm->medium_color(),wm->dark_color());
193
194  int has_flags=0;
195  pmenu_item *p=first;
196  for (;p;p=p->next) if (p->on_off) has_flags=1;
197  x=has_flags ? 3+wm->frame_font()->width() : 3;
198  y=3;
199 
200  for (p=first;p;p=p->next,i++,y+=wm->frame_font()->height()+1)
201    p->draw(win,x,y,w-6,0,wm,i==active);
202
203}
204
205void pmenu_item::draw_self(jwindow *parent, int x, int y, int w, int top, window_manager *wm, int active)
206{
207  int bx=x;
208  if (on_off) bx=x-wm->frame_font()->width();
209
210  if (!n)
211  {
212    int h=wm->frame_font()->height();
213    parent->screen->wiget_bar(x,y+h/2-1,x+w-1,y+h/2,wm->dark_color(),wm->medium_color(),wm->bright_color());
214  } else
215  {
216    if (active)
217    {
218      if (xp!=-1)
219        parent->screen->xor_bar(bx,y,x+w-1,y+wm->frame_font()->height()+1,wm->dark_color());
220      else
221      {
222        parent->screen->bar(bx,y,x+w-1,y+wm->frame_font()->height()+1,wm->dark_color());
223        wm->frame_font()->put_string(parent->screen,x+1,y+1,n,wm->medium_color());     
224        if (on_off && *on_off) wm->frame_font()->put_string(parent->screen,bx+1,y+1,"*",wm->medium_color());
225      }
226    } else
227    {
228      if (xp!=-1)
229        parent->screen->xor_bar(bx,y,x+w-1,y+wm->frame_font()->height()+1,wm->dark_color());
230      else
231      {
232        parent->screen->bar(bx,y,x+w-1,y+wm->frame_font()->height()+1,wm->medium_color());
233        wm->frame_font()->put_string(parent->screen,x+1,y+1,n,wm->bright_color());
234        if (on_off && *on_off) wm->frame_font()->put_string(parent->screen,bx+1,y+1,"*",wm->bright_color());
235      }
236    }
237  }
238}
239
240void pmenu_item::draw(jwindow *parent, int x, int y, int w, int top,
241                      window_manager *wm, int active)
242
243  if (n)
244  {
245    if (active)
246    {     
247      draw_self(parent,x,y,w,top,wm,active);
248      if (sub)
249      {
250        if (top)
251          sub->draw(parent,x,y+wm->frame_font()->height()+2,wm);
252        else
253          sub->draw(parent,x+w,y,wm);
254      }
255    }
256    else
257    {
258      if (sub)
259      {
260        if (top)
261          sub->hide(parent,x,y+wm->frame_font()->height()+2,wm);
262        else
263          sub->hide(parent,x+w,y,wm);
264      }
265      draw_self(parent,x,y,w,top,wm,active);
266
267    }
268
269  } else draw_self(parent,x,y,w,top,wm,active);
270}
271
272int pmenu::itemx(pmenu_item *p, window_manager *wm)
273{
274  if (p->xp!=-1) return p->xp;
275  int w=bar->screen->width();
276 
277
278  int total=0,tx,tw,i=0,x;
279  for (pmenu_item *pp=top;pp;pp=pp->next,i++)
280  { if (pp==p) x=i;
281    total++;
282  }
283
284 
285  tw=w/(total+1);
286  return tw/2+x*tw;
287}
288
289
290void pmenu::draw(image *screen, window_manager *wm, int top_only)
291{
292
293}
294
295
296int psub_menu::handle_event(jwindow *parent, int x, int y, window_manager *wm, event &ev)
297{
298  int w,h;
299  calc_size(w,h,wm);
300  short cx1,cy1,cx2,cy2;
301  screen->get_clip(cx1,cy1,cx2,cy2);
302
303  x=win->x;
304  y=win->y;
305
306  int has_flags=0,dx=3;
307  for (pmenu_item *p=first;p;p=p->next) if (p->on_off) has_flags=1;
308  if (has_flags) dx+=wm->frame_font()->width();
309
310  int th=wm->frame_font()->height();
311  if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w && ev.mouse_move.y<y+h)
312  {
313    int new_active=(ev.mouse_move.y-y-3)/(th+1);
314    if (item_num(new_active)==NULL) new_active=-1;
315
316    if (new_active!=active)
317    {
318      if (active!=-1)
319        item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,wm,0);
320      active=new_active;
321      if (active!=-1)
322        item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,wm,1);
323    }
324    if (ev.type==EV_MOUSE_BUTTON)
325    {
326      if (active!=-1)
327        return item_num(active)->handle_event(win,dx,3+active*(th+1),w-6,0,wm,ev);
328      else return 0;
329    } else return 1;
330  } else if (active!=-1)
331    return item_num(active)->handle_event(win,win->x+dx,win->y+3+active*(th+1),w-6,0,wm,ev);
332  else return 0;
333
334
335}
336
337int pmenu_item::handle_event(jwindow *parent, int x, int y, int w, int top,
338                             window_manager *wm, event &ev)
339{
340  x+=parent->x;
341  y+=parent->y;
342  if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w &&
343      ev.mouse_move.y<y+wm->frame_font()->height()+2)
344  {
345    if (sub) return 1;
346    else
347    {
348      if (ev.type==EV_MOUSE_BUTTON &&n)
349        wm->push_event(new event(id,(char *)this));
350      return 1;
351    }   
352  } else if (sub)
353  {
354    if (top)
355      return sub->handle_event(parent,x,y+wm->frame_font()->height()+2,wm,ev);
356    else return sub->handle_event(parent,x+w,y,wm,ev);
357  } else return 0;
358}
359
360pmenu_item *pmenu::inarea(int mx, int my, image *screen, window_manager *wm)
361{
362  short cx1,cy1,cx2,cy2;
363  screen->get_clip(cx1,cy1,cx2,cy2); 
364  mx-=bar->x;
365  my-=bar->y;
366  if (mx<0 || my<0 || mx>=bar->screen->width() || my>=bar->screen->height()) return NULL;
367  else
368  {
369    for (pmenu_item *p=top;p;p=p->next)
370    {
371      if (!p->next) return p;
372      else if (itemx(p->next,wm)>mx) return p;
373    }
374    return NULL;
375  }
376}
377
378int psub_menu::own_event(event &ev)
379{
380  if (win && ev.window==win) return 1; else
381    for (pmenu_item *p=first;p;p=p->next)
382      if (p->own_event(ev))
383        return 1;
384  return 0;
385}
386
387int pmenu_item::own_event(event &ev)
388{
389  if (sub)
390    return sub->own_event(ev);
391  else return 0;
392}
393
394pmenu_item::~pmenu_item()
395{ if (n) jfree(n); if (sub) delete sub;
396}
397
398int pmenu::handle_event(event &ev, image *screen, window_manager *wm)
399{
400  if (!active && ev.window!=bar) return 0;
401/*
402    int yes=0;
403    if (ev.window==bar) yes=1;    // event in top bar?
404    else
405    {
406      for (pmenu_item *p=top;p && !yes;p=p->next)  // event in submenu?
407      if (p->own_event(ev)) yes=1;
408    }
409    if (!yes) return 0;        // event is not for us...
410  }*/
411
412  switch (ev.type)
413  {
414    case EV_KEY :
415    {
416      for (pmenu_item *p=top;p;p=p->next)
417      {
418        pmenu_item *r=p->find_key(ev.key);
419        if (r)
420        {
421          wm->push_event(new event(r->id,(char *)r));
422          return 1;
423        }
424      }
425      return 0;
426    } break;
427    case EV_MOUSE_MOVE :
428    {
429      pmenu_item *new_selection=inarea(ev.mouse_move.x,ev.mouse_move.y,screen,wm);
430      if (!new_selection && active &&
431          active->handle_event(bar,itemx(active,wm),1,itemw(active,wm),1,wm,ev))
432        return 1;
433      else if (active!=new_selection)
434      {
435        if (active)
436          active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,0);
437        active=new_selection;
438        if (active)
439          active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,1);
440      }
441      if (active) return 1;
442      else return 0;
443    } break;
444    case EV_MOUSE_BUTTON :
445    {
446      if (active)
447      {
448        if (active->handle_event(bar,itemx(active,wm),1,itemw(active,wm),1,wm,ev))
449        {
450          active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,0);
451          active=NULL;
452          return 1;
453        } else return 0;
454      }
455      else return 0;
456    } break;
457  }
458  return 0;
459}
460
461
Note: See TracBrowser for help on using the repository browser.