Back to index

texmacs  1.0.7.15
scrollable_widget.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : scrollable_widget.cpp
00004 * DESCRIPTION: Scrollable widgets
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 "window.hpp"
00013 #include "Widkit/scroll_widget.hpp"
00014 
00015 SI get_dx (gravity grav, int w);
00016 SI get_dy (gravity grav, int h);
00017 
00018 inline bool is_nil (wk_widget_rep* x) { return x==NULL; }
00019 
00020 /******************************************************************************
00021 * Routines for scrollable widgets
00022 ******************************************************************************/
00023 
00024 scrollable_widget_rep::scrollable_widget_rep (
00025   wk_widget child, gravity grav):
00026     scroll_widget_rep (1, grav)
00027 {
00028   a[0]= child;
00029   scx= 0; scy= 0;
00030   ex1= 0; ey1= 0;
00031   ex2= 0; ey2= 0;
00032   backup= grav;
00033 }
00034 
00035 scrollable_widget_rep::operator tree () {
00036   return tree (TUPLE, "scrollable", (tree) a[0]);
00037 }
00038 
00039 void
00040 scrollable_widget_rep::scroll_event_hor (SI& x, SI& bef, SI& af) {
00041   abs_round (x);
00042   if ((x + x1() - ox) < ex1) x = ex1 - x1() + ox;
00043   if ((x + x2() - ox) > ex2) x = ex2 - x2() + ox;
00044 
00045   if (attached ()) {
00046     renderer ren= win->get_renderer ();
00047     ren->set_origin (ox, oy);
00048     int dx= max (-w, min (w, x- scx));
00049     if ((dx>-w) && (dx<w) && (dx!=0)) {
00050       win->begin_draw ();
00051       ren->clip (0, -h, w, 0);
00052       win->translate (0, -h, w, 0, -dx, 0);
00053       ren->unclip ();
00054       win->end_draw ();
00055     }
00056     if (dx>0) this << emit_invalidate (w- dx, -h, w, 0);
00057     if (dx<0) this << emit_invalidate (0, -h, -dx, 0);
00058   }
00059 
00060   scx      = x;
00061   bef      = ox- x1();
00062   af       = x2()- ox;
00063   a[0]->ox = ox- scx;
00064 }
00065 
00066 void
00067 scrollable_widget_rep::scroll_event_ver (SI& y, SI& bef, SI& af) {
00068   abs_round (y);
00069   if ((y + y1() - oy) < ey1) y = ey1 - y1() + oy;
00070   if ((y + y2() - oy) > ey2) y = ey2 - y2() + oy;
00071 
00072   if (attached ()) {
00073     renderer ren= win->get_renderer ();
00074     ren->set_origin (ox, oy);
00075     int dy= max (-h, min (h, y- scy));
00076     if ((dy>-h) && (dy<h) && (dy!=0)) {
00077       win->begin_draw ();
00078       ren->clip (0, -h, w, 0);
00079       win->translate (0, -h, w, 0, 0, -dy);
00080       if (dy>0) a[0] << emit_clear (0, -dy, w, 0);
00081       else a[0] << emit_clear (0, -h, w, -h-dy);
00082       ren->unclip ();
00083       win->end_draw ();
00084     }
00085     if (dy>0) this << emit_invalidate (0, -dy, w, 0);
00086     if (dy<0) this << emit_invalidate (0, -h, w, -h-dy);
00087   }
00088 
00089   scy      = y;
00090   bef      = oy- y1();
00091   af       = y2()- oy;
00092   a[0]->oy = oy- scy;
00093 }
00094 
00095 void
00096 scrollable_widget_rep::scroll_to (SI scx2, SI scy2) {
00097   if ((scx2 != scx) && (!is_nil (hor))) hor << emit_bar_scroll_to (scx2);
00098   if ((scy2 != scy) && (!is_nil (ver))) ver << emit_bar_scroll_to (scy2);
00099 }
00100 
00101 void
00102 scrollable_widget_rep::set_extents (SI ex1b, SI ey1b, SI ex2b, SI ey2b) {
00103   ex1= ex1b; ey1= ey1b; ex2= ex2b; ey2= ey2b;
00104   abs_outer_round (ex1, ey1, ex2, ey2);
00105   if (is_nil (hor)) scx = ex1- (x1()- ox);
00106   if (is_nil (ver)) scy = ey1- (y1()- oy);
00107   a[0]->ox = ox -scx; a[0]->oy = oy -scy ;
00108   a[0]->w  = ex2-ex1; a[0]->h  = ey2-ey1;
00109   if ((backup == north_west) && ((a[0]->ox>0) || (a[0]->oy<0))) {
00110     // dirty bug fix: the fact that a[0]->x1(), a[0]->y1(), etc.
00111     // are not computed correctly, implies that only part of the window
00112     // is repainted. We therefore pretend that the child is twice
00113     // as large as it really is
00114     a[0]->grav= center;
00115     a[0]->w <<= 1; a[0]->h <<= 1;
00116   }
00117   else a[0]->grav= backup;
00118   if (attached ()) this << emit_invalidate_all ();
00119   if (!is_nil (hor)) hor << emit_bar_set_extents (ex1, ex2);
00120   if (!is_nil (ver)) ver << emit_bar_set_extents (ey1, ey2);
00121 }
00122 
00123 /******************************************************************************
00124 * Event handlers
00125 ******************************************************************************/
00126 
00127 void
00128 scrollable_widget_rep::handle_get_size (get_size_event ev) {
00129   if (ev->mode==-1) {
00130     ev->w= 8*PIXEL;
00131     ev->h= 8*PIXEL;
00132   }
00133   if (ev->mode== 1) gui_maximal_extents (ev->w, ev->h);
00134 }
00135 
00136 void
00137 scrollable_widget_rep::handle_position (position_event ev) { (void) ev;
00138   set_extents (ex1, ey1, ex2, ey2);
00139   a[0] << emit_reposition ();
00140 }
00141 
00142 void
00143 scrollable_widget_rep::handle_set_widget (set_widget_event ev) {
00144   if      (ev->which == "hor-bar") hor= ev->w.rep;
00145   else if (ev->which == "ver-bar") ver= ev->w.rep;
00146   else attribute_widget_rep::handle_set_widget (ev);
00147 }
00148 
00149 void
00150 scrollable_widget_rep::handle_get_coord1 (get_coord1_event ev) {
00151   if      (ev->which == "width") ev->c1= w;
00152   else if (ev->which == "height") ev->c1= h;
00153   else attribute_widget_rep::handle_get_coord1 (ev);
00154 }
00155 
00156 void
00157 scrollable_widget_rep::handle_get_coord2 (get_coord2_event ev) {
00158   if      (ev->which == "scroll position") {
00159     ev->c1= scx; ev->c2= scy; }
00160   else if (ev->which == "extra width") {
00161     ev->c1= 0; ev->c2= 0; }
00162   else attribute_widget_rep::handle_get_coord2 (ev);
00163 }
00164 
00165 void
00166 scrollable_widget_rep::handle_get_coord4 (get_coord4_event ev) {
00167   if      (ev->which == "visible") {
00168     ev->c1= scx   ; ev->c2= scy -h;
00169     ev->c3= scx+ w; ev->c4= scy;
00170   }
00171   else if (ev->which == "extents") {
00172     ev->c1= ex1; ev->c2= ey1;
00173     ev->c3= ex2; ev->c4= ey2;
00174   }
00175   else attribute_widget_rep::handle_get_coord4 (ev);
00176 }
00177 
00178 void
00179 scrollable_widget_rep::handle_set_coord2 (set_coord2_event ev) {
00180   if      (ev->which == "scroll position")
00181     scroll_to (ev->c1, ev->c2);
00182   else if (ev->which == "extra width");
00183   else attribute_widget_rep::handle_set_coord2 (ev);
00184 }
00185 
00186 void
00187 scrollable_widget_rep::handle_set_coord4 (set_coord4_event ev) {
00188   if (ev->which == "extents")
00189     set_extents (ev->c1, ev->c2, ev->c3, ev->c4);
00190   else attribute_widget_rep::handle_set_coord4 (ev);
00191 }
00192 
00193 void
00194 scrollable_widget_rep::handle_scroll (scroll_event ev) {
00195   if      (ev->which == "hor-bar")
00196     scroll_event_hor (ev->c1, ev->c2, ev->c3);
00197   else if (ev->which == "ver-bar")
00198     scroll_event_ver (ev->c1, ev->c2, ev->c3);
00199   else { WK_FAILED ("invalid scroll"); }
00200 }