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

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