Back to index

texmacs  1.0.7.15
basic_widget.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : basic_widget.cpp
00004 * DESCRIPTION: Basic widgets can handle the most common events
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "Widkit/basic_widget.hpp"
00013 #include "gui.hpp"
00014 #include "window.hpp"
00015 #include "Widkit/Event/attribute_event.hpp"
00016 
00017 SI get_dx (gravity grav, SI w);
00018 SI get_dy (gravity grav, SI h);
00019 
00020 /******************************************************************************
00021 * Constructors and destructors
00022 ******************************************************************************/
00023 
00024 basic_widget_rep::basic_widget_rep (gravity grav):
00025   wk_widget_rep (array<wk_widget> (0), array<string> (0), grav),
00026   ptr_focus (-1) {}
00027 basic_widget_rep::basic_widget_rep (
00028   array<wk_widget> a, gravity grav):
00029     wk_widget_rep (a, array<string> (N(a)), grav), ptr_focus (-1) {}
00030 basic_widget_rep::basic_widget_rep (
00031   array<wk_widget> a2, array<string> name2, gravity grav2):
00032     wk_widget_rep (a2, name2, grav2), ptr_focus (-1) {}
00033 
00034 /******************************************************************************
00035 * Generating events in local coordinates
00036 ******************************************************************************/
00037 
00038 event
00039 basic_widget_rep::emit_position (SI rx, SI ry, SI w, SI h, gravity grav) {
00040   return ::emit_position (ox+ rx, oy+ ry, w, h, grav);
00041 }
00042 
00043 event
00044 basic_widget_rep::emit_invalidate (SI x1, SI y1, SI x2, SI y2) {
00045   return ::emit_invalidate (ox+ x1, oy+ y1, ox+ x2, oy+ y2);
00046 }
00047 
00048 event
00049 basic_widget_rep::emit_mouse (mouse_event ev) {
00050   return ::emit_mouse (ev, ev->type, ox+ ev->x, oy+ ev->y);
00051 }
00052 
00053 event
00054 basic_widget_rep::emit_mouse (mouse_event ev, string type) {
00055   return ::emit_mouse (ev, type, ox+ ev->x, oy+ ev->y);
00056 }
00057 
00058 event
00059 basic_widget_rep::emit_mouse (mouse_event ev, string type, SI x, SI y) {
00060   return ::emit_mouse (ev, type, ox+x, oy+y);
00061 }
00062 
00063 event
00064 basic_widget_rep::emit_clear (SI x1, SI y1, SI x2, SI y2) {
00065   return ::emit_clear (ox+ x1, oy+ y1, ox+ x2, oy+ y2);
00066 }
00067 
00068 event
00069 basic_widget_rep::emit_repaint (SI x1, SI y1, SI x2, SI y2, bool& stop) {
00070   return ::emit_repaint (ox+ x1, oy+ y1, ox+ x2, oy+ y2, stop);
00071 }
00072 
00073 event
00074 basic_widget_rep::emit_find_child (SI x, SI y, int& which) {
00075   return ::emit_find_child (ox+ x, oy+ y, which);
00076 }
00077 
00078 /******************************************************************************
00079 * Exchanging information with the widget
00080 ******************************************************************************/
00081 
00082 void
00083 basic_widget_rep::handle_get_size (get_size_event ev) {
00084   if (N(a)>0) {
00085     int i;
00086     SI w= 0, h= 0;
00087     for (i=0; i<N(a); i++) {
00088       SI ww= ev->w, hh= ev->h;
00089       a[i] << get_size (ww, hh, ev->mode);
00090       w= max (w, ww);
00091       h= max (h, hh);
00092     }
00093     ev->w= w;
00094     ev->h= h;
00095   }
00096 }
00097 
00098 void
00099 basic_widget_rep::handle_get_widget (get_widget_event ev) {
00100   int i;
00101   for (i=0; i<N(a); i++)
00102     if (name[i] == ev->which) {
00103       ev->w= a[i];
00104       return;
00105     }
00106   WK_FAILED ("could not get widget attribute " * ev->which);
00107 }
00108 
00109 void
00110 basic_widget_rep::handle_set_widget (set_widget_event ev) {
00111   int i;
00112   for (i=0; i<N(a); i++)
00113     if (name[i] == ev->which) { a[i]= ev->w; return; }
00114   WK_FAILED ("could not set widget attribute " * ev->which);
00115 }
00116 
00117 /******************************************************************************
00118 * Handling structure events
00119 ******************************************************************************/
00120 
00121 void
00122 basic_widget_rep::handle_attach_window (attach_window_event ev) {
00123   if ((win!=NULL) && (ev->win!=NULL) && (win!=ev->win))
00124     WK_FAILED ("widget already attached to another window");
00125   win= ev->win;
00126   for (int i=0; i<N(a); i++) a[i] << emit_attach_window (win);
00127 }
00128 
00129 void
00130 basic_widget_rep::handle_position (position_event ev) { (void) ev;
00131   int i;
00132   for (i=0; i<N(a); i++)
00133     a[i] << emit_position (0, 0, w, h, grav);
00134 }
00135 
00136 void
00137 basic_widget_rep::handle_move (move_event ev) { (void) ev;
00138 }
00139 
00140 void
00141 basic_widget_rep::handle_resize (resize_event ev) { (void) ev;
00142 }
00143 
00144 void
00145 basic_widget_rep::handle_destroy (destroy_event ev) { (void) ev;
00146   int i;
00147   for (i=0; i<N(a); i++)
00148     a[i] << emit_destroy ();
00149 }
00150 
00151 /******************************************************************************
00152 * Handling input/output events
00153 ******************************************************************************/
00154 
00155 void
00156 basic_widget_rep::handle_keypress (keypress_event ev) { (void) ev; }
00157 
00158 void
00159 basic_widget_rep::handle_keyboard_focus (keyboard_focus_event ev) {(void) ev;}
00160 
00161 void
00162 basic_widget_rep::handle_mouse (mouse_event ev) {
00163   string type= ev->type;
00164   SI     x= ev->x, y= ev->y;
00165   int    focus;
00166 
00167   this << emit_find_child (x, y, focus);
00168   if (type == "leave") focus=-1;
00169   if (focus != ptr_focus) {
00170     if ((ptr_focus >= 0) && (ptr_focus < N(a)))
00171       a[ptr_focus] << emit_mouse (ev, "leave");
00172     ptr_focus= focus;
00173     if ((ptr_focus >= 0) && (ptr_focus < N(a)))
00174       a[ptr_focus] << emit_mouse (ev, "enter");
00175     if ((type == "move") || (type == "enter") || (type == "leave")) return;
00176   }
00177   if ((ptr_focus >= 0) && (ptr_focus < N(a)))
00178     a[ptr_focus] << emit_mouse (ev);
00179 }
00180 
00181 void
00182 basic_widget_rep::handle_alarm (alarm_event ev) {
00183   cout << "Alarm: " << ev->message << "\n";
00184 }
00185 
00186 void
00187 basic_widget_rep::handle_clear (clear_event ev) {
00188   renderer ren= win->get_renderer ();
00189   ren->set_background (white);
00190   ren->clear (ev->x1, ev->y1, ev->x2, ev->y2);
00191 }
00192 
00193 void
00194 basic_widget_rep::handle_repaint (repaint_event ev) { (void) ev; }
00195 
00196 /******************************************************************************
00197 * Handling requests and miscellaneous events
00198 ******************************************************************************/
00199 
00200 void
00201 basic_widget_rep::handle_update (update_event ev) { (void) ev;
00202   if (attached ()) {
00203     this << emit_attach_window (win);
00204     this << emit_reposition ();
00205     this << emit_invalidate_all ();
00206   }
00207 }
00208 
00209 void
00210 basic_widget_rep::handle_refresh (refresh_event ev) { (void) ev;
00211   for (int i=0; i<N(a); i++)
00212     a[i] << emit_refresh ();
00213 }
00214 
00215 void
00216 basic_widget_rep::handle_invalidate (invalidate_event ev) {
00217   if (ev->all_flag) win->invalidate (x1()-ox, y1()-oy, x2()-ox, y2()-oy);
00218   else win->invalidate (ev->x1, ev->y1, ev->x2, ev->y2);
00219 }
00220 
00221 void
00222 basic_widget_rep::handle_keyboard_grab (keyboard_grab_event ev) { (void) ev; }
00223 
00224 void
00225 basic_widget_rep::handle_mouse_grab (mouse_grab_event ev) { (void) ev; }
00226 
00227 void
00228 basic_widget_rep::handle_request_alarm (request_alarm_event ev) { (void) ev; }
00229 
00230 void
00231 basic_widget_rep::handle_find_child (find_child_event ev) {
00232   int& i= ev->which;
00233   for (i=0; i<N(a); i++)
00234     if ((ev->x >= a[i]->x1()-ox) && (ev->x < a[i]->x2()-ox) &&
00235        (ev->y >= a[i]->y1()-oy) && (ev->y < a[i]->y2()-oy)) return;
00236   i= -1;
00237 }
00238 
00239 /******************************************************************************
00240 * The main event dispatcher
00241 ******************************************************************************/
00242 
00243 void
00244 test_round (wk_widget w, string var, SI num) {
00245   if (num != ((num>>8)<<8)) {
00246     w->wk_error ("Bad rounding of " * var * "=" * as_string (num));
00247     FAILED ("bad rounding");
00248   }
00249 }
00250 
00251 static void
00252 test_window_attached (event ev, wk_widget w) {
00253   if (!w->attached ()) {
00254     cerr << "\n" << HRULE << "\n";
00255     cerr << ev << " was sent to\n" << w;
00256     cerr << HRULE << "\n";
00257     FAILED ("widget was not yet attached to window");
00258   }
00259 }
00260 
00261 bool
00262 basic_widget_rep::handle (event ev) {
00263   if (DEBUG_EVENTS) cout << "TeXmacs] " << ev << "\n";
00264   // " ---> " << wk_widget (this) << "\n";
00265   if (attached ()) win->get_renderer ()->set_origin (ox, oy);
00266   switch (ev->type) {
00267   case GET_SIZE_EVENT:
00268     handle_get_size (ev);
00269     return true;
00270   case GET_WIDGET_EVENT:
00271     handle_get_widget (ev);
00272     return true;
00273   case SET_WIDGET_EVENT:
00274     handle_set_widget (ev);
00275     return true;
00276   case ATTACH_WINDOW_EVENT:
00277     handle_attach_window (ev);
00278     return true;
00279   case POSITION_EVENT: {
00280     position_event e (ev);
00281     if (!e->flag) {
00282       ox= e->ox+ get_dx (grav, e->w)- get_dx (e->grav, e->w);
00283                  test_round (this, "ox", ox);
00284       oy= e->oy+ get_dy (grav, e->h)- get_dy (e->grav, e->h);
00285                  test_round (this, "oy", oy);
00286       w = e->w ; test_round (this, "w", w);
00287       h = e->h ; test_round (this, "h", h);
00288     }
00289     ev= emit_reposition ();
00290     handle_position (ev);
00291     return true;
00292   }
00293   case MOVE_EVENT:
00294     handle_move (ev);
00295     return true;
00296   case RESIZE_EVENT:
00297     handle_resize (ev);
00298     return true;
00299   case DESTROY_EVENT:
00300     handle_destroy (ev);
00301     return true;
00302   case KEYPRESS_EVENT:
00303     test_window_attached (ev, this);
00304     handle_keypress (ev);
00305     return true;
00306   case KEYBOARD_FOCUS_EVENT:
00307     test_window_attached (ev, this);
00308     handle_keyboard_focus (ev);
00309     return true;
00310   case MOUSE_EVENT: {
00311     test_window_attached (ev, this);
00312     mouse_event e (ev);
00313     ev= ::emit_mouse (e, e->type, e->x - ox, e->y - oy);
00314     handle_mouse (ev);
00315     return true;
00316   }
00317   case ALARM_EVENT: {
00318     alarm_event e (ev);
00319     handle_alarm (e);
00320     return true;
00321   }
00322   case CLEAR_EVENT: {
00323     test_window_attached (ev, this);
00324     clear_event e (ev);
00325     SI rx1= max (e->x1, x1())- ox;
00326     SI ry1= max (e->y1, y1())- oy;
00327     SI rx2= min (e->x2, x2())- ox;
00328     SI ry2= min (e->y2, y2())- oy;
00329     if ((rx2 > rx1) && (ry2 > ry1)) {
00330       event ev= ::emit_clear (rx1, ry1, rx2, ry2);
00331       win->get_renderer ()->clip (rx1, ry1, rx2, ry2);
00332       handle_clear (ev);
00333       win->get_renderer ()->unclip ();
00334     }
00335     return true;
00336   }
00337   case REPAINT_EVENT: {
00338     test_window_attached (ev, this);
00339     repaint_event e (ev);
00340     SI rx1= max (e->x1, x1())- ox;
00341     SI ry1= max (e->y1, y1())- oy;
00342     SI rx2= min (e->x2, x2())- ox;
00343     SI ry2= min (e->y2, y2())- oy;
00344 
00345     if ((rx2 > rx1) && (ry2 > ry1)) {
00346       event ev= ::emit_repaint (rx1, ry1, rx2, ry2, e->stop);
00347       win->get_renderer ()->clip (rx1, ry1, rx2, ry2);
00348       handle_repaint (ev);
00349       win->get_renderer ()->unclip ();
00350     }
00351 
00352     int i;
00353     ev= emit_repaint (rx1, ry1, rx2, ry2, e->stop);
00354     for (i=0; i<N(a); i++) a[i] << ev;
00355     return true;
00356   }
00357   case UPDATE_EVENT:
00358     test_window_attached (ev, this);
00359     handle_update (ev);
00360     return true;
00361   case REFRESH_EVENT:
00362     handle_refresh (ev);
00363     return true;
00364   case INVALIDATE_EVENT: {
00365     if (!attached ()) return true;
00366     test_window_attached (ev, this);
00367     invalidate_event e (ev);
00368     if (!e->all_flag)
00369       ev= ::emit_invalidate (e->x1- ox, e->y1- oy, e->x2- ox, e->y2- oy);
00370     handle_invalidate (ev);
00371     return true;
00372   }
00373   case KEYBOARD_GRAB_EVENT:
00374     handle_keyboard_grab (ev);
00375     return true;
00376   case MOUSE_GRAB_EVENT:
00377     handle_mouse_grab (ev);
00378     return true;
00379   case REQUEST_ALARM_EVENT:
00380     handle_request_alarm (ev);
00381     return true;
00382   case FIND_CHILD_EVENT: {
00383     find_child_event e (ev);
00384     ev= ::emit_find_child (e->x- ox, e->y- oy, e->which);
00385     handle_find_child (ev);
00386     return true;
00387   }
00388   case GET_COORD2_EVENT: {
00389     get_coord2_event e (ev);
00390     if (e->which == "extra width") {
00391       e->c1= e->c2= 0;
00392       return true;
00393     }
00394     else return false;
00395   }
00396   case SET_COORD2_EVENT: {
00397     set_coord2_event e (ev);
00398     return e->which == "extra width";
00399   }
00400   }
00401   return false;
00402 }