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

Last change on this file since 671 was 671, checked in by Sam Hocevar, 11 years ago

imlib: convert some Jwindow members to vec2i.

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