root/widgets/table.r

Revision 113, 9.6 kB (checked in by cyphre, 6 weeks ago)

-fixed keyboard focus when selecting a row

Line 
1table: make rebface [
2        tip:    {
3                USAGE:
4                        table options ["Name" left .6 "Age" right .4] data ["Bob" 32 "Pete" 45 "Jack" 29]
5
6                DESCRIPTION:
7                        Columns and rows of values formatted according to a header definition block.
8
9                OPTIONS:
10                        'multi allows multiple rows to be selected at once
11                        'no-dividers hides column dividers
12                        ["Title" align width] triplets for each column
13        }
14        size:   50x25
15        pane:   []
16        data:   []
17        edge:   default-edge
18        ;       widget facets
19        redraw: make function! [] []    ; place-holder for examine
20        selected: make function! [] []  ; place-holder for examine
21        picked: []
22        widths: []
23        aligns: []
24        cols:   none
25        rows:   make function! [] [pane/1/rows]
26        ;BEG fixed by Cyphre, sponsored by Robert       
27        total-width: none
28
29        add-row: func [
30                row [block!]
31                /position
32                        pos [integer!]
33        ][
34                either pos [
35                        pos: (pos - 1) * cols
36                ][
37                        pos: 1 + length? data
38                ]
39                insert at data pos row
40                redraw
41        ]
42       
43        remove-row: func [
44                row [integer! block!]
45                /local rows removed
46        ][
47                if integer? row [row: to-block row]
48                rows: sort/reverse copy row
49                repeat n length? rows [
50                        row: max 1 min rows/:n (length? data) / cols
51                        remove/part skip data (row - 1) * cols cols
52                ]
53                redraw
54        ]
55       
56        alter-row: func [
57                row [integer! block!]
58                values [block!]
59                /local rows last-picked
60        ][
61                last-picked: copy picked
62                if integer? row [row: to-block row]
63                rows: row
64                if (length? rows) <> (length? values) [
65                        values: reduce [values]
66                ]
67                if (length? rows) = (length? values) [
68                        repeat n length? rows [
69                                row: max 1 min rows/:n (length? data) / cols
70                                change skip data (row - 1) * cols copy/part values/:n cols
71                        ]
72                ]               
73                redraw
74                unless empty? last-picked [select-row/no-action last-picked]
75        ]
76
77        select-row: func [
78                row [integer! none! block!]
79                /no-action
80                /local rows lines
81        ][
82                clear picked
83                ;       #45 AGT handle none! case
84                if row [
85                        row: either integer? row [to block! row] [sort copy row]
86                        rows: pane/1/rows
87                        lines: pane/1/lines
88                        foreach r row [
89                                r: max 1 min rows r
90                                insert picked r
91                        ]
92                        if any [
93                                row/1 < (pane/1/scroll + 1)
94                                row/1 > (pane/1/scroll + pane/1/lines)
95                        ][
96                                pane/1/pane/2/data: 1 / (rows - lines) * ((min (rows - lines + 1) row/1) - 1)
97                        ]
98                        unless no-action [action/on-click self]
99                ]
100                ;activate the table keys control - Cyphre
101                system/view/caret: pane/1/pane/1/text
102                system/view/focal-face: pane/1/pane/1
103                show self
104        ]
105
106        set-columns: func [
107                options [block!]
108                /no-show
109                /no-dividers
110                /local col-offset p last-col dividers?
111        ] [
112                p: self
113
114                if (length? pane) > 2 [
115                        remove/part next pane 2 * cols - 1
116                ]
117                clear widths
118                clear aligns
119               
120                cols: (length? options) / 3
121                p/pane/1/cols: cols
122                p/pane/1/data: p/data
123                                                               
124                col-offset: total-width: 0
125                foreach [column halign width] options [
126                        unless any [string? column word? column] [
127                                gui-error "Table expected column name to be a string or word"
128                        ]
129                        unless find [left center right] halign [
130                                gui-error "Table expected column align to be one of left, center or right"
131                        ]
132                        unless decimal? width [
133                                gui-error "Table expected column width to be a decimal"
134                        ]
135                        insert tail aligns halign
136                        insert tail widths width: to integer! p/size/x * width
137                        total-width: total-width + width
138
139                        insert back tail pane make subface [
140                                offset: as-pair col-offset 0
141                                size:   as-pair width - sizes/cell sizes/line
142                                text:   form column     
143                                color:  colors/theme-dark
144                                col:    length? widths
145                                para:   make default-para [margin: as-pair sizes/line + 2 2]
146                                ;BEG fixed by Cyphre, sponsored by Robert
147                                font: make default-font-heading [align: aligns/:col]
148                                ;END fixed by Cyphre, sponsored by Robert
149                                feel:   make default-feel [
150                                        over: make function! [face act pos] [
151                                                face/color: either act [colors/theme-light] [colors/theme-dark]
152                                                show face
153                                        ]
154                                        engage: make function! [face act event /local arrow] [
155                                                if act = 'down [
156                                                        arrow: last parent-face/pane
157                                                        unless arrow/col = col [
158                                                                arrow/col: col
159                                                                arrow/asc: none
160                                                                arrow/offset/x: offset/x + size/x - (sizes/cell * 3)
161                                                        ]
162                                                        arrow/action arrow
163                                                ]
164                                        ]
165                                ]
166                        ]
167                        col-offset: col-offset + width
168                        ;       resize dragger
169                        if cols > length? widths [
170                                insert back tail pane make subface [
171                                        offset: as-pair col-offset - sizes/cell 0
172                                        ;BEG fixed by Cyphre, sponsored by Robert
173                                        size:   as-pair 2 either no-dividers [sizes/line] [p/size/y]
174                                        ;END fixed by Cyphre, sponsored by Robert
175                                        color:  colors/outline-dark
176                                        span:   unless no-dividers [all [p/span find p/span #H #H]] ; AGT resize bars if needed
177                                        col-1:  length? widths
178                                        col-2:  1 + length? widths
179                                        feel:   make default-feel [
180                                                over: make function! [face act pos] [
181                                                        color: either act [colors/state-dark] [colors/outline-dark]
182                                                        show face
183                                                ]
184                                                engage: make function! [face act event /local delta arrow] [
185                                                        switch/default act [
186                                                                down    [data: event/offset/x]
187                                                                up              [data: none feel/over face false 0x0]
188                                                                alt-up  [data: none feel/over face false 0x0]
189                                                        ][
190                                                                if all [
191                                                                        data
192                                                                        event/type = 'move
193                                                                        event/offset/x <> data
194                                                                ] [
195                                                                        delta: event/offset/x - data
196                                                                        delta: either positive? delta [
197                                                                                min delta parent-face/pane/(col-2 * 2)/size/x - (sizes/line * 2)
198                                                                        ][
199                                                                                max delta negate parent-face/pane/(col-1 * 2)/size/x - (sizes/line * 2)
200                                                                        ]
201                                                                        unless zero? delta [
202                                                                                arrow: last parent-face/pane
203                                                                                if arrow/col = col-1 [arrow/offset/x: arrow/offset/x + delta]
204                                                                                ;       move dragger bar
205                                                                                offset/x: offset/x + delta
206                                                                                ;       adjust column widths
207                                                                                widths/:col-1: widths/:col-1 + delta
208                                                                                widths/:col-2: widths/:col-2 - delta
209                                                                                ;       adjust heading widths and offset
210                                                                                parent-face/pane/(col-1 * 2)/size/x: widths/:col-1 - sizes/cell
211                                                                                parent-face/pane/(col-2 * 2)/offset/x: offset/x + sizes/cell
212                                                                                either cols = col-2 [
213                                                                                        parent-face/pane/(col-2 * 2)/size/x: widths/:col-2
214                                                                                ][
215                                                                                        parent-face/pane/(col-2 * 2)/size/x: widths/:col-2 - sizes/cell
216                                                                                ]
217                                                                                ;       show changes
218                                                                                show parent-face
219                                                                        ]
220                                                                ]
221                                                        ]
222                                                ]
223                                        ]
224                                ]
225                        ]
226                ]
227                ;       reassign options
228                p/options: pane/1/options
229                ;       is total-width OK
230                last-col: first back back tail pane
231                last-col/size/x: last-col/size/x + sizes/cell + size/x - total-width
232                if negative? last-col/size/x [
233                        gui-error "Table column widths are too large"
234                ]
235                widths/:cols: widths/:cols + size/x - total-width
236                ;       is last label resizeable?
237                if all [span find span #W] [
238                        last-col/span: #W
239                ]
240                ;       init iterator *after* we know align
241                pane/1/init
242                unless no-show [
243                        show self
244                ]
245        ]
246        ;END fixed by Cyphre, sponsored by Robert       
247        init:   make function! [/local p opts dividers?] [
248                ;       default options
249                opts: [table]
250                if 'multi = first options [remove options insert tail opts 'multi]
251                dividers?: either 'no-dividers = first options [remove options false] [true]
252                if 'multi = first options [remove options insert tail opts 'multi]
253                ;       basic options and data validation
254                unless integer? cols: divide length? options 3 [
255                        gui-error "Table has an invalid options block"
256                ]
257                if all [not empty? data decimal? divide length? data cols] [
258                        gui-error "Table has an invalid data block"
259                ]
260                ;       face iterator
261                p: self
262                insert tail pane make face-iterator [
263                        offset:         as-pair 0 sizes/line
264                        size:           p/size - as-pair 0 sizes/line
265                        span:           either p/span [copy p/span] [none]
266                        data:           p/data
267                        cols:           p/cols
268                        widths:         p/widths                                                ; share widths
269                        aligns:         p/aligns                                                ; share aligns
270                        options:        opts
271                        picked:         p/picked                                                ; share picked block
272                        action:         get in p/action 'on-click               ; share action func
273                        alt-action:     get in p/action 'on-alt-click   ; share alt-action func
274                        dbl-action:     get in p/action 'on-dbl-click   ; share dbl-action func
275                ]
276                ;BEG fixed by Cyphre, sponsored by Robert               
277                ;       arrow
278                insert tail pane make subface [
279                        offset: as-pair negate sizes/line sizes/cell
280                        size:   as-pair sizes/cell * 3 sizes/cell * 3
281                        effect: [arrow black rotate 0]
282                        cols:   p/cols
283                        col:    none
284                        asc:    true
285                        feel:   make default-feel [
286                                engage: make function! [face act event] [
287                                        all [act = 'down face/action face]
288                                ]
289                        ]
290                        action: make function! [face /local last-selected] [
291                                asc: either none? asc [true] [complement asc]
292                                effect/rotate: either asc [0] [180]
293                                ;BEG fixed by Cyphre, sponsored by Robert
294                                last-selected: selected
295                                ;END fixed by Cyphre, sponsored by Robert
296                                either asc [
297                                        sort/skip/compare parent-face/data cols col
298                                ][
299                                        sort/skip/compare/reverse parent-face/data cols col
300                                ]
301                                ;BEG fixed by Cyphre, sponsored by Robert
302                                all [
303                                        last-selected
304                                        select-row/no-action (((index? find parent-face/data last-selected) - 1) / cols) + 1
305                                ]
306                                ;END fixed by Cyphre, sponsored by Robert
307                                show parent-face
308                        ]
309                ]
310                ;       column headings
311                either dividers? [set-columns/no-show options] [set-columns/no-show/no-dividers options]
312                ;END fixed by Cyphre, sponsored by Robert
313                ;       accessors
314                redraw: get in pane/1 'redraw
315                selected: get in pane/1 'selected
316                ;       feel
317                feel: make default-feel [
318                        redraw: make function! [face act pos /local total arrow] [
319                                if act = 'show [
320                                        total: 0
321                                        foreach width widths [total: total + width]
322                                        widths/:cols: widths/:cols + size/x - total
323                                        ;       is arrow on last col
324                                        arrow: last pane
325                                        if arrow/col = cols [arrow/offset/x: size/x + sizes/cell - sizes/line]
326                                ]
327                        ]
328                ]
329        ]
330]
Note: See TracBrowser for help on using the browser.