I just do not understand the scroller

Discussion in 'Rebol' started by swhite, Feb 2, 2011.

  1. swhite

    swhite Member

    I have made myself a test script by copying a scroller demo from the cookbook. I added a couple debugging buttons so I could see what is going on inside. I understand the general idea of the scroller: when one operates the scroller, the scroller's "data" value changes from 0 to 1, and that indicates how far through the scrolled item one is scrolling. That fraction, from 0 to 1, is used to adjust the "Y" value of some feature of whatever you are scrolling through, and after that "Y" value is adjusted, you re-show the item being scrolled. In the case of scrolling "down" a text block, the "Y" value would have to go negative, assuming the "top" has a "Y" value of zero, like the coordinate system in algebra.

    So that's fine, I get the concept. But I don't really understand exactly how it works, specifically the following point:

    In the script below, right out of the cookbook, in the first function, the scroll-tface function, I see that it is setting the para/scroll/y value. I see that one wants a negative number (thus the "negate), and I see that the bar/data (varying from 0 to 1) is being multiplied by something, but that next ONE line I don't get. Is it the max of (zero, or (user-data minus size/y), or is it the (max of zero or user-data) minus size/y? And what does txt/size/y represent. Is it the size of the text, or the size of the box that displays it? If it's the size of the text, is in lines or characters? In the update-tface function, txt/user-data also is set to the "Y" value of txt, supposedly, although it doesn't show that way in my debugging display.

    I can't believe how, in REBOL, just ONE LINE of code can be so difficult to understand.

    Thank you for any insights.

    REBOL [
    ]
    scroll-tface: func [txt bar][
    txt/para/scroll/y: negate bar/data *
    (max 0 txt/user-data - txt/size/y)
    show txt
    ]
    open-tface: func [txt bar /local file][
    if file: request-file [
    txt/text: read first file
    reset-tface txt bar
    ]
    ]
    reset-tface: func [txt bar][
    txt/para/scroll/y: 0
    bar/data: 0
    update-tface txt bar
    show [txt bar]
    ]
    update-tface: func [txt bar] [
    txt/line-list: none
    txt/user-data: second size-text txt
    bar/redrag txt/size/y / txt/user-data
    ]
    show-values: func [txt bar] [
    t1-user-data/text: to-string txt/user-data
    t1-para-scroll-y/text: to-string txt/para/scroll/y
    t1-size-y/text: to-string txt/size/y
    s1-data/text: to-string bar/data
    show t1-user-data
    show t1-para-scroll-y
    show t1-size-y
    show s1-data
    ]
    out: layout [
    across
    h3 "Text Scrolling Example" return
    space 0
    t1: text 600x300 wrap green black font-name font-fixed
    s1: scroller 16x300 [scroll-tface t1 s1]
    return
    pad 0x5 space 5
    button "Open" [open-tface t1 s1]
    button "Debug" [show-values t1 s1]
    button "Halt" [halt]
    return
    label "t1/user-data"
    t1-user-data: text "initial"
    return
    label "t1-size-y"
    t1-size-y: text "initial"
    return
    label "t1/para/scroll/y"
    t1-para-scroll-y: text "initial"
    return
    label "s1/data"
    s1-data: text "initial"
    ]
    view out
  2. Graham

    Graham Developer Staff Member

    To understand this, you need to know the Rebol basics. Suggest you look up how precedence operates in evaluation.
  3. swhite

    swhite Member

    Thank you. That seemed to trigger the little gray cells in some way so that I was able to understand what I was not understanding.

    The key understanding is that t1 it an interface object, and its text value can be envisioned as a rectangle of pixels, with the text "displayed" on it. Only a part shows through the window. The para/scroll/y value shows the starting point from which text is displayed. This value starts at zero when the text is displayed at the top, and "increases" in a negative direction because the text area can be envisioned as a grid with the top left corner being 0x0--thus "down" the text would be in a negative y direction like the coordinates in algebra. The display window also is a rectangle of pixels, and displaying in it starts at 0x0.

    The size/y value is the vertical size of the text window. The user-data value is the vertical size of the text. The (user-data minus size/y) expression is evaluated first. The result of that calculation represents a point in the text value somewhere back from the maximum value, that is, back from the end. That point, back from the end, is back by a distance equal to the size of the display window. In other words, it is the point in the text value where, if the text is displayed from that point forward, you will hit the end of the text when you hit the end of the window. In other words, it is the point where you start to display text when you are displaying the last page.

    The para/scroll/y value is going to vary from zero (the top of the text) to the result of the above calculation (the last page), as you operate the scroller. That is why the (user-data minus size/y) result is multiplied by the data value of the scroller (which is a fraction in the range of zero to one). Somewhere in that range of zero through (user-data minus size/y) is where we want to start displaying a window of text.

    The reason for the max function is that it could happen that the text is SMALLER than the window. In that case, (user-data minus size/y) will be negative (and will be negated later giving a positive value), and we don't want that. Instead, we want to display from the top all the time, and thus want para/scroll/y to be zero.

    We negate the para/scroll/y value because we are going "down" the text in a negative y direction.

    This came to me on the bus on the way home yesterday. Now that I go through it all in detail, it seems so simple that I wonder what all the fuss was.
  4. MaxV

    MaxV Member

    First of all, if you use rebgui.r, scroller are easier and automatic.
    However the cookbook is the following:http://www.rebol.net/cookbook/recipes/0029.html , right?
    Well, to understand the code, let's analyze the code, step by step:
    out: is the layout, you have to focal to 2 elements t1 and s1
    t1: is a simple text area.
    s1: is the scroller. A scroller has a value from 0 (beginning, top) to 1 (end, bottom). Every time the scrolled is used (clicked) what happens? [scroll-tface t1 s1], i.e. the function scroll-tface is launched with 2 arguments: t1 and s1.
    scroll-tface: this function do only one thing:
    set the offset of text vertically, so the text scroll. How much move the offset of text?
    To move down the text, we nned a negative value. txt/user-data is 300, the height of the box. So the formula is about:
    -( 0.x * text_length )
    Where 0.x is the percentage of where you place the scroller rectangle (0.1 , 0.2, 0.5, etc.). ;)

Share This Page