source: abuse/trunk/src/imlib/jwindow.cpp @ 106

Last change on this file since 106 was 106, checked in by Sam Hocevar, 15 years ago
  • Rename the "eh" variable to "wm" because it's a window manager, not an event handler.
  • No longer pass the window manager to functions, there's only one.

Inspired by Win32 Abuse changelog for January 28, 2001:

  • Starting work on singleton code; will get rid of all

references to an arbitrary window_manager* because
there's only going to be one, and it's not ever
going to change.

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