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

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