source: abuse/tags/pd/macabuse/imlib/jwindow.c @ 49

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