source: golgotha/src/i4/window/mwmstyle.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 18.5 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "window/style.hh"
10#include "window/window.hh"
11#include "device/kernel.hh"
12#include "window/dragwin.hh"
13#include "window/colorwin.hh"
14#include "image/image.hh"
15#include "menu/boxmenu.hh"
16#include "window/win_evt.hh"
17#include "gui/text.hh"
18#include "gui/deco_win.hh"
19#include "app/app.hh"
20#include "gui/gradiant.hh"
21
22class i4_mwm_context_help : public i4_window_class
23{
24  i4_graphical_style_class *style;
25  i4_str *text;
26public:
27  i4_event_handler_reference_class<i4_window_class> shadow;
28
29  void draw(i4_draw_context_class &context)
30  {
31    i4_font_class *f=style->font_hint->small_font;
32    local_image->clear(style->color_hint->text_background, context);
33    local_image->rectangle(0,0, width()-1, height()-1, 0, context);
34   
35    f->set_color(style->color_hint->text_foreground);
36    f->put_string(local_image, 2,2, *text, context);
37  }
38
39  i4_mwm_context_help(i4_graphical_style_class *style, const i4_const_str text)
40    :  style(style),
41       i4_window_class(style->font_hint->small_font->width(text)+4,
42                       style->font_hint->small_font->height(text)+4),
43       text(new i4_str(text))
44  {   
45  }
46
47  ~i4_mwm_context_help()
48  {
49    delete text;
50    if (shadow.get())
51      i4_kernel.delete_handler(shadow.get());
52  }
53
54  char *name() { return "i4_mwm_context_help"; }
55};
56
57class i4_mwm_style_class : public i4_graphical_style_class
58{
59public:
60  i4_image_class *close_icon;
61
62  virtual void uninit()
63  {
64    if (close_icon)
65    {
66      delete close_icon;
67      close_icon=0;
68    }
69    i4_graphical_style_class::uninit();
70  }
71
72  char *name() { return "MWM"; }
73  virtual i4_parent_window_class *create_mp_window(i4_coord x, i4_coord y,
74                                                   w16 w, w16 h,
75                                                   const i4_const_str &title,
76                                                   i4_event_reaction_class *on_delete=0
77                                                   );
78
79  virtual i4_bool close_mp_window(i4_parent_window_class *created_window)
80  {
81    if (!created_window) return i4_F;
82    i4_parent_window_class *to_del=created_window->get_parent();
83    if (!to_del) return i4_F;
84    i4_parent_window_class *to_del_parent=to_del->get_parent();
85    if (!to_del_parent) return i4_F;
86   
87    i4_kernel.delete_handler(to_del);
88
89    return i4_T;
90  }
91
92  virtual i4_bool available_for_display(i4_display_class *whom) { return i4_T; }
93
94  virtual i4_menu_class *create_menu(i4_bool hide_on_pick)
95  {
96    return new i4_box_menu_class(this,hide_on_pick);
97  }
98
99
100  virtual void get_in_deco_size(w32 &left, w32 &top, w32 &right, w32 &bottom)
101  {
102    left=right=top=bottom=2;
103  }
104
105  virtual void get_out_deco_size(w32 &left, w32 &top, w32 &right, w32 &bottom)
106  {
107    left=right=top=bottom=2;
108  }
109
110  virtual void deco_neutral_fill(i4_image_class *screen,
111                                 sw32 x1, sw32 y1, sw32 x2, sw32 y2,
112                                 i4_draw_context_class &context)
113  {
114   
115
116    i4_rect_list_class sub_clip(&context.clip,0,0);
117    sub_clip.intersect_area(x1,y1,x2,y2);
118    sub_clip.swap(&context.clip);
119
120    i4_image_class *im=icon_hint->background_bitmap;
121    if (im)
122    {
123      int iw=im->width(), ih=im->height();
124      int dx1=-context.xoff;
125      int dy1=-context.yoff;
126      while (dx1+iw<x1) dx1+=iw;
127      while (dy1+ih<y1) dy1+=ih;
128
129      int x,y;
130      for (y=dy1; y<=y2; y+=ih)
131        for (x=dx1; x<=x2; x+=iw)
132          im->put_image(screen, x,y, context);       
133    }
134    else
135      screen->clear(color_hint->neutral(), context);
136
137
138    sub_clip.swap(&context.clip);
139  }
140
141  // draw a decoration around an area that looks like it's pressed into the screen
142  virtual void draw_in_deco(i4_image_class *screen,
143                            i4_coord x1, i4_coord y1,
144                            i4_coord x2, i4_coord y2,
145                            i4_bool active,
146                            i4_draw_context_class &context)
147  {
148    i4_color_hint_class::bevel *color;
149    if (active)
150      color=&color_hint->window.active;
151    else
152      color=&color_hint->window.passive;
153
154    screen->add_dirty(x1,y1,x2,y1+1,context);
155    screen->add_dirty(x1,y1+2,x1+1,y2,context);
156    screen->add_dirty(x1+2,y2-1,x2,y2,context);
157    screen->add_dirty(x1-1,y1+2,x2,y2-2,context);
158
159    screen->bar(x1,y1,x2,y1,color->dark,context);
160    screen->bar(x1,y1,x1,y2,color->dark,context);
161
162    screen->bar(x1+1,y1+1,x2-1,y1+1,color_hint->black,context);
163    screen->bar(x1+1,y1+1,x1+1,y2-1,color_hint->black,context);
164
165    screen->bar(x1+1,y2,x2,y2,color->bright,context);
166    screen->bar(x2,y1+1,x2,y2,color->bright,context);
167
168    screen->bar(x1+2,y2-1,x2-1,y2-1,color->medium,context);
169    screen->bar(x2-1,y1+1,x2-1,y2-1,color->medium,context);   
170  }
171
172  // draw a decoration around an area that looks like it sticks out the screen
173  virtual void draw_out_deco(i4_image_class *screen,
174                             i4_coord x1, i4_coord y1,
175                             i4_coord x2, i4_coord y2,
176                             i4_bool active,
177                             i4_draw_context_class &context)
178  {
179    i4_color_hint_class::bevel *color;
180    if (active)
181      color=&color_hint->window.active;
182    else
183      color=&color_hint->window.passive;
184
185
186    screen->add_dirty(x1,y1,x2,y1+1,context);
187    screen->add_dirty(x1,y1+2,x1+1,y2,context);
188    screen->add_dirty(x1+2,y2-1,x2,y2,context);
189    screen->add_dirty(x1-1,y1+2,x2,y2-2,context);
190
191    screen->bar(x1,y1,x2,y1,color->bright,context);
192    screen->bar(x1,y1,x1,y2,color->bright,context);
193
194    screen->bar(x1+1,y1+1,x2-1,y1+1,color->medium,context);
195    screen->bar(x1+1,y1+1,x1+1,y2-1,color->medium,context);
196
197    screen->bar(x1+1,y2,x2,y2,color->dark,context);
198    screen->bar(x2,y1+1,x2,y2,color->dark,context);
199
200    screen->bar(x1+2,y2-1,x2-1,y2-1,color_hint->black,context);
201    screen->bar(x2-1,y1+1,x2-1,y2-1,color_hint->black,context);
202 
203  }
204
205  // this will create a temporary (quick) context help window at the mouse cursor
206  // you are responsible for deleting the window
207  virtual i4_window_class *create_quick_context_help(int mouse_x, int mouse_y,
208                                                     const i4_const_str &str)
209  {
210    i4_parent_window_class *parent=i4_current_app->get_root_window();
211    i4_mwm_context_help *w=new i4_mwm_context_help(this, str);
212
213    if (w->width()+mouse_x+3 > parent->width())
214      mouse_x=parent->width()-w->width()-3;
215    if (w->height()+mouse_y+3 > parent->height())
216      mouse_y=parent->height()-w->height()-3;
217
218    i4_window_class *cw=new i4_color_window_class(w->width(), w->height(), 0, this);
219    w->shadow=cw;
220
221    parent->add_child(mouse_x+3, mouse_y+3, cw);   
222    parent->add_child(mouse_x, mouse_y, w);
223
224
225
226    return w;
227  }
228
229} mwm_style;
230
231
232class i4_mwm_event_class : public i4_user_message_event_class
233{
234public:
235  enum {
236    CLOSE_YOURSELF,
237    MAXIMIZE_YOURSELF
238  } ;
239  i4_window_class *from;
240
241  i4_mwm_event_class(w8 sub_type, i4_window_class *from)
242    : i4_user_message_event_class(sub_type),from(from) {}
243
244  virtual i4_event  *copy() { return new i4_mwm_event_class(sub_type,from); }
245
246};
247
248
249static void widget(i4_image_class *im,
250                   i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
251                   i4_color bright, i4_color med, i4_color dark,
252                   i4_draw_context_class &context)
253{
254  // to keep from creating a dirty for each operation below
255  im->add_dirty(x1,y1,x2,y2,context);     
256
257  im->bar(x1,y1,x2,y1,bright,context);
258  im->bar(x1,y1+1,x1,y2,bright,context);
259  im->bar(x2,y1+1,x2,y2,dark,context);
260  im->bar(x1+1,y2,x2-1,y2,dark,context);
261  im->bar(x1+1,y1+1,x2-1,y2-1,med,context);
262}
263
264
265class i4_mwm_close_button_class : public i4_window_class
266
267private:
268  i4_graphical_style_class *hint;
269  i4_bool active;
270
271public:
272  char *name() { return "close_button"; }
273
274  i4_mwm_close_button_class(w16 w, w16 h,i4_graphical_style_class *hint)
275    : i4_window_class (w,h),hint(hint)
276  {
277    active=i4_F;
278  }
279
280  void activate(i4_bool yes)
281  {
282    active=yes;
283    request_redraw();
284  }
285   
286
287  virtual void receive_event(i4_event *ev)
288  {
289    i4_mwm_event_class c(i4_mwm_event_class::CLOSE_YOURSELF,this);
290    if (ev->type()==i4_event::MOUSE_BUTTON_DOWN && parent)
291      i4_kernel.send_event(parent,&c);
292  }
293 
294  void draw(i4_draw_context_class &context)
295  {
296    i4_color_hint_class::bevel *color;
297    /*    if (active)
298      color=&hint->color_hint->window.active;
299    else */
300    color=&hint->color_hint->window.passive;
301
302    local_image->add_dirty(0,0,width()-1,height()-1,context);
303
304
305
306    widget(local_image, 0,0,width()-2,height()-2,color->bright,color->medium,color->dark,context);
307    local_image->bar(0,height()-1,width()-1,height()-1,hint->color_hint->black,context);
308    local_image->bar(width()-1,0,width()-1,height()-1,hint->color_hint->black,context);
309
310    mwm_style.icon_hint->close_icon->put_image(local_image,2,2,context);   
311  }
312
313  virtual void show_self(w32 indent)
314  {   
315    char fmt[50];
316    sprintf(fmt,"%%%ds mwm_close_button",indent);
317    i4_warning(fmt," ");
318  }
319} ;
320
321
322static inline int get_res_num(char *name, int def)
323{
324  i4_const_str s=i4_string_man.get(name);
325  if (s.null()) return def;
326  i4_const_str::iterator i=s.begin();
327  int r=i.read_number();
328  int g=i.read_number();
329  int b=i.read_number();
330  return (r<<16)|(g<<8)|b;
331}
332
333// this is the top draggable part of a window
334class i4_mwm_drag_bar_class : public i4_window_class
335{
336private:
337  i4_graphical_style_class *hint;
338  i4_bool active,dragging;
339public:
340  i4_const_str title;
341
342  char *name() { return "drag_bar"; }
343
344  enum
345  {
346    MIN_WIDTH=15
347  };
348
349  i4_mwm_drag_bar_class(w16 w, w16 h, const i4_const_str &title, i4_graphical_style_class *hint) :
350    i4_window_class(w,h), hint(hint), title(title)
351  {
352    active=i4_F;
353    dragging=i4_F;
354  }
355
356  void activate(i4_bool yes)
357  {
358    active=yes;
359    request_redraw();
360  }
361
362  void draw(i4_draw_context_class &context)
363  {
364    i4_color_hint_class::bevel *color;
365    if (active)
366      color=&hint->color_hint->window.active;
367    else
368      color=&hint->color_hint->window.passive;
369
370
371    local_image->add_dirty(0,0,width()-1,height()-1,context);
372    local_image->rectangle(0,0,width()-1,height()-1,hint->color_hint->black,context);
373
374    i4_color sc,ec;
375
376    if (active)
377    {
378      sc=get_res_num("drag_bar_gradiant_active_start", 0x80);
379      ec=get_res_num("drag_bar_gradiant_active_end", 0x20);
380    }
381    else
382    {
383      sc=get_res_num("drag_bar_gradiant_start", 0x707070);
384      ec=get_res_num("drag_bar_gradiant_end", 0x202020);
385    }
386
387    i4_gradiant_bar(local_image, 1,1,width()-2,height()-2, sc, ec, context);
388
389
390//     if (dragging)
391//       local_image->widget(1,1,width()-2,height()-2,
392//                           color->dark,color->medium,color->bright,context);
393//     else
394//       local_image->widget(1,1,width()-2,height()-2,
395//                           color->bright,color->medium,color->dark,context);
396
397    i4_font_class *font=hint->font_hint->normal_font;
398    w16 strw=font->width(title);
399    w16 strh=font->height(title);
400
401    font->set_color(0xffffff);
402
403    font->put_string(local_image,width()/2-strw/2,height()/2-strh/2,title,context);
404  }
405   
406  virtual void receive_event(i4_event *ev)
407  {
408    if (ev->type()==i4_event::MOUSE_BUTTON_DOWN)
409    {
410      if (!dragging)
411      {
412        i4_window_request_drag_start_class drag(this);
413        i4_kernel.send_event(parent,&drag);
414        if (drag.return_result)
415        {
416          dragging=i4_T;
417          request_redraw();
418        }
419      }
420    } else if (ev->type()==i4_event::MOUSE_BUTTON_UP)
421    {
422      if (dragging)
423      {
424        i4_window_request_drag_end_class end_drag(this);
425        i4_kernel.send_event(parent,&end_drag);
426        dragging=i4_F;
427        request_redraw();
428      }
429    }
430  }
431
432};
433
434
435class i4_mwm_window_class : public i4_draggable_window_class
436{
437private:
438  i4_graphical_style_class *hint;
439  i4_mwm_drag_bar_class *drag;
440  i4_mwm_close_button_class *close_button;
441  i4_bool active,draw_frame;
442  w16 left,right,top,bottom;
443  i4_parent_window_class *user_area;
444  i4_event_reaction_class *on_delete;
445 
446  w32 close_button_width(i4_graphical_style_class *style)   
447  { return 2+style->icon_hint->close_icon->width()+3; }
448
449  w32 close_button_height(i4_graphical_style_class *style)   
450  { return 2+style->icon_hint->close_icon->height()+3; }
451
452 
453  w32 dragbar_height(i4_graphical_style_class *style, const i4_const_str &title)
454  {   
455    return hint->font_hint->normal_font->height(title)+4+1;
456  }
457
458public:
459  ~i4_mwm_window_class()
460  {
461    if (on_delete)
462      delete on_delete;
463    on_delete = 0;
464  }
465
466  i4_parent_window_class *user_window() { return user_area; }
467
468  i4_mwm_window_class(w16 width, w16 height,
469                      const i4_const_str &title,
470                      i4_graphical_style_class *hint,
471                      i4_event_reaction_class *on_delete)
472    : i4_draggable_window_class(width,height), hint(hint),
473      on_delete(on_delete)
474  {   
475    left=2;
476    if (close_button_height(hint)>dragbar_height(hint,title))
477      top=close_button_height(hint);
478    else
479      top=dragbar_height(hint,title);
480
481    top+=2;  // top border
482
483    right=2;
484    bottom=2;
485
486   
487    active=i4_F;
488    draw_frame=i4_T;
489   
490    resize(w+left+right,h+top+bottom);
491   
492    drag=new i4_mwm_drag_bar_class(w-left-right-close_button_width(hint),
493                                   top-2,
494                                   title,hint);
495    add_child(2,2,drag);
496
497    close_button=new i4_mwm_close_button_class(close_button_width(hint),
498                                               close_button_height(hint),
499                                               hint);
500
501    add_child(w-right-close_button_width(hint),2,close_button);
502
503    user_area=i4_add_color_window(this, hint->color_hint->window.passive.medium,
504                                  hint,
505                                  left, top,
506                                  width, height);
507  }
508
509  virtual void parent_draw(i4_draw_context_class &context)
510  {   
511    if (draw_frame ||
512        !undrawn_area.clipped_away(0,0,0+width()-1,0+1)     ||
513        !undrawn_area.clipped_away(0,0,0+1,0+height()-1)  ||
514        !undrawn_area.clipped_away(0+1,0+height()-2,0+width()-1,0+height()-1)  ||
515        !undrawn_area.clipped_away(0+width()-2,0,0+width()-1,0+height()-1))
516       
517    {
518      i4_color_hint_class::bevel *color;
519      if (active)
520        color=&hint->color_hint->window.active;
521      else
522        color=&hint->color_hint->window.passive;
523
524
525      local_image->add_dirty(0,0,width()-1,1,context);
526      local_image->add_dirty(0,2,1,height()-1,context);
527      local_image->add_dirty(2,height()-2,width()-1,height()-1,context);
528      local_image->add_dirty(width()-2,2,width()-1,height()-3,context);
529
530      local_image->bar(0,0,width()-1,0,color->medium,context);
531      local_image->bar(0,1,0,height()-1,color->medium,context);
532
533      local_image->bar(1,1,width()-2,1,color->bright,context);
534      local_image->bar(1,2,1,height()-2,color->bright,context);
535
536      local_image->bar(width()-2,2,width()-2,height()-2,color->medium,context);
537      local_image->bar(2,height()-2,width()-3,height()-2,color->medium,context);
538
539      local_image->bar(width()-1,0,width()-1,height()-1,hint->color_hint->black,context);
540      local_image->bar(0,height()-1,width()-2,height()-1,hint->color_hint->black,context);
541      draw_frame=i4_F;
542    }
543
544
545    if (!undrawn_area.empty())
546      local_image->bar(2,2,width()-3,height()-3,hint->color_hint->window.passive.medium,context);
547
548  }
549
550  virtual i4_bool need_redraw()
551  {
552    return (i4_bool)(i4_parent_window_class::need_redraw()|draw_frame);
553  }
554
555  void receive_event(i4_event *ev)
556  {
557    if (ev->type()==i4_event::WINDOW_MESSAGE)
558    {
559      CAST_PTR(f,i4_window_message_class,ev);
560      if (f->sub_type==i4_window_message_class::GOT_MOUSE_FOCUS)
561      {
562        active=i4_T;
563        drag->activate(i4_T);
564        close_button->activate(i4_T);
565        draw_frame=i4_T;
566
567      }
568      else if (f->sub_type==i4_window_message_class::LOST_MOUSE_FOCUS)
569      {
570        drag->activate(i4_F);
571        close_button->activate(i4_F);
572        active=i4_F;
573        draw_frame=i4_T;
574
575      }
576      else if (f->sub_type==i4_window_message_class::NOTIFY_RESIZE)
577      {
578        CAST_PTR(res,i4_window_notify_resize_class,ev);
579
580        i4_mwm_window_class *new_parent=new i4_mwm_window_class(res->new_width,
581                                                                res->new_height,
582                                                                drag->title,
583                                                                hint,
584                                                                on_delete ?
585                                                                on_delete->copy() : 0);
586
587        user_area->transfer_children(new_parent->user_area,0,0);
588
589        // this will be post-poned
590        i4_kernel.delete_handler(this);
591
592        parent->add_child(x(),y(),new_parent);
593
594      }
595
596      i4_draggable_window_class::receive_event(ev);
597    } else if (ev->type()==i4_event::USER_MESSAGE)
598    {
599      CAST_PTR(f,i4_mwm_event_class,ev);
600      if (f->sub_type==i4_mwm_event_class::CLOSE_YOURSELF)
601      {
602        if (on_delete)
603          i4_kernel.send(on_delete);
604
605        i4_kernel.delete_handler(this);
606      }
607    } else i4_draggable_window_class::receive_event(ev);   
608  }
609
610} ;
611
612
613i4_parent_window_class *i4_mwm_style_class::create_mp_window(i4_coord x, i4_coord y,
614                                                             w16 w, w16 h,
615                                                             const i4_const_str &title,
616                                                             i4_event_reaction_class *on_delete)
617{
618    i4_parent_window_class *parent=i4_current_app->get_root_window();
619
620  i4_mwm_window_class *win=new i4_mwm_window_class(w,h,title,this,on_delete);
621  if (x==-1)
622    x=parent->width()/2-w/2;
623  if (y==-1)
624    y=parent->height()/2-h/2;
625
626  parent->add_child(x,y,win);
627  return win->user_window();
628}
Note: See TracBrowser for help on using the repository browser.