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

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

style: remove trailing spaces, fix copyright statements.

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