scrolling explained

ulis, 2002-11-24

I gave this explanation on comp.lang.tcl and saw a new related question. The first subject was : scrolling to an item.

Here are some explanations about scrolling.

    sx1           vx1    ix1    ix2    vx2            sx2
    |             |      |      |      |              | 
    +-------------------------------------------------+
    |                                                 |
    |             +--------------------+              |
    |             |                    |              |
    |             |      +------+      |              |
    |             |      | item |      |              |
    |             |      +------+      |              |
    |             |                    |              |
    |             |    visible area    |              |
    |             +--------------------+              |
    |                                                 |
    |                  scroll region                  |
    +-------------------------------------------------+

    The scroll region is where are all your items.

    For a canvas generally you set the scroll region with:
      .cnv config -scrollregion [.cnv bbox all]
    sx1 & sx2 are the x coordinates of the scroll region. 
    sx1, the beginning, sx2, the end.
    You get sx1 & sx2 with .cnv cget -scrollregion.

    The visible area is the visible surface of the canvas displayed on screen.
    vx1 & vx2 are the x coordinates of the visible area.
    vx1, the beginning, vx2, the end.
    You know vx1 & vx2 because vx1 is 0 
    and you fixed vx2 with -width $vx2.

    ix1 & ix2 are the x coordinates of the item.
    ix1, the beginning, ix2, the end.
    You can get ix1 & ix2 with [.cnv bbox item_tag].

    Scrolling is varying the position of the visible area within the scroll region.
    If you want to see the beginning of your item you need to have ix1 between vx1 & vx2.
    For a canvas, the operation to use is:
      .cnv xview moveto $fraction
    where $fraction is ($vx1 - $sx1) / ($sx2 - $sx1)
    (the percent of the scroll region before the visible area).

    So, if you want ix1 == vx1 
    (the beginning of the item at the beginning of the visible area)
    for a canvas you need to do:
      .cnv xview moveto [expr {double($ix1 - $sx1) / ($sx2 - $sx1)}]

A canvas example:

  # create the canvas & the item
  canvas .c -width 100 -height 100 \
    -scrollregion {-400 -400 400 400} -bg white -bd 1 -relief sunken
  .c create text 200 200 -text hidden -tags hidden
  # the 'view' proc
  proc view {tag} \
  {
    foreach {x1 y1 x2 y2} [.c bbox $tag] break
    foreach {s1 t1 s2 t2} [.c cget -scrollregion] break
    .c xview moveto [expr {double($x1 - $s1) / ($s2 - $s1)}]
    .c yview moveto [expr {double($y1 - $t1) / ($t2 - $t1)}]
  }
  # some stuff for the demo
  proc hide {} \
  {
    .c xview moveto 0.0
    .c yview moveto 0.0
  }
  button .v -text view -command {view hidden}
  button .h -text hide -command {hide}
  grid .c -columnspan 2
  grid .v .h