REBOL [
    title: "Resizeable Table/Grid/Multi-column List Widget Example"
    date: 13-Jul-2011 
    file: %table-grid-list.r
    author: Nick Antonaccio 
    purpose: {
        One of the greatest things about REBOL/View is the built in GUI dialect
            ("VID").  It's great for building simple GUI layouts quickly and
            easily, but the native list widget can be confusing for newcomers.
        THIS EXAMPLE IS A FULL FEATURED TABLE/GRID/LIST WIDGET FOR VID GUIs.
            KEYS:  INSERT  DELETE  ARROWS  PAGE UP/DOWN  - +  F1  CTRL+R M S O F U
            MOUSE: click header to sort, RIGHT-CLICK/DRAG to RESIZE, click to edit
        Columns can be SORTED and *RESIZED* by clicking the headers.  Data can be
            EDITED by clicking cells.  Rows can be added, removed, and moved with
            the INSERT, DELETE, and CTRL+M keys.  Data blocks can be loaded and
            saved to/from files, in both "flattened" and sub-block formats, using
            the CTRL+S CTRL+L CTRL+F and CTRL+U keys.  Column format (color, font,
            etc.) can be easily specified in the column code.  Alternate rows are
            automatically shaded, and mousing-over a row highlights the current
            row.  Up and down arrow keys, and page up/down keys can be used to
            scroll.  The mouse can also be used to scroll (with the scroll bar).
            Data can be reverted to the last saved change (by clicking the "r"
            button in the GUI).  The entire grid can be resized to any percentage,
            with automatic sizing of columns (use the "+" and "-" keys to resize
            this example).  The entire grid size will also automatically adjust to
            fit a resized screen.  Press [F1] for help.
        The compressed code adds all necessary functionality to VID's native list
            widget - paste it as-is into your script (uncompress to see how it
            works, or to make changes).
        Keep the variables and naming coventions as they are in the GUI code (the
            variables gui, gui-size, t-size, x, y, li, list-size, sl, sl-size,
            s-pos, and my-supply need to be changed in the compressed code if ever
            changed in the GUI layout).
        You can add as many columns as needed to your own GUI grids:
            Headers must be labeled h1, h2, h3...  Put DIFFERENT TEXT in each.
            Columns must be labeled col1, col2, col3...  Format each as needed.
        "header-block" must be edited to contain each of the header labels (i.e.,
            if your table has headers h1, h2, and h3, the header block should be
            [h1/text h2/text h3/text]).
        "x" holds the data displayed in the table - you can save, load, and
            manipulate it directly, then refresh the display (try the CTRL+S and
            CTRL+O keys in the GUI example to save and load the grid data).
        Rows of data are each stored in a SEPARATE block within the "x" block.
            To "flatten" the block (i.e., to save the grid data in one large
            block, without sub-blocks), try the CTRL+F keys in this GUI example.
            To load a flattened block, try the CTRL+U keys.
        "y" holds a copy of the original data (click the "r" button in the GUI
            example to reload it and refresh the display to its last saved state).
        "feel editstyle" is used to make a column EDITABLE.  Click any cell in the
            GUI example to edit.  These changes are made directly to the "x" block
            and then the GUI is refreshed.
        "feel slidestyle" is used to make a column RESIZABLE (RIGHT CLICK/drag the 
            header to expand or contract any column width).  This function also
            contains the "sort-column" function, which allows the user to sort
            columns of data by clicking the header.
        "sort-column" sorts the selected column number.  Each call to this
            function alternates between ascending and descending sort order.
        "key-scroll" enables keyboard scrolling (use the up/down cursor keys, and
            page up/down keys in this GUI example).
        "add-line" adds a row of data to the grid, at a chosen index (use the
            [INSERT] key in this GUI example).
        "remove-line" removes a selected row of data (use the [DELETE] key in this
            GUI example).
        "move-line" moves a row of data from one selected index to another (use
            the CTRL+M keys in this GUI example to move rows).
        "resize-fit" resizes the table to fit the GUI, with equally sized columns.
            The compressed code contains an insert-event-function which 
            automatically resizes the table to fit the GUI window, when resized.
            Press CTRL+R in this GUI example to execute the function manually.
        "resize-grid" resizes the table a given percentage (press the "+" and "-"
            keys in this GUI example to see it work).
        Notice that the majority of user-editable code in the GUI consists of
            headers, column names and formatting, and "key" widgets to run the
            desired functions.  In this example GUI, the user presses keystroke
            combinations to activate the desired features, but those functions
            could also be added to the action blocks of buttons, and/or executed
            by any other typical trigger.
    }
]

notify {
    Be sure to RIGHT-CLICK AND DRAG headers to RESIZE COLUMNS.
    Click headers to sort columns.
    You can also insert, delete, and move rows, click cells to edit,
    resize the grid, scroll with keyboard and mouse, save and load
    all data to/from files, and more.  Create your own tables with
    all the same features by editing just a few lines.
    Press F1 for more info.
}

x: copy []             ; The data shown in the grid is labeled "x", by default
random/seed now/time   ; Generate 5000 rows of random data:
repeat i 5000 [
    append/only x reduce [
        random "abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*(),.';" 
        form random 1000 
        form random 1000 
        random "abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*(),.';"
        form i
    ]                  ; all data is stored in string format
]  y: copy x           ; "y" holds a backup copy of the original grid data

header-block: [h1/text h2/text h3/text h4/text h5/text] ; EDITED FOR 5 COLUMNS

do decompress list-widget-functions: #{
789CAD574B6F1B3710BEFB570CD443B50D362B1971806EFD407F402EB90A3AD0
DA59890D45AEB95C5B4AE0FFDE21B9A448594214B7060C899C996F1E9C977AA5
4DB95262D8CA1ADA41AE60D17214CD121657407FC8CD0635F4964DE906750D52
99E43CF2D93F7B59ADD4B6631A6137A2317824AC2933C0C02117700FF6F8381E
974E7EF90E9CDB9338E03EFB8D7A01C1AF9657DF705FF62BAD84080EFA53C9B6
6A902628EECB4EF5B5FF800F90F13806DE8E44325FA05C9BCD03EC0A42F382F1
6A9973DFC22CF2CC3CAD1755C30C0BCAAA0C2F337FFCD20BF24363CFBF63B9D6
BC098E74A857280D5B63F0623DF0D2B211F6BE37B8AD9E39BE54E40CA22C5BB6
C2AA6312AB796599E02F28613EDBCD9CA8E0BD71B2D5BC4E0FF0071CF41C715E
D75163754D607FDE380633DAA029780D79978025CE6E9051FE948F42ADBE15C5
18995192516818D730FF9C6A733C83743E2929F65639F85367B8923D583309D3
7A0A82EDD5609C814E072C7C08978760B6DCD4D028ECDF133E2791BC0A4C632C
AC9FA9D7257C9C17A496354D29B8C4A0941952D299513B97CDAE06A34A4E4EAC
A9B4343E0D48280677A632DC08AC1A6CD9200C4CFE6E1A786682E84045A0294B
7EAB27B1845AA5B729927AD6E5EA90C85613DCD9CCD468062D7D5E4A7C293D64
0D2BD5ED61E1EF090C38CCCFBC1C1116ACEB905EFA00E0E52793B118648F54D2
EEC96CC9EE9C0145CA7F2858FB385BF58CFF57A0BE12AE51E041EB09FCB71811
C1E801E1F63E28A5CF7F1497B0987CF52A60021DA774F35EC2E461B2CC31BC29
592452F7DF38EF849468CA5FF2FB8BD5D16AB5FDA5E4B04F72819A11DEC63501
A7E04CA701C1C6AE004A9D6930DDDD1497C7F34B1ECD08F336A236641519E343
1A188BE84D3A0FB6340E86AE13FB3A1F71F88CF281F296FA3DCD405BEB341615
CDBB970D37B6C1A677D79F661FDDFFCD8DB7C0C9D5A3F807DFD9838352497C80
A73A3892EAB021AD43B500EEB88971199F85A276C2A8EB19299F250638A21F2B
AB38B312154EF7934D37DC51147AC11B0AF65E600C835C53838F4B008D594C87
32B73777F0FBD0D1383B2C0D1EF0816630D5BFC666A0C69BB607689DFE65C459
0DBE3DD7174AA6060459B8BF8353BD284F8AD46A264CD9A817CAAADE30673C2D
2F3560A5DAB6C7C43C6B4D49F930DAF823125CE1F6DF6923B0EFDC724D992A71
CD0C1532F53E8F488D3EC12F3261CA3BF71C61C4E667920CE8991445791ADC2E
A2ECA9DB4B102833E7C5E8F3314E4EBB1CED944D2985BE9F44DA9CB5EA1CE59C
4DC7FCC1A2D3F7E7EC711D627C94E305EC08C9EE0951F6357ED3D809CB92E510
FC38BCD46BCCE08B659CBE57C8CF27D3DB16E6A984A364CDAE63B21ED21F3286
46E5D644E2B86153F7C0869BAC7950FFD587D6A18E1AC75401B38B60E868D4EC
5BD7ABEC34182FEBF12A443E28F3265FDC9A324FDAB1F765F32B0C484F8C83E1
AD937E6B29ED5C30A5579D8C0A1A84FB0EAD5ABF0286EDD2EE94AEE393858E8F
26FACFD74A8750C26C7733BB8A8BE361B926D2E7D98EB6EB9F2DC8EFDABCC3AF
13C87EE6B9B10CF175AC4B57FF0285CB5B342E0E0000
}

svv/vid-face/color: white
view/options center-face gui: layout gui-block: [
    size gui-size  across  space 0x0
    style header button as-pair t-size 20 black white bold
    h1: header "Text1" feel slidestyle  ; EDIT THESE FOR YOUR OWN NEEDS.  EACH
    h2: header "Num1" feel slidestyle   ; HEADER MUST CONTAIN UNIQUE TEXT.
    h3: header "Num2" feel slidestyle   ; YOU CAN HAVE AS MANY OR AS FEW
    h4: header "Text2" feel slidestyle  ; COLUMNS AS NEEDED (ALL RESIZEABLE).
    h5: header "Key" feel slidestyle    ; THEY MUST BE LABELED:  H1, H2, H3...
    h6: button black "r" 17x20 [if true = request "Reset?"[x: copy y show li]]
    return
    li: list list-size [
        style cell text t-size feel editstyle    ; EVERY CELL IS NOW EDITABLE
        across  space 0x0
        col1: cell blue    ; EDIT THE LOOK AND FEEL OF EACH COLUMN AS NEEDED.
        col2: cell         ; COLUMNS MUST BE LABELED:  COL1, COL2, COL3...
        col3: cell red     ; THEY CONTAIN THE *DATA* LABELED BY HEADERS ABOVE.
        col4: cell blue    ; THEY ARE TYPICALLY TEXT FIELDS, BUT CAN BE ANY
        col5: cell         ; OTHER TYPE OF GUI WIDGET DESIRED.
    ] supply my-supply
    sl: scroller sl-size [s-pos: (length? x) * value  show li]
    key keycode [up] [key-scroll -1]         ; EACH OF THESE KEYS DEMONSTRATES
    key keycode [down] [key-scroll 1]        ; A FEATURE.  THESE FUNCTIONS
    key keycode [page-up] [key-scroll -20]   ; COULD ALSO BE ADDED TO THE
    key keycode [page-down] [key-scroll 20]  ; ACTION BLOCKS OF GUI BUTTONS OR
    key keycode [insert] [add-line]          ; OTHER WIDGETS, OR OTHERWISE
    key #"^~" [remove-line]                  ; ACTIVATED...
    key #"^M" [move-line]
    key #"^R" [resize-fit]
    key #"+" [resize-grid 1.333]
    key #"-" [resize-grid .75]
    key #"^S" [save to-file request-file/save x]
    key #"^O" [attempt [y: copy x: copy load request-file/only  show li]]
    key #"^F" [fx: copy [] foreach row x [append fx reduce row]save %f.txt fx]
    key #"^U" [attempt [  ; load a 'flattened' block
        fx: load request-file/only/file %f.txt
        x: copy [] foreach [a b c d e] fx [append/only x reduce [a b c d e]] 
        show li
    ]]
    key keycode [f1] [editor system/script/header/purpose]
] [resize]



; Here's a simpler, typical implementation:


REBOL [title: "Table/Grid/List Widget Example"]

x: copy [] random/seed now/time repeat i 1000 [append/only x reduce [random "abcdef" form random 1000 form i]] y: copy x

header-block: [h1/text h2/text h3/text] 

do decompress list-widget-functions: #{
789CAD574B6F1B3710BEFB570CD443B50D362B1971806EFD407F402EB90A3AD0
DA59890D45AEB95C5B4AE0FFDE21B9A448594214B7060C899C996F1E9C977AA5
4DB95262D8CA1ADA41AE60D17214CD121657407FC8CD0635F4964DE906750D52
99E43CF2D93F7B59ADD4B6631A6137A2317824AC2933C0C02117700FF6F8381E
974E7EF90E9CDB9338E03EFB8D7A01C1AF9657DF705FF62BAD84080EFA53C9B6
6A902628EECB4EF5B5FF800F90F13806DE8E44325FA05C9BCD03EC0A42F382F1
6A9973DFC22CF2CC3CAD1755C30C0BCAAA0C2F337FFCD20BF24363CFBF63B9D6
BC098E74A857280D5B63F0623DF0D2B211F6BE37B8AD9E39BE54E40CA22C5BB6
C2AA6312AB796599E02F28613EDBCD9CA8E0BD71B2D5BC4E0FF0071CF41C715E
D75163754D607FDE380633DAA029780D79978025CE6E9051FE948F42ADBE15C5
18995192516818D730FF9C6A733C83743E2929F65639F85367B8923D583309D3
7A0A82EDD5609C814E072C7C08978760B6DCD4D028ECDF133E2791BC0A4C632C
AC9FA9D7257C9C17A496354D29B8C4A0941952D299513B97CDAE06A34A4E4EAC
A9B4343E0D48280677A632DC08AC1A6CD9200C4CFE6E1A786682E84045A0294B
7EAB27B1845AA5B729927AD6E5EA90C85613DCD9CCD468062D7D5E4A7C293D64
0D2BD5ED61E1EF090C38CCCFBC1C1116ACEB905EFA00E0E52793B118648F54D2
EEC96CC9EE9C0145CA7F2858FB385BF58CFF57A0BE12AE51E041EB09FCB71811
C1E801E1F63E28A5CF7F1497B0987CF52A60021DA774F35EC2E461B2CC31BC29
592452F7DF38EF849468CA5FF2FB8BD5D16AB5FDA5E4B04F72819A11DEC63501
A7E04CA701C1C6AE004A9D6930DDDD1497C7F34B1ECD08F336A236641519E343
1A188BE84D3A0FB6340E86AE13FB3A1F71F88CF281F296FA3DCD405BEB341615
CDBB970D37B6C1A677D79F661FDDFFCD8DB7C0C9D5A3F807DFD9838352497C80
A73A3892EAB021AD43B500EEB88971199F85A276C2A8EB19299F250638A21F2B
AB38B312154EF7934D37DC51147AC11B0AF65E600C835C53838F4B008D594C87
32B73777F0FBD0D1383B2C0D1EF0816630D5BFC666A0C69BB607689DFE65C459
0DBE3DD7174AA6060459B8BF8353BD284F8AD46A264CD9A817CAAADE30673C2D
2F3560A5DAB6C7C43C6B4D49F930DAF823125CE1F6DF6923B0EFDC724D992A71
CD0C1532F53E8F488D3EC12F3261CA3BF71C61C4E667920CE8991445791ADC2E
A2ECA9DB4B102833E7C5E8F3314E4EBB1CED944D2985BE9F44DA9CB5EA1CE59C
4DC7FCC1A2D3F7E7EC711D627C94E305EC08C9EE0951F6357ED3D809CB92E510
FC38BCD46BCCE08B659CBE57C8CF27D3DB16E6A984A364CDAE63B21ED21F3286
46E5D644E2B86153F7C0869BAC7950FFD587D6A18E1AC75401B38B60E868D4EC
5BD7ABEC34182FEBF12A443E28F3265FDC9A324FDAB1F765F32B0C484F8C83E1
AD937E6B29ED5C30A5579D8C0A1A84FB0EAD5ABF0286EDD2EE94AEE393858E8F
26FACFD74A8750C26C7733BB8A8BE361B926D2E7D98EB6EB9F2DC8EFDABCC3AF
13C87EE6B9B10CF175AC4B57FF0285CB5B342E0E0000
}
svv/vid-face/color: white
view/options center-face gui: layout gui-block: [
    size gui-size  across  space 0x0
    style header button as-pair t-size 20 black white bold
    h1: header "Text" feel slidestyle
    h2: header "Num" feel slidestyle
    h3: header "Key" feel slidestyle
    button black "r" 17x20 [if true = request "Reset?"[x: copy y show li]]
    return
    li: list list-size [
        style cell text t-size feel editstyle  across  space 0x0
        col1: cell blue
        col2: cell
        col3: cell red
    ] supply my-supply
    sl: scroller sl-size [s-pos: (length? x) * value  show li]
    key keycode [up] [key-scroll -1]
    key keycode [down] [key-scroll 1]
    key keycode [page-up] [key-scroll -20]
    key keycode [page-down] [key-scroll 20]
    key keycode [insert] [add-line]
    key #"^~" [remove-line]
    key #"^M" [move-line]
    key #"^S" [save to-file request-file/save x]
    key #"^O" [attempt [y: copy x: copy load request-file/only  show li]]
] [resize]