source: abuse/trunk/src/imlib/pmenu.cpp @ 481

Last change on this file since 481 was 481, checked in by Sam Hocevar, 12 years ago

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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