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

Last change on this file since 109 was 109, checked in by Sam Hocevar, 11 years ago
  • Started cleaning up jwindow.cpp, preparing everything for future Abuse Win32 merges.
File size: 9.9 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+1;
28  int h=wm->font()->height()+4;
29
30
31  bar=wm->new_window(X,Y,w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
32                     h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
33  bar->freeze();  // can't drag this window
34  bar->screen->wiget_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=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),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=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),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    if (parent->y+parent->h+wm->font()->height()>cy2)
192      y=-h;
193     else y=y-h+wm->font()->height()+5;
194     
195
196  win=wm->new_window(parent->x+x,parent->y+y,
197                     w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
198                     h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
199  win->freeze();
200  win->screen->wiget_bar(0,0,w-1,h-1,wm->bright_color(),wm->medium_color(),wm->dark_color());
201
202  int has_flags=0;
203  pmenu_item *p=first;
204  for (;p;p=p->next) if (p->on_off) has_flags=1;
205  x=has_flags ? 3+wm->font()->width() : 3;
206  y=3;
207 
208  for (p=first;p;p=p->next,i++,y+=wm->font()->height()+1)
209    p->draw(win,x,y,w-6,0,i==active);
210
211}
212
213void pmenu_item::draw_self(jwindow *parent, int x, int y, int w, int top, int active)
214{
215  int bx=x;
216  if (on_off) bx=x-wm->font()->width();
217
218  if (!n)
219  {
220    int h=wm->font()->height();
221    parent->screen->wiget_bar(x,y+h/2-1,x+w-1,y+h/2,wm->dark_color(),wm->medium_color(),wm->bright_color());
222  } else
223  {
224    if (active)
225    {
226      if (xp!=-1)
227        parent->screen->xor_bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
228      else
229      {
230        parent->screen->bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
231        wm->font()->put_string(parent->screen,x+1,y+1,n,wm->medium_color());   
232        if (on_off && *on_off) wm->font()->put_string(parent->screen,bx+1,y+1,"*",wm->medium_color());
233      }
234    } else
235    {
236      if (xp!=-1)
237        parent->screen->xor_bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
238      else
239      {
240        parent->screen->bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->medium_color());
241        wm->font()->put_string(parent->screen,x+1,y+1,n,wm->bright_color());
242        if (on_off && *on_off) wm->font()->put_string(parent->screen,bx+1,y+1,"*",wm->bright_color());
243      }
244    }
245  }
246}
247
248void pmenu_item::draw(jwindow *parent, int x, int y, int w, int top,
249                      int active)
250
251  if (n)
252  {
253    if (active)
254    {     
255      draw_self(parent,x,y,w,top,active);
256      if (sub)
257      {
258        if (top)
259          sub->draw(parent,x,y+wm->font()->height()+2);
260        else
261          sub->draw(parent,x+w,y);
262      }
263    }
264    else
265    {
266      if (sub)
267      {
268        if (top)
269          sub->hide(parent,x,y+wm->font()->height()+2);
270        else
271          sub->hide(parent,x+w,y);
272      }
273      draw_self(parent,x,y,w,top,active);
274
275    }
276
277  } else draw_self(parent,x,y,w,top,active);
278}
279
280int pmenu::itemx(pmenu_item *p)
281{
282  if (p->xp!=-1) return p->xp;
283  int w=bar->screen->width();
284 
285
286  int total=0,tw,i=0,x=0;
287  for (pmenu_item *pp=top;pp;pp=pp->next,i++)
288  { if (pp==p) x=i;
289    total++;
290  }
291
292 
293  tw=w/(total+1);
294  return tw/2+x*tw;
295}
296
297
298void pmenu::draw(image *screen, int top_only)
299{
300
301}
302
303
304int psub_menu::handle_event(jwindow *parent, int x, int y, event &ev)
305{
306  int w,h;
307  calc_size(w,h);
308  short cx1,cy1,cx2,cy2;
309  screen->get_clip(cx1,cy1,cx2,cy2);
310
311  x=win->x;
312  y=win->y;
313
314  int has_flags=0,dx=3;
315  for (pmenu_item *p=first;p;p=p->next) if (p->on_off) has_flags=1;
316  if (has_flags) dx+=wm->font()->width();
317
318  int th=wm->font()->height();
319  if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w && ev.mouse_move.y<y+h)
320  {
321    int new_active=(ev.mouse_move.y-y-3)/(th+1);
322    if (item_num(new_active)==NULL) new_active=-1;
323
324    if (new_active!=active)
325    {
326      if (active!=-1)
327        item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,0);
328      active=new_active;
329      if (active!=-1)
330        item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,1);
331    }
332    if (ev.type==EV_MOUSE_BUTTON)
333    {
334      if (active!=-1)
335        return item_num(active)->handle_event(win,dx,3+active*(th+1),w-6,0,ev);
336      else return 0;
337    } else return 1;
338  } else if (active!=-1)
339    return item_num(active)->handle_event(win,win->x+dx,win->y+3+active*(th+1),w-6,0,ev);
340  else return 0;
341
342
343}
344
345int pmenu_item::handle_event(jwindow *parent, int x, int y, int w, int top,
346                             event &ev)
347{
348  x+=parent->x;
349  y+=parent->y;
350  if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w &&
351      ev.mouse_move.y<y+wm->font()->height()+2)
352  {
353    if (sub) return 1;
354    else
355    {
356      if (ev.type==EV_MOUSE_BUTTON &&n)
357        wm->push_event(new event(id,(char *)this));
358      return 1;
359    }   
360  } else if (sub)
361  {
362    if (top)
363      return sub->handle_event(parent,x,y+wm->font()->height()+2,ev);
364    else return sub->handle_event(parent,x+w,y,ev);
365  } else return 0;
366}
367
368pmenu_item *pmenu::inarea(int mx, int my, image *screen)
369{
370  short cx1,cy1,cx2,cy2;
371  screen->get_clip(cx1,cy1,cx2,cy2); 
372  mx-=bar->x;
373  my-=bar->y;
374  if (mx<0 || my<0 || mx>=bar->screen->width() || my>=bar->screen->height()) return NULL;
375  else
376  {
377    for (pmenu_item *p=top;p;p=p->next)
378    {
379      if (!p->next) return p;
380      else if (itemx(p->next)>mx) return p;
381    }
382    return NULL;
383  }
384}
385
386int psub_menu::own_event(event &ev)
387{
388  if (win && ev.window==win) return 1; else
389    for (pmenu_item *p=first;p;p=p->next)
390      if (p->own_event(ev))
391        return 1;
392  return 0;
393}
394
395int pmenu_item::own_event(event &ev)
396{
397  if (sub)
398    return sub->own_event(ev);
399  else return 0;
400}
401
402pmenu_item::~pmenu_item()
403{ if (n) jfree(n); if (sub) delete sub;
404}
405
406int pmenu::handle_event(event &ev, image *screen)
407{
408  if (!active && ev.window!=bar) return 0;
409/*
410    int yes=0;
411    if (ev.window==bar) yes=1;    // event in top bar?
412    else
413    {
414      for (pmenu_item *p=top;p && !yes;p=p->next)  // event in submenu?
415      if (p->own_event(ev)) yes=1;
416    }
417    if (!yes) return 0;        // event is not for us...
418  }*/
419
420  switch (ev.type)
421  {
422    case EV_KEY :
423    {
424      for (pmenu_item *p=top;p;p=p->next)
425      {
426        pmenu_item *r=p->find_key(ev.key);
427        if (r)
428        {
429          wm->push_event(new event(r->id,(char *)r));
430          return 1;
431        }
432      }
433      return 0;
434    } break;
435    case EV_MOUSE_MOVE :
436    {
437      pmenu_item *new_selection=inarea(ev.mouse_move.x,ev.mouse_move.y,screen);
438      if (!new_selection && active &&
439          active->handle_event(bar,itemx(active),1,itemw(active),1,ev))
440        return 1;
441      else if (active!=new_selection)
442      {
443        if (active)
444          active->draw(bar,itemx(active),1,itemw(active),1,0);
445        active=new_selection;
446        if (active)
447          active->draw(bar,itemx(active),1,itemw(active),1,1);
448      }
449      if (active) return 1;
450      else return 0;
451    } break;
452    case EV_MOUSE_BUTTON :
453    {
454      if (active)
455      {
456        if (active->handle_event(bar,itemx(active),1,itemw(active),1,ev))
457        {
458          active->draw(bar,itemx(active),1,itemw(active),1,0);
459          active=NULL;
460          return 1;
461        } else return 0;
462      }
463      else return 0;
464    } break;
465  }
466  return 0;
467}
468
469
Note: See TracBrowser for help on using the repository browser.