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

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

ps3: make everything compile on the PS3. Of course, nothing links yet
because so much support is missing.

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