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

Last change on this file since 111 was 111, checked in by Sam Hocevar, 11 years ago
  • Simplified the window creation arguments. Got rid of a lot of macros and hid stuff in private namespaces.

Inspired by Win32 Abuse changelog for January 28, 2001:

  • Well, in the process of adding changes necessary to

handle recovery from alt-tabbing away from Abuse
(which is why I was updating jwindow::redraw()),
the entire windowing system is getting an overhaul.
It's gonna be sweet when I'm done, though.

  • jwindow::redraw() has been changed to a virtual

function requiring no parameters. This'll make
it much easier to implement special specific-
purpose windows.

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