source: abuse/trunk/src/imlib/jwindow.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: 14.7 KB
RevLine 
[56]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
[2]12#include "video.hpp"
13#include "image.hpp"
[106]14#include "input.hpp"
[2]15#include "event.hpp"
16#include "filter.hpp"
17#include "event.hpp"
18#include "jwindow.hpp"
19
20int jw_left=5,jw_right=5,jw_top=15,jw_bottom=5;
21
22int frame_top() { return jw_top; }
23int frame_bottom() { return jw_bottom; }
24int frame_left() { return jw_left; }
25int frame_right() { return jw_right; }
26
27void set_frame_size(int x)
28
29  if (x<1) x=1;
30  jw_left=x;
31  jw_right=x;
32  jw_top=10+x;
33  jw_bottom=x;
34}
35
36 // true if a window lies in this area
37int window_manager::window_in_area(int x1, int y1, int x2, int y2)
38{
39  for (jwindow *f=first;f;f=f->next)
40    if (f->x<=x2 && f->y<=y2 && f->x+f->l-1>=x1 && f->y+f->h-1>=y1)
41      return 1;
42  return 0;
43}
44
45void window_manager::grab_focus(jwindow *j)
46{ grab=j; }
47
48void window_manager::release_focus()
49{ grab=NULL; }
50
51
52void window_manager::close_window(jwindow *j)
53{
54  jwindow *k;
55  if (grab==j) grab=NULL;
56  if (state==dragging && j==drag_window)  // close the window we were dragging
57    state=inputing;
58
59  if (j==first)
60    first=first->next;
61  else
62  {
63    for (k=first;k->next!=j;k=k->next)
64      k->screen->add_dirty(j->x-k->x,j->y-k->y,
65                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
66    k->screen->add_dirty(j->x-k->x,j->y-k->y,
67                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
68    k->next=j->next;
69  }
70  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
71  delete j;
72}
73
74void window_manager::hide_windows()
75{
76  jwindow *p;
77  for (p=first;p;p=p->next)
78  {
[109]79    if (!p->is_hidden())
[2]80    {
[109]81      p->hide();
[2]82      screen->add_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
83    }
84  }
85}
86
87void window_manager::show_windows()
88{
89  jwindow *p;
90  for (p=first;p;p=p->next)
[109]91    if (p->is_hidden())
[2]92      show_window(p);     
93}
94
95void window_manager::hide_window(jwindow *j)
96{
97  jwindow *k;
98  if (j==first)
99    first=first->next;
100  else
101  {
102    for (k=first;k->next!=j;k=k->next)
103      k->screen->add_dirty(j->x-k->x,j->y-k->y,
104                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
105    k->screen->add_dirty(j->x-k->x,j->y-k->y,
106                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
107    k->next=j->next;
108  }
109  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
[109]110  j->hide();
[2]111}
112
113void window_manager::show_window(jwindow *j)
114{
[109]115  if (j->is_hidden())
[2]116  {
[109]117    j->show();
[2]118    j->screen->add_dirty(0,0,j->l-1,j->h-1);
119  }
120}
121
122void window_manager::get_event(event &ev)
123{
124  jwindow *j;
125  eh->get_event(ev);
126  if (ev.type==EV_KEY)
127    key_state[ev.key]=1;
128  else if (ev.type==EV_KEYRELEASE)
129    key_state[ev.key]=0;
130
131  if (state==inputing)
132  {
133    for (ev.window=NULL,j=first;j;j=j->next)
[109]134      if (!j->is_hidden() && ev.mouse_move.x>=j->x && ev.mouse_move.y>=j->y &&
[2]135          ev.mouse_move.x<j->x+j->l && ev.mouse_move.y<j->y+j->h)
136        ev.window=j;
137
138    if (!ev.window && grab) ev.window=grab;
139
140    if (ev.window)
141    {
142      int closew=0,movew=0;
143
144      if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1 && ev.window &&
145           ev.mouse_move.x>=ev.window->x && ev.mouse_move.y>=ev.window->y &&
146           ev.mouse_move.x<ev.window->x+ev.window->l && ev.mouse_move.y<ev.window->y+ev.window->y1()))
147      {
148        if (ev.mouse_move.x-ev.window->x<11) closew=1;
[109]149        else if (ev.window->is_moveable()) movew=1;
[2]150      } else if (grab)
151        ev.window=grab;
152
153      if (ev.type==EV_KEY && ev.key==JK_ESC)
154        closew=1;
155
156     
157   
158      if (closew)
159        ev.type=EV_CLOSE_WINDOW;
160      else if (movew)
161      {
162        int red=0;
163        if (ev.window==first)       // see if we need to raise the window
164        {
165          first=first->next;
166          if (first)
167            red=1;
168        }
169        else
170        {
171          jwindow *last=first;
172          for (;last->next!=ev.window;last=last->next);
173          if (ev.window->next)
174            red=1;
175          last->next=ev.window->next;
176        }
177        if (!first)
178          first=ev.window;
179        else
180        {
181          jwindow *last=first;
182          for (;last->next;last=last->next);
183          last->next=ev.window;
184        }
185        ev.window->next=NULL;
186        if (red)
187        {
[4]188          jwindow *j=ev.window;
[2]189/*        screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
190          for (p=first;p!=j;p=p->next)
191            p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);*/
192          j->screen->add_dirty(0,0,j->l-1,j->h-1);
193          flush_screen();
194        }
195
196        state=dragging;
197        drag_window=ev.window;
198        drag_mousex=ev.window->x-ev.mouse_move.x;
199        drag_mousey=ev.window->y-ev.mouse_move.y;
200        ev.type=EV_SPURIOUS;
201      } else if (ev.window)
[106]202        ev.window->inm->handle_event(ev,ev.window);
[2]203    }
204  } else if (state==dragging)
205  {
206    ev.window=drag_window;
207    if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button==0)  // user released the mouse
208    {
209      state=inputing;
210      ev.type=EV_SPURIOUS;
211    } else if (ev.type==EV_MOUSE_MOVE)
212    {
213       move_window(drag_window,ev.mouse_move.x+drag_mousex,ev.mouse_move.y+drag_mousey);
214       flush_screen();
215       ev.type=EV_DRAG_WINDOW;
216       ev.window_position.x=ev.mouse_move.x+drag_mousex;
217       ev.window_position.y=ev.mouse_move.y+drag_mousey;
218    }
219  }
220  if (ev.type==EV_REDRAW)
221  {
222    for (j=first;j;j=j->next)
223       j->screen->add_dirty(ev.redraw.x1-j->x,ev.redraw.y1-j->y,
224                     ev.redraw.x2-j->x,ev.redraw.y2-j->y);
225    screen->add_dirty(ev.redraw.x1,ev.redraw.y1,ev.redraw.x2,ev.redraw.y2);
226    flush_screen();
227    ev.type=EV_SPURIOUS;   // we took care of this one by ourselves.
228  }
229}
230
231void jwindow::resize(int L, int H)
232{
233  screen->change_size(L,H);
234  l=L; h=H;
235}
236
237void window_manager::resize_window(jwindow *j, int l, int h)
238{
239  jwindow *p;
240  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
241  for (p=first;p!=j;p=p->next)
242    p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);
243  j->resize(l,h);
244  if (!frame_suppress)
245  j->redraw(hi,med,low,frame_font());
246}
247
248void window_manager::move_window(jwindow *j, int x, int y)
249{
250  jwindow *p;
251  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
252  for (p=first;p!=j;p=p->next)
253    p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);
254  j->x=x;
255  j->y=y;
256  j->screen->add_dirty(0,0,j->l-1,j->h-1);
257}
258
259window_manager::window_manager(image *Screen, palette *Pal, int Hi,
260                               int Med, int Low, JCFont *Font)
261{
262  screen=Screen; hi=Hi; low=Low; med=Med; first=NULL; pal=Pal; grab=NULL;
263  bk=pal->find_closest(0,0,0);
264  state=inputing; fnt=Font;  wframe_fnt=Font;
265  memset(key_state,0,sizeof(key_state));
266  eh=new event_handler(screen,pal);
267  frame_suppress=0;
268}
269
[39]270jwindow *window_manager::new_window(int x, int y, int l, int h, ifield *fields, char const *Name)
[2]271{
272  if (x>screen->width()-4) x=screen->width()-25;
273  if (y>screen->height()-4) y=screen->height()-10;
274 
[106]275  jwindow *j=new jwindow(x,y,l,h,fields,Name),*k;
[109]276  j->show();
[2]277  if (!first)
278    first=j;
279  else
280  {
281    k=first;
282    while (k->next) k=k->next;
283    k->next=j;
284    j->next=NULL;
285  }
286  if (!frame_suppress)
287    j->redraw(hi,med,low,frame_font());
288  return j;
289}
290
291void window_manager::flush_screen()
292{
293  jwindow *p,*q;
294
[4]295  int mx=0,my=0;
296  image *mouse_pic=NULL,*mouse_save=NULL;
[2]297 
298  if (has_mouse())
299  {   
300    mouse_pic=eh->mouse_sprite()->visual;
301    mouse_save=eh->mouse_sprite()->save;
302    mx=eh->mouse->drawx();
303    my=eh->mouse->drawy();
304
305    screen->put_part(mouse_save,0,0,mx,my,mx+mouse_pic->width()-1,my+mouse_pic->height()-1);
306    mouse_pic->put_image(screen,mx,my,1);
307  }
308 
309  for (p=first;p;p=p->next)
[109]310    if (!p->is_hidden())
[2]311       screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
312  update_dirty(screen);
313
314  if (has_mouse())
315    mouse_save->put_image(screen,mx,my);
316
317
318  for (p=first;p;p=p->next)
319  {
[109]320    if (!p->is_hidden())
[2]321    {
322      if (has_mouse())
323      {     
324        p->screen->put_part(mouse_save,0,0,mx-p->x,my-p->y,
325                            mx-p->x+mouse_pic->width()-1,
326                            my-p->y+mouse_pic->height()-1);
327        if (has_mouse())
328        mouse_pic->put_image(p->screen,mx-p->x,my-p->y,1);
329      }
330     
331
332//      screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
333      for (q=p->next;q;q=q->next)
[109]334        if (!q->is_hidden())
[2]335          p->screen->delete_dirty(q->x-p->x,
336                              q->y-p->y,
337                              q->x+q->l-1-p->x,
338                              q->y+q->h-1-p->y);
339      update_dirty(p->screen,p->x,p->y);
340      if (has_mouse())
341         mouse_save->put_image(p->screen,mx-p->x,my-p->y,0);
342    }
343  }
344}
345
[109]346jwindow::jwindow(int X, int Y, int L, int H, ifield *fields, char const *Name)
[2]347{
[109]348    ifield *i;
349    int x1, y1, x2, y2;
[2]350
[109]351    l = 0; h = 0;
352    hidden = false;
353    moveable = true;
354    if(fields)
355        for(i = fields; i; i = i->next)
356        {
357            i->area(x1, y1, x2, y2);
358            if ((int)y2 > (int)h)
359                h = y2 + 1;
360            if ((int)x2 > (int)l)
361                l = x2 + 1;
362        }
363    else
[2]364    {
[109]365        l = 2;
366        h = 2;
[2]367    }
368
[109]369    l = L > 0 ? L + jw_left : l - L;
370    l += WINDOW_FRAME_RIGHT;
371    if(l < 18)
372        l = 18;
373    h = H > 0 ? H + jw_top : h - h;
374    h += WINDOW_FRAME_BOTTOM;
375    if(h < 12)
376        h = 12;
377    //if (!fields) { l+=WINDOW_FRAME_LEFT; h+=WINDOW_FRAME_TOP; }
378    y = Y >= 0 ? Y : yres - h + Y - WINDOW_FRAME_TOP - WINDOW_FRAME_BOTTOM - 1;
379    x = X >= 0 ? X : xres - l + X - WINDOW_FRAME_LEFT - WINDOW_FRAME_RIGHT - 1;
[2]380
[109]381    backg = wm->medium_color();
[2]382
[109]383    screen=new image(l,h,NULL,2);
384    l = screen->width();
385    h = screen->height();
386    screen->clear(backg);
387    next = NULL;
388    inm = new input_manager(screen, fields);
389    if(Name == NULL)
390        name = strcpy((char *)jmalloc(strlen(" ") + 1, "jwindow::window name"), " "); 
391    else
392        name = strcpy((char *)jmalloc(strlen(Name) + 1, "jwindow::window name"), Name);
393}
[2]394
[109]395void jwindow::local_close()
396{
397    ;
[2]398}
399
400void jwindow::redraw(int hi, int med, int low, JCFont *fnt)
401{
402  if (jw_right>=3)
403    screen->rectangle(0,0,l-3,h-3,low);
404  if (jw_right>=2)
405    screen->rectangle(1,1,l-2,h-2,med);
406  if (jw_right>=1)
407    screen->rectangle(2,2,l-1,h-1,hi);
408
409
410 
411  screen->wiget_bar(0,0,l-1,8,hi,med,low);
412  screen->line(1,1,l-2,1,low);
413  screen->line(1,3,l-2,3,low);
414  screen->line(1,5,l-2,5,low);
415  screen->line(1,7,l-2,7,low);
416
417  screen->wiget_bar(4,3,10,5,hi,med,low);
418  screen->rectangle(3,2,11,6,0); 
419
420  screen->line(0,8,l-1,8,0);
421  if (jw_right>=1)
422    screen->wiget_bar(0,9,l-1,h-1,hi,med,low); 
423    screen->wiget_bar(0,9,l-1,h-1,hi,med,low);
424  if (jw_right>=2)
425    screen->wiget_bar(4,13,l-jw_right,h-jw_right,low,med,hi);
426
427
428  if (name && name[0] && (name[0]!=' ' || name[1]))
429  {
430    short cx1,cy1,cx2,cy2;
431    screen->get_clip(cx1,cy1,cx2,cy2);
432    screen->set_clip(14,1,l-2,WINDOW_FRAME_TOP-4);
433    screen->bar(14,1,14+fnt->width()*strlen(name),15-8,med);
434    fnt->put_string(screen,14,1,name,low); 
435    screen->set_clip(cx1,cy1,cx2,cy2);
436  }
437 
438  screen->bar(x1(),y1(),x2(),y2(),backg);
439  inm->redraw();
440}
441
442
443ifield *input_manager::unlink(int id)     // unlinks ID from fields list and return the pointer to it
444{
[4]445  for (ifield *i=first,*last=NULL;i;i=i->next)
[2]446  {
447    if (i->id==id)
448    {
449      if (i==first)
450        first=first->next;
451      else
452        last->next=i->next;
453      if (active==i)
454        active=first;
455      return i;
456    }
457    ifield *x=i->unlink(id);
458    if (x) return x;
459    last=i;
460  }
461  return NULL;   // no such id
462}
463
464input_manager::~input_manager()
465{ ifield *i;
466  while (first)
467  { i=first;
468    first=first->next;
469    delete i;
470  }
471}
472
473void input_manager::clear_current()
474{
[109]475    if(owner)
476        screen = owner->screen;
477    if(active)
478        active->draw(0, screen);
479    active = NULL;
[2]480}
481
[106]482void input_manager::handle_event(event &ev, jwindow *j)
[2]483{
484  ifield *i,*in_area=NULL;
485  int x1,y1,x2,y2;
[109]486
487  if(owner)
488      screen = owner->screen;
489
[2]490  if (j)
491  {
492    ev.mouse_move.x-=j->x;
493    ev.mouse_move.y-=j->y;
494    cur=j;
495  }
496
497  if (!grab)
498  {
499    if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1) || ev.type==EV_MOUSE_MOVE)
500    {
501      for (i=first;i;i=i->next)
502      {
[106]503        i->area(x1,y1,x2,y2);
[2]504        if (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
505            ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2)
506        in_area=i;
507      }
508      if (in_area!=active && (no_selections_allowed || (in_area && in_area->selectable())))
509      {
510        if (active)
[106]511          active->draw(0,screen);
[2]512
513        active=in_area;
514
515        if (active)
[106]516          active->draw(1,screen);
[2]517      }
518    }
519    if (ev.type==EV_KEY && ev.key==JK_TAB && active)
520    {
[106]521      active->draw(0,screen);
[2]522      do
523      {
524        active=active->next;
525        if (!active) active=first;
526      } while (active && !active->selectable());
[106]527      active->draw(1,screen);
[2]528    }
529  } else active=grab;
530
531  if (active)
532  {
533    if (ev.type!=EV_MOUSE_MOVE && ev.type!=EV_MOUSE_BUTTON)
[106]534      active->handle_event(ev,screen,this);
[2]535    else
536    {
[106]537      active->area(x1,y1,x2,y2);
[2]538      if (grab || (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
539          ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2))
540      {
541        if (j)
[106]542          active->handle_event(ev,screen,j->inm);
543        else active->handle_event(ev,screen,this);
[2]544      }
545    }
546  }
547
548  if (j)
549  {
550    ev.mouse_move.x+=j->x;
551    ev.mouse_move.y+=j->y;
552  }
553}
554
555void input_manager::allow_no_selections()
556{
557  no_selections_allowed=1;
558}
559
560void input_manager::redraw()
561{
[109]562    ifield *i;
563    if(owner)
564        screen = owner->screen;
565    for(i = first; i; i = i->next)
566        i->draw_first(screen);
567    if(active)
568        active->draw(1, screen);
[2]569}
570
[106]571input_manager::input_manager(image *Screen, ifield *First)
[2]572{
[109]573    no_selections_allowed = 0;
574    cur = NULL;
575    grab = NULL;
576    owner = NULL;
577    screen = Screen;
578    active = first = First;
579    while(active && !active->selectable())
580        active = active->next;
581    if(screen)
582        redraw();
[2]583}
584
[109]585input_manager::input_manager(jwindow *Owner, ifield *First)
586{
587    no_selections_allowed = 0;
588    cur = NULL;
589    grab = NULL;
590    owner = Owner;
591    screen = NULL;
592    active = first = First;
593    while(active && !active->selectable())
594        active = active->next;
595}
596
[2]597void input_manager::grab_focus(ifield *i)
598{ grab=i;
599  if (cur)
600    wm->grab_focus(cur);
601}
602
603void input_manager::release_focus()
604{ grab=NULL;
605  if (cur)
606    wm->release_focus();
607}
608
609void input_manager::remap(filter *f)
610{
611  for (ifield *i=first;i;i=i->next)
612   i->remap(f);
613  redraw();
614}
615
616void input_manager::add(ifield *i)
617{ ifield *f=first;
618  if (i->selectable())
619  {
620    if (!f)
621      first=i;
622    else
623    {
624      while (f->next) f=f->next;
625      f->next=i;
626    }
627  }
628}
629
630ifield *input_manager::get(int id)
631{
632  ifield *f;
633  for (f=first;f;f=f->next)
634  {
635    ifield *ret=f->find(id);
636    if (ret) return ret;
637  }
638  return NULL;
639}
640
[109]641ifield::ifield()
642{
643    owner = NULL;
644    x = 0;
645    y = 0;
646    next = NULL;
647    id = 0;
648}
[2]649
[109]650ifield::~ifield()
651{
652    ;
653}
[2]654
[109]655/* re-position the control with respect to the "client" area of the window */
656void ifield::set_owner(jwindow * newowner)
657{
658    if(owner)
659        move(x - owner->x1(), y - owner->y1());
660    owner = newowner;
661    if(owner)
662        move(x + owner->x1(), y + owner->y1());
663}
664
Note: See TracBrowser for help on using the repository browser.