source: abuse/tags/pd/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.5 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
26 // true if a window lies in this area
27int window_manager::window_in_area(int x1, int y1, int x2, int y2)
28{
29  for (jwindow *f=first;f;f=f->next)
30    if (f->x<=x2 && f->y<=y2 && f->x+f->l-1>=x1 && f->y+f->h-1>=y1)
31      return 1;
32  return 0;
33}
34
35void window_manager::grab_focus(jwindow *j)
36{ grab=j; }
37
38void window_manager::release_focus()
39{ grab=NULL; }
40
41
42void window_manager::close_window(jwindow *j)
43{
44  jwindow *k;
45  if (grab==j) grab=NULL;
46  if (state==dragging && j==drag_window)  // close the window we were dragging
47    state=inputing;
48
49  if (j==first)
50    first=first->next;
51  else
52  {
53    for (k=first;k->next!=j;k=k->next)
54      k->screen->add_dirty(j->x-k->x,j->y-k->y,
55                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
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->next=j->next;
59  }
60  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
61  delete j;
62}
63
64void window_manager::hide_windows()
65{
66  jwindow *p;
67  for (p=first;p;p=p->next)
68  {
69    if (!p->property.hidden)
70    {
71      p->property.hidden=1;
72      screen->add_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
73    }
74  }
75}
76
77void window_manager::show_windows()
78{
79  jwindow *p;
80  for (p=first;p;p=p->next)
81    if (p->property.hidden)
82      show_window(p);     
83}
84
85void window_manager::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->property.hidden=1;
101}
102
103void window_manager::show_window(jwindow *j)
104{
105  if (j->property.hidden)
106  {
107    j->property.hidden=0;
108    j->screen->add_dirty(0,0,j->l-1,j->h-1);
109  }
110}
111
112void window_manager::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->property.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->property.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,*p;
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,this);
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 window_manager::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(hi,med,low,frame_font());
236}
237
238void window_manager::move_window(jwindow *j, int x, int y)
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->x=x;
245  j->y=y;
246  j->screen->add_dirty(0,0,j->l-1,j->h-1);
247}
248
249window_manager::window_manager(image *Screen, palette *Pal, int Hi,
250                               int Med, int Low, JCFont *Font)
251{
252  screen=Screen; hi=Hi; low=Low; med=Med; first=NULL; pal=Pal; grab=NULL;
253  bk=pal->find_closest(0,0,0);
254  state=inputing; fnt=Font;  wframe_fnt=Font;
255  memset(key_state,0,sizeof(key_state));
256  eh=new event_handler(screen,pal);
257  frame_suppress=0;
258}
259
260jwindow *window_manager::new_window(int x, int y, int l, int h, ifield *fields, char *Name)
261{
262  if (x>screen->width()-4) x=screen->width()-25;
263  if (y>screen->height()-4) y=screen->height()-10;
264 
265  jwindow *j=new jwindow(x,y,l,h,this,fields,Name),*k;
266  j->property.hidden=0;
267  if (!first)
268    first=j;
269  else
270  {
271    k=first;
272    while (k->next) k=k->next;
273    k->next=j;
274    j->next=NULL;
275  }
276  if (!frame_suppress)
277    j->redraw(hi,med,low,frame_font());
278  return j;
279}
280
281void window_manager::flush_screen()
282{
283  jwindow *p,*q;
284
285  int mx,my,but;
286  image *mouse_pic,*mouse_save;
287 
288  if (has_mouse())
289  {   
290    mouse_pic=eh->mouse_sprite()->visual;
291    mouse_save=eh->mouse_sprite()->save;
292    mx=eh->mouse->drawx();
293    my=eh->mouse->drawy();
294
295    screen->put_part(mouse_save,0,0,mx,my,mx+mouse_pic->width()-1,my+mouse_pic->height()-1);
296    mouse_pic->put_image(screen,mx,my,1);
297  }
298 
299  for (p=first;p;p=p->next)
300    if (!p->property.hidden)
301       screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
302  update_dirty(screen);
303
304  if (has_mouse())
305    mouse_save->put_image(screen,mx,my);
306
307
308  for (p=first;p;p=p->next)
309  {
310    if (!p->property.hidden)
311    {
312      if (has_mouse())
313      {     
314        p->screen->put_part(mouse_save,0,0,mx-p->x,my-p->y,
315                            mx-p->x+mouse_pic->width()-1,
316                            my-p->y+mouse_pic->height()-1);
317        if (has_mouse())
318        mouse_pic->put_image(p->screen,mx-p->x,my-p->y,1);
319      }
320     
321
322//      screen->delete_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
323      for (q=p->next;q;q=q->next)
324        if (!q->property.hidden)
325          p->screen->delete_dirty(q->x-p->x,
326                              q->y-p->y,
327                              q->x+q->l-1-p->x,
328                              q->y+q->h-1-p->y);
329      update_dirty(p->screen,p->x,p->y);
330      if (has_mouse())
331         mouse_save->put_image(p->screen,mx-p->x,my-p->y,0);
332    }
333  }
334}
335
336void jwindow::set_moveability(int x)
337{
338  property.moveable=x;
339}
340
341jwindow::jwindow(int X, int Y, int L, int H, window_manager *wm, ifield *fields, char *Name)
342{
343  ifield *i;
344  int x1,y1,x2,y2;
345  l=0; h=0;
346  property.moveable=1;
347  if (fields)
348    for (i=fields;i;i=i->next)
349    {
350      i->area(x1,y1,x2,y2,wm);
351      if ((int)y2>(int)h)
352        h=y2+1;
353      if ((int)x2>(int)l)
354        l=x2+1;
355    }
356  else { l=2; h=2; }
357
358  if (L<=0) { l=l-L; } else l=L+jw_left;
359  if (H<=0) { h=h-H; } else h=H+jw_top;
360
361 if (Y<0) y=yres-h+Y-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM-1; else y=Y;
362 if (X<0) x=xres-l+X-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT-1; else x=X;
363
364  backg=wm->medium_color();
365  l+=WINDOW_FRAME_RIGHT; h+=WINDOW_FRAME_BOTTOM;
366//  if (!fields) { l+=WINDOW_FRAME_LEFT; h+=WINDOW_FRAME_TOP; }
367
368  if (l<18) l=18;
369  if (h<12) h=12;
370  screen=new image(l,h,NULL,2);
371  l=screen->width();
372  h=screen->height();
373  screen->clear(backg);
374  next=NULL;
375  inm=new input_manager(screen,wm,fields);
376  if (Name==NULL)
377    name=strcpy((char *)jmalloc(strlen(" ")+1,"jwindow::window name")," "); 
378  else
379    name=strcpy((char *)jmalloc(strlen(Name)+1,"jwindow::window name"),Name);
380}
381
382void jwindow::local_close() { ; }
383
384void jwindow::redraw(int hi, int med, int low, JCFont *fnt)
385{
386  if (jw_right>=3)
387    screen->rectangle(0,0,l-3,h-3,low);
388  if (jw_right>=2)
389    screen->rectangle(1,1,l-2,h-2,med);
390  if (jw_right>=1)
391    screen->rectangle(2,2,l-1,h-1,hi);
392
393
394 
395  screen->wiget_bar(0,0,l-1,8,hi,med,low);
396  screen->line(1,1,l-2,1,low);
397  screen->line(1,3,l-2,3,low);
398  screen->line(1,5,l-2,5,low);
399  screen->line(1,7,l-2,7,low);
400
401  screen->wiget_bar(4,3,10,5,hi,med,low);
402  screen->rectangle(3,2,11,6,0); 
403
404  screen->line(0,8,l-1,8,0);
405  if (jw_right>=1)
406    screen->wiget_bar(0,9,l-1,h-1,hi,med,low); 
407    screen->wiget_bar(0,9,l-1,h-1,hi,med,low);
408  if (jw_right>=2)
409    screen->wiget_bar(4,13,l-jw_right,h-jw_right,low,med,hi);
410
411
412  if (name && name[0] && (name[0]!=' ' || name[1]))
413  {
414    short cx1,cy1,cx2,cy2;
415    screen->get_clip(cx1,cy1,cx2,cy2);
416    screen->set_clip(14,1,l-2,WINDOW_FRAME_TOP-4);
417    screen->bar(14,1,14+fnt->width()*strlen(name),15-8,med);
418    fnt->put_string(screen,14,1,name,low); 
419    screen->set_clip(cx1,cy1,cx2,cy2);
420  }
421 
422  screen->bar(x1(),y1(),x2(),y2(),backg);
423  inm->redraw();
424}
425
426
427ifield *input_manager::unlink(int id)     // unlinks ID from fields list and return the pointer to it
428{
429  for (ifield *i=first,*last;i;i=i->next)
430  {
431    if (i->id==id)
432    {
433      if (i==first)
434        first=first->next;
435      else
436        last->next=i->next;
437      if (active==i)
438        active=first;
439      return i;
440    }
441    ifield *x=i->unlink(id);
442    if (x) return x;
443    last=i;
444  }
445  return NULL;   // no such id
446}
447
448input_manager::~input_manager()
449{ ifield *i;
450  while (first)
451  { i=first;
452    first=first->next;
453    delete i;
454  }
455}
456
457void input_manager::clear_current()
458{
459  if (active)
460    active->draw(0,screen,wm);
461
462  active=NULL;
463}
464
465void input_manager::handle_event(event &ev, jwindow *j, window_manager *wm)
466{
467  ifield *i,*in_area=NULL;
468  int x1,y1,x2,y2;
469  if (j)
470  {
471    ev.mouse_move.x-=j->x;
472    ev.mouse_move.y-=j->y;
473    cur=j;
474  }
475
476  if (!grab)
477  {
478    if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1) || ev.type==EV_MOUSE_MOVE)
479    {
480      for (i=first;i;i=i->next)
481      {
482        i->area(x1,y1,x2,y2,wm);
483        if (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
484            ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2)
485        in_area=i;
486      }
487      if (in_area!=active && (no_selections_allowed || (in_area && in_area->selectable())))
488      {
489        if (active)
490          active->draw(0,screen,wm);
491
492        active=in_area;
493
494        if (active)
495          active->draw(1,screen,wm);
496      }
497    }
498    if (ev.type==EV_KEY && ev.key==JK_TAB && active)
499    {
500      active->draw(0,screen,wm);
501      do
502      {
503        active=active->next;
504        if (!active) active=first;
505      } while (active && !active->selectable());
506      active->draw(1,screen,wm);
507    }
508  } else active=grab;
509
510  if (active)
511  {
512    if (ev.type!=EV_MOUSE_MOVE && ev.type!=EV_MOUSE_BUTTON)
513      active->handle_event(ev,screen,wm,this);
514    else
515    {
516      active->area(x1,y1,x2,y2,wm);
517      if (grab || (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
518          ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2))
519      {
520        if (j)
521          active->handle_event(ev,screen,wm,j->inm);
522        else active->handle_event(ev,screen,wm,this);
523      }
524    }
525  }
526
527  if (j)
528  {
529    ev.mouse_move.x+=j->x;
530    ev.mouse_move.y+=j->y;
531  }
532}
533
534void input_manager::allow_no_selections()
535{
536  no_selections_allowed=1;
537}
538
539void input_manager::redraw()
540{
541  ifield *i;
542  for (i=first;i;i=i->next)
543    i->draw_first(screen,wm);
544  if (active)
545    active->draw(1,screen,wm);
546}
547
548input_manager::input_manager(image *Screen, window_manager *WM, ifield *First)
549{
550  no_selections_allowed=0;
551  cur=NULL;
552  grab=NULL;
553  screen=Screen;
554  wm=WM;
555  active=first=First;
556  while (active && !active->selectable()) active=active->next;
557  redraw();
558}
559
560void input_manager::grab_focus(ifield *i)
561{ grab=i;
562  if (cur)
563    wm->grab_focus(cur);
564}
565
566void input_manager::release_focus()
567{ grab=NULL;
568  if (cur)
569    wm->release_focus();
570}
571
572void input_manager::remap(filter *f)
573{
574  for (ifield *i=first;i;i=i->next)
575   i->remap(f);
576  redraw();
577}
578
579void input_manager::add(ifield *i)
580{ ifield *f=first;
581  if (i->selectable())
582  {
583    if (!f)
584      first=i;
585    else
586    {
587      while (f->next) f=f->next;
588      f->next=i;
589    }
590  }
591}
592
593ifield *input_manager::get(int id)
594{
595  ifield *f;
596  for (f=first;f;f=f->next)
597  {
598    ifield *ret=f->find(id);
599    if (ret) return ret;
600  }
601  return NULL;
602}
603
604
605
Note: See TracBrowser for help on using the repository browser.