root/rebgui.r

Revision 118, 138.3 kB (checked in by ashley, 5 weeks ago)

Button color fix

Line 
1REBOL[version: 118]
2if system/version < 1.3.2[make error! "RebGUI requires View 1.3.2 or greater"]
3unless value? 'viewed?[
4find-window: make function![
5"Find a face's window face."
6face[object!]
7][
8while[face/parent-face][face: face/parent-face]
9face
10]
11viewed?: make function![
12"Returns TRUE if face is displayed."
13face[object!]
14][
15found? find system/view/screen-face/pane find-window face
16]
17]
18system/locale: make system/locale[
19colors:[black navy blue violet forest maroon coffee purple reblue coal oldrab red brick crimson leaf brown aqua teal magenta sienna water olive papaya mint gray rebolor green orange pewter base-color khaki cyan tan silver pink sky gold wheat yellow yello beige snow linen ivory white]
20words:[]
21language: "English"
22dictionary: none
23dict: none
24]
25ctx-rebgui: make object![
26build: 118
27view*: system/view
28locale*: system/locale
29find-face: make function![pnt[pair!]f[object! block!]/local p result][
30all[
31object? :f
32f/show?
33within? pnt win-offset? f f/size
34return f
35]
36p: either object? :f[get in f 'pane][:f]
37either block? :p[
38result: none
39foreach face head reverse copy p[
40if all[object? :face face/show? face: find-face pnt face][
41result: face
42break
43]
44]
45result
46][
47all[object? :p find-face pnt :p]
48]
49]
50subface: make system/standard/face[
51color: edge: font: para: feel: none
52]
53all-chars: make string! 256
54repeat i 256[insert tail all-chars to char! i - 1]
55font?: make function![
56font-name[string!]
57][
58all[font-name = font-sans-serif return true]
59(size-text make subface[text: all-chars font: make view*/screen-face/font[name: font-sans-serif]]) <>
60(size-text make subface[text: all-chars font: make view*/screen-face/font[name: font-name]])
61]
62gui-error: make function![
63error[string!]
64/continue
65][
66write/append/lines %rebgui.log reform[now/date now/time error]
67unless continue[make error! error]
68]
69span-resize: make function![face[object!]delta[pair!]][
70if face/span[
71face/old-size: face/size
72all[find face/span #X face/offset/x: face/offset/x + delta/x]
73all[find face/span #Y face/offset/y: face/offset/y + delta/y]
74all[find face/span #W face/size/x: face/size/x + delta/x]
75all[find face/span #H face/size/y: face/size/y + delta/y]
76all[face/old-size <> face/size object? get in face 'action face/action/on-resize face]
77]
78any[
79if block? get in face 'pane[foreach f face/pane[span-resize f delta]]
80if object? get in face 'pane[span-resize face/pane delta]
81]
82]
83span-size: make function![face[object!]size[pair!]margin[pair!]][
84if face/span[
85all[
86find face/span #L
87face/size/x: size/x - face/offset/x - margin/x
88all[find[drop-list edit-list]face/type face/pane/offset/x: face/size/x - sizes/line + 1]
89]
90all[find face/span #V face/size/y: size/y - face/offset/y - margin/y]
91all[face/old-size <> face/size object? get in face 'action face/action/on-resize face]
92if find face/span #O[
93face/offset/x: either any[zero? face/offset/y size/y = (face/offset/y + face/size/y)][
94size/x - face/size/x
95][
96size/x - face/size/x - margin/x
97]
98]
99]
100if block? get in face 'pane[
101either face/type = 'tab-panel[
102foreach f face/pane[span-size f face/size 0x0]
103][
104foreach f face/pane[span-size f face/size face/pane/1/offset]
105]
106]
107if object? get in face 'pane[span-size face/pane face/size face/pane/offset]
108]
109unview-keep: make function![num[integer!]/local pane][
110pane: head view*/screen-face/pane
111while[(length? pane) > num][remove back tail pane]
112show view*/screen-face
113]
114words:[after at bold button-size data do edge effect feel field-size font indent italic label-size margin on on-alt-click on-away on-click on-dbl-click on-edit on-focus on-key on-over on-resize on-scroll on-unfocus options pad para rate return reverse space text-color text-size tight tip underline]
115select-face: make function![face][
116face/color: colors/state-light
117face/font/color: colors/page
118show face
119]
120deselect-face: make function![face /fill][
121face/color: either fill[colors/page][none]
122face/font/color: colors/text
123show face
124]
125colors: construct/with either exists? %ui.dat[pick load %ui.dat 3][[]]make object![
126page: ivory
127text: coal
128theme-light: 195.221.127
129theme-dark: 136.187.0
130state-light: 255.204.127
131state-dark: 255.153.0
132outline-light: 204.204.204
133outline-dark: 136.136.136
134]
135sizes: construct/with either exists? %ui.dat[pick load %ui.dat 6][[]]make object![
136cell: 4
137edge: 1
138font: 12
139font-height: none
140gap: 2
141line: cell * 5
142margin: 4
143slider: cell * 4
144]
145behaviors: construct/with either exists? %ui.dat[pick load %ui.dat 9][[]]make object![
146action-on-enter:[drop-list edit-list field password spinner]
147action-on-tab:[field]
148caret-on-focus:[area]
149cyclic:[group-box panel sheet tab-panel]
150hilight-on-focus:[edit-list field password spinner]
151tabbed:[area button drop-list drop-tree edit-list field grid password spinner]
152]
153effects: construct/with either exists? %ui.dat[pick load %ui.dat 12][[]]make object![
154arrows-together: false
155radius: 5
156font: either font? "arial"["verdana"][font-sans-serif]
157fonts: sort reduce[font-sans-serif font-fixed font-serif "verdana"]
158splash-delay: 1
159tooltip-delay: 0:00:01
160webdings: font? "webdings"
161window: none
162]
163on-fkey: make object![
164f1: f2: f3: f4: f5: f6: f7: f8: f9: f10: f11: f12: none
165]
166edit: make object![
167siblings: none
168caret: none
169letter: make bitset![#"A" - #"Z" #"a" - #"z" #"'"]
170capital: make bitset![#"A" - #"Z"]
171other: negate letter
172edits: make function![
173words[block!]
174/local result ln w
175][
176result: copy[]
177foreach word words[
178repeat n ln: length? word[
179insert tail result head remove at copy word n
180]
181repeat n ln - 1[
182insert tail result head change change at copy word n pick word n + 1 pick word n
183]
184foreach ch "abcdefghijklmnopqrstuvwxyz"[
185repeat n ln[
186poke w: copy word n ch
187insert tail result w
188]
189repeat n ln + 1[
190insert tail result head insert at copy word n ch
191]
192]
193]
194result
195]
196lookup-word: make function![
197word[string!]
198/local result
199][
200any[
201not empty? result: intersect locale*/dict make hash! word: reduce[word]
202not empty? result: intersect locale*/dict make hash! edits word
203result: word
204]
205sort result
206]
207insert?: true
208keymap:[
209#"^H" back-char
210#"^~" del-char
211#"^M" enter
212#"^A" all-text
213#"^C" copy-text
214#"^X" cut-text
215#"^V" paste-text
216#"^T" clear-tail
217#"^Z" undo
218#"^Y" redo
219#"^[" undo-all
220#"^S" spellcheck
221#"^/" ctrl-enter
222]
223hilight-text: make function![start end][
224view*/highlight-start: start
225view*/highlight-end: end
226]
227hilight-all: make function![face][
228either empty? face/text[unlight-text][
229view*/highlight-start: head face/text
230view*/highlight-end: tail face/text
231]
232]
233unlight-text: make function![][
234view*/highlight-start: view*/highlight-end: none
235]
236hilight?: make function![][
237all[
238object? view*/focal-face
239string? view*/highlight-start
240string? view*/highlight-end
241not zero? offset? view*/highlight-end view*/highlight-start
242]
243]
244hilight-range?: make function![/local start end][
245start: view*/highlight-start
246end: view*/highlight-end
247if negative? offset? start end[start: end end: view*/highlight-start]
248reduce[start end]
249]
250tabbed?: make function![
251face[object!]
252][
253all[
254face/show?
255find behaviors/tabbed face/type
256not find face/options 'info
257face
258]
259]
260cyclic?: make function![
261face[object!]
262][
263all[find behaviors/cyclic face/type face]
264]
265unfocus: make function![/local face][
266if face: view*/focal-face[
267if all[face/type <> 'face get in face/action 'on-unfocus][
268unless face/action/on-unfocus face[return false]
269]
270all[
271view*/caret
272in face 'caret
273face/caret: index? view*/caret
274]
275all[
276face/type = 'button
277face/feel/over face false none
278]
279]
280view*/focal-face: view*/caret: none
281unlight-text
282all[face show face]
283true
284]
285copy-selected-text: make function![/local start end][
286if hilight?[
287set[start end]hilight-range?
288write clipboard:// copy/part start end
289true
290]
291]
292delete-selected-text: make function![/local start end][
293if hilight?[
294set[start end]hilight-range?
295remove/part start end
296view*/caret: start
297view*/focal-face/line-list: none
298unlight-text
299true
300]
301]
302cut-text: make function![][
303undo-add face
304copy-selected-text face
305delete-selected-text
306]
307paste-text: make function![][
308undo-add face
309delete-selected-text
310face/line-list: none
311view*/caret: insert view*/caret read clipboard://
312]
313undo-max: 20
314undo-add: make function![face][
315if in face 'undo[
316insert clear face/undo at copy face/text index? view*/caret
317if all[undo-max undo-max < length? head face/undo][remove head face/undo]
318face/undo: tail face/undo
319]
320]
321undo-get: make function![face][
322face/text: head view*/caret: first face/undo
323face/line-list: none
324remove face/undo
325]
326word-limits: make bitset! {
327^-^M/[](){}"}
328word-limits: reduce[word-limits complement word-limits]
329current-word: make function![str /local s ns][
330unless string? str[gui-error/continue reform["Current word trap" type? str str]exit]
331set[s]word-limits
332s: any[all[s: find/reverse str s next s]head str]
333set[ns]word-limits
334ns: any[find str ns tail str]
335hilight-text s ns
336show view*/focal-face
337]
338next-word: make function![str /local s ns][
339set[s ns]word-limits
340any[all[s: find str s find s ns]tail str]
341]
342back-word: make function![str /local s ns][
343set[s ns]word-limits
344any[all[ns: find/reverse str ns ns: find/reverse ns s next ns]head str]
345]
346end-of-line: make function![str][
347any[find str "^/" tail str]
348]
349beg-of-line: make function![str /local nstr][
350either nstr: find/reverse str "^/"[next nstr][head str]
351]
352next-field: make function![face /wrap][
353unless face/parent-face[return none]
354unless find[object! block!]type?/word get in face/parent-face 'pane[
355return none
356]
357siblings: compose[(face/parent-face/pane)]
358unless wrap[siblings: find/tail siblings face]
359foreach sibling siblings[
360if target: any[
361tabbed? sibling
362into-widget/forwards sibling
363][
364return target
365]
366]
367all[
368not cyclic? face/parent-face
369target: next-field face/parent-face
370return target
371]
372all[
373target: next-field/wrap face
374return target
375]
376]
377back-field: make function![face /wrap][
378unless face/parent-face[return none]
379unless find[object! block!]type?/word get in face/parent-face 'pane[
380return none
381]
382siblings: reverse compose[(face/parent-face/pane)]
383unless wrap[siblings: find/tail siblings face]
384foreach sibling siblings[
385if target: any[
386tabbed? sibling
387into-widget/backwards sibling
388][
389return target
390]
391]
392all[
393not cyclic? face/parent-face
394target: back-field face/parent-face
395return target
396]
397all[
398target: back-field/wrap face
399return target
400]
401]
402into-widget: make function![
403{Recursivly returns the first tabbable face in parent's face pane tree.}
404face[object!]
405/forwards
406/backwards
407/local
408target children
409][
410unless find[object! block!]type?/word get in face 'pane[
411return none
412]
413unless face/show?[
414return none
415]
416children: compose[(face/pane)]
417catch[
418foreach child either backwards[reverse children][children][
419if target: any[
420tabbed? child
421either backwards[
422into-widget/backwards child
423][
424into-widget child
425]
426][
427throw target
428]
429]
430]
431]
432keys-to-insert: make bitset! #{
43301000000FFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
434}
435insert-char: make function![face char][
436delete-selected-text
437unless any[insert? tail? view*/caret "^/" = first view*/caret][remove view*/caret]
438insert view*/caret char
439view*/caret: next view*/caret
440]
441move: make function![event ctrl plain][
442either event/shift[
443any[view*/highlight-start view*/highlight-start: view*/caret]
444][unlight-text]
445view*/caret: either event/control ctrl plain
446if event/shift[
447either view*/caret = view*/highlight-start[unlight-text][view*/highlight-end: view*/caret]
448]
449]
450move-y: make function![face delta /local pos tmp tmp2][
451tmp: offset-to-caret face 0x2 + delta + pos: caret-to-offset face view*/caret
452tmp2: caret-to-offset face tmp
453either tmp2/y <> pos/y[tmp][view*/caret]
454]
455edit-text: make function![
456face event
457/local key edge para caret scroll page-up page-down face-size
458][
459face-size: face/size - either face/edge[2 * face/edge/size][0]
460key: event/key
461if char? key[
462either find keys-to-insert key[
463undo-add face
464insert-char face key
465][key: select keymap key]
466]
467if word? key[
468page-up:[move-y face face-size - sizes/font-height - sizes/font-height * 0x-1]
469page-down:[move-y face face-size - sizes/font-height * 0x1]
470do select[
471left[move event[back-word view*/caret][back view*/caret]]
472right[move event[next-word view*/caret][next view*/caret]]
473up[move event page-up[move-y face sizes/font-height * 0x-1]]
474down[move event page-down[move-y face sizes/font-height * 0x1]]
475page-up[move event[head view*/caret]page-up]
476page-down[move event[tail view*/caret]page-down]
477home[move event[head view*/caret][beg-of-line view*/caret]]
478end[move event[tail view*/caret][end-of-line view*/caret]]
479insert[either event/shift[paste-text][insert?: complement insert?]]
480back-char[
481undo-add face
482any[
483delete-selected-text
484head? view*/caret
485either event/control[
486tmp: view*/caret
487remove/part view*/caret: back-word tmp tmp
488][remove view*/caret: back view*/caret]
489]
490]
491del-char[
492undo-add face
493either event/shift[unless face/type = 'password[cut-text]][
494any[
495delete-selected-text
496tail? view*/caret
497either event/control[
498remove/part view*/caret back next-word view*/caret
499if tail? next view*/caret[remove back tail view*/caret]
500][remove view*/caret]
501]
502]
503]
504enter[
505either find behaviors/action-on-enter face/type[
506all[face/type = 'spinner face/action/on-unfocus face]
507set-focus face
508face/action/on-click face
509][
510undo-add face
511insert-char face "^/"
512]
513]
514ctrl-enter[undo-add face insert-char face tab]
515all-text[hilight-all face]
516copy-text[unless face/type = 'password[copy-selected-text face unlight-text]]
517cut-text[unless face/type = 'password[cut-text]]
518paste-text[paste-text]
519clear-tail[
520undo-add face
521remove/part view*/caret end-of-line view*/caret
522]
523undo[
524if all[in face 'undo not head? face/undo][
525insert face/undo at copy face/text index? view*/caret
526face/undo: back face/undo
527undo-get face
528]
529]
530redo[
531if all[in face 'undo not tail? face/undo][
532face/undo: insert face/undo at copy face/text index? view*/caret
533undo-get face
534]
535]
536undo-all[
537if in face 'esc[
538clear face/text
539all[in face 'undo clear face/undo]
540all[string? face/esc insert face/text face/esc]
541view*/caret: tail face/text
542]
543]
544spellcheck[
545request-spellcheck face
546]
547]key
548]
549edge: face/edge
550para: face/para
551scroll: face/para/scroll
552if error? try[
553caret: caret-to-offset face view*/caret
554if caret/y < (edge/size/y + para/origin/y + para/indent/y)[
555scroll/y: round/to scroll/y - caret/y sizes/font-height
556]
557if caret/y > (face-size/y - sizes/font-height)[
558scroll/y: round/to (scroll/y + ((face-size/y - sizes/font-height) - caret/y)) sizes/font-height
559]
560unless para/wrap?[
561if caret/x < (edge/size/x + para/origin/x + para/indent/x)[
562scroll/x: scroll/x - caret/x + (edge/size/x + para/origin/x + para/indent/x)
563]
564if caret/x > (face-size/x - para/margin/x)[
565scroll/x: scroll/x + (face-size/x - para/margin/x - caret/x)
566]
567]
568if scroll <> face/para/scroll[
569face/para/scroll: scroll
570if face/type = 'area[face/key-scroll?: true]
571]
572][gui-error/continue reform["Caret trap" face/type face/para]]
573show face
574]
575feel: make object![
576redraw: detect: over: none
577engage: func[face act event /local txt][
578do select[
579key[
580unless all[get in face/action 'on-key not face/action/on-key face event][
581txt: copy face/text
582edit-text face event
583all[
584get in face/action 'on-edit
585strict-not-equal? txt face/text
586face/action/on-edit face
587]
588]
589]
590down[
591either event/double-click[
592all[view*/caret not empty? view*/caret current-word view*/caret]
593][
594either face = view*/focal-face[
595unlight-text
596view*/caret: offset-to-caret face event/offset
597show face
598][
599caret: offset-to-caret face event/offset
600set-focus face
601]
602]
603]
604over[
605unless view*/caret = offset-to-caret face event/offset[
606unless view*/highlight-start[view*/highlight-start: view*/caret]
607view*/highlight-end: view*/caret: offset-to-caret face event/offset
608show face
609]
610]
611alt-up[face/action/on-alt-click face]
612scroll-line[face/action/on-scroll face event/offset]
613scroll-page[face/action/on-scroll/page face event/offset]
614]act
615]
616]
617]
618widgets: make object![
619rebind: make function![][
620default-edge/color: colors/text
621default-edge/size: as-pair sizes/edge sizes/edge
622theme-edge/color: colors/theme-dark
623theme-edge/size: default-edge/size
624outline-edge/color: colors/outline-light
625outline-edge/size: default-edge/size
626default-font/size: sizes/font
627default-font/name: effects/font
628default-font-bold: make default-font[style: 'bold]
629default-font-heading: make default-font[style: 'bold color: colors/page align: 'center shadow: 1x1]
630default-font-large: make default-font[size: sizes/font * 2]
631default-font-right: make default-font[align: 'right]
632default-font-top: make default-font[valign: 'top]
633default-para-indented/origin/x: sizes/line
634default-text/text: copy ""
635sizes/font-height: second size-text default-text
636foreach w next find first self 'choose[
637widgets/:w/rebind
638]
639]
640default-edge: make object![
641color: colors/text
642image: none
643effect: none
644size: as-pair sizes/edge sizes/edge
645]
646theme-edge: make default-edge[
647color: colors/theme-dark
648]
649outline-edge: make default-edge[
650color: colors/outline-light
651]
652default-font: make object![
653name: effects/font
654style: none
655size: sizes/font
656color: colors/text
657offset: 0x0
658space: 0x0
659align: 'left
660valign: 'middle
661shadow: none
662]
663default-font-bold: make default-font[
664style: 'bold
665]
666default-font-heading: make default-font[
667style: 'bold
668color: colors/page
669align: 'center
670shadow: 1x1
671]
672default-font-large: make default-font[
673size: sizes/font * 2
674]
675default-font-right: make default-font[
676align: 'right
677]
678default-font-top: make default-font[
679valign: 'top
680]
681default-para: make object![
682origin: 2x2
683margin: 2x2
684indent: 0x0
685tabs: 0
686wrap?: false
687scroll: 0x0
688]
689default-para-wrap: make default-para[
690origin: 2x0
691indent: 0x0
692wrap?: true
693]
694default-para-indented: make default-para[
695origin: as-pair sizes/line 2
696]
697default-feel: make object![
698redraw:
699detect:
700over:
701engage: none
702]
703default-action: make object![
704on-alt-click:
705on-away:
706on-click:
707on-dbl-click:
708on-edit:
709on-focus:
710on-key:
711on-over:
712on-resize:
713on-scroll:
714on-unfocus: none
715]
716set 'rebface make subface[
717feel: default-feel
718action: default-action
719options:[]
720rebind: init: tip: none
721]
722default-text: make rebface[
723size: 10000x10000
724text: ""
725font: default-font
726para: default-para
727]
728sizes/font-height: second size-text default-text
729date-spec:[
730tight
731symbol 9x6 data 'rewind[face/parent-face/data/year: face/parent-face/data/year - 1 show face/parent-face]
732symbol 9x6 data 'left[face/parent-face/data/month: face/parent-face/data/month - 1 show face/parent-face]
733symbol 34x6[set-data face/parent-face first face/parent-face/options]
734symbol 9x6 data 'right[face/parent-face/data/month: face/parent-face/data/month + 1 show face/parent-face]
735symbol 9x6 data 'forward[face/parent-face/data/year: face/parent-face/data/year + 1 show face/parent-face]
736return
737]
738foreach day locale*/days[
739insert tail date-spec compose[label 10 (copy/part day 3) font[align: 'center]]
740]
741insert tail date-spec[return bar]
742loop 6[
743insert tail date-spec 'return
744loop 7[
745insert tail date-spec[
746box 10x6 font[align: 'center valign: 'middle]edge[size: 0x0 color: colors/state-dark]feel[
747over: make function![face act pos][
748either all[act face/text][
749face/parent-face/data/day: to integer! face/text
750set-title face/parent-face form face/parent-face/data
751select-face face
752][deselect-face face]
753]
754engage: make function![face act event][
755all[
756act = 'down
757face/text
758face/parent-face/data/day: to integer! face/text
759poke face/parent-face/options 1 face/parent-face/data
760face/parent-face/action/on-click face/parent-face
761]
762all[
763find[up alt-up]act
764face/feel/over face false none
765]
766]
767]
768]
769]
770]
771face-iterator: make rebface[
772type: 'face-iterator
773pane:[]
774data:[]
775timeout: now/time/precise
776feel: make default-feel[
777redraw: make function![face act pos][
778if all[act = 'show face/size <> face/old-size][face/resize]
779]
780engage: make function![face act event /local i][
781if act = 'time[
782if (now/time/precise - face/timeout) > 0:00:00.2[
783face/action face
784face/rate: none
785show face
786]
787]
788if act = 'key[
789do select[
790#"^A"[
791if find face/options 'multi[
792clear face/picked
793repeat i face/rows[insert tail face/picked i]
794face/action face
795]
796]
797down[
798i: 1 + last face/picked
799if i <= face/rows[
800i: min face/rows i
801insert clear face/picked i
802if find[table text-list]face/parent-face/type[
803face/timeout: now/time/precise
804face/rate: 60
805if i > (face/scroll + face/lines)[
806face/pane/2/data: 1 / (face/rows - face/lines) * ((min (face/rows - face/lines + 1) (i - face/lines + 1)) - 1)
807face/scroll: face/scroll + 1
808]
809]
810]
811]
812up[
813i: -1 + last face/picked
814if i > 0[
815i: max 1 i
816insert clear face/picked i
817if find[table text-list]face/parent-face/type[
818face/timeout: now/time/precise
819face/rate: 60
820if i = face/scroll[
821face/pane/2/data: 1 / (face/rows - face/lines) * ((min (face/rows - face/lines + 1) i) - 1)
822face/scroll: face/scroll - 1
823]
824]
825]
826]
827#"^M"[
828all[find[table text-list]face/parent-face/type face/action face]
829]
830]event/key
831show face
832]
833]
834]
835lines: none
836rows: none
837cols: 1
838widths: none
839aligns: none
840picked:[]
841scroll: 0
842resize: make function![][
843lines: to integer! size/y / sizes/line
844pane/2/show?: either rows > lines[
845scroll: max 0 min scroll rows - lines
846true
847][
848scroll: 0
849false
850]
851]
852redraw: make function![][
853clear picked
854rows: either empty? data[0][(length? data) / cols]
855resize
856pane/2/ratio: either zero? rows[1][lines / rows]
857show self
858]
859selected: make function![/local blk][
860if empty? picked[return none]
861either any[find options 'multi parent-face/type = 'table][
862all[rows = length? picked return data]
863blk: copy[]
864either cols = 1[
865foreach row picked[insert tail blk pick data row]
866][
867foreach row picked[
868repeat col cols[
869insert tail blk pick data -1 + row * cols + col
870]
871]
872]
873blk
874][
875blk: pick data first picked
876]
877]
878init: make function![/local p][
879attempt[remove find span #X]
880attempt[remove find span #Y]
881lines: to integer! size/y / sizes/line
882rows: (length? data) / cols
883clear pane
884p: self
885insert pane make subface[
886size: p/size
887span: p/span
888pane: make function![face index /local col-offset clr][
889either integer? index[
890if index <= min lines rows[
891line/offset/y: index - 1 * sizes/line
892line/size/x: size/x
893index: index + scroll
894either p/parent-face/type = 'table[
895col-offset: 0
896repeat i p/cols[
897line/pane/:i/offset/x: col-offset
898line/pane/:i/size/x: p/widths/:i - sizes/cell
899all[
900p/pane/2/show?
901i = p/cols
902line/pane/:i/size/x: line/pane/:i/size/x + (p/size/x - p/pane/2/size/x - (line/pane/:i/offset/x + line/pane/:i/size/x))
903]
904line/pane/:i/text: replace/all form pick p/data index - 1 * cols + i "^/" "¶"
905line/pane/:i/font/color: either find p/options 'no-action[
906colors/text
907][
908either find picked index[colors/page][colors/text]
909]
910col-offset: col-offset + pick widths i
911]
912][
913line/text: replace/all form pick face/parent-face/data index "^/" "¶"
914line/font/color: either find p/options 'no-action[
915colors/text
916][
917either find picked index[colors/page][colors/text]
918]
919]
920line/color: either find p/options 'no-action[none][if find picked index[colors/theme-light]]
921if all[
922line/color = colors/theme-light
923face/parent-face/type = 'choose
924][face/parent-face/auto: pick face/parent-face/data index]
925line/data: index
926line
927]
928][to integer! index/y / sizes/line + 1]
929]
930text: ""
931line: make rebface[
932size: as-pair 0 sizes/line
933font: make default-font[]
934feel: make default-feel[
935over: make function![face into pos][
936if find face/parent-face/parent-face/options 'over[
937either into[insert clear picked data][clear picked]
938show face
939]
940]
941engage: make function![face act event /local p a b][
942p: face/parent-face
943either event/double-click[
944all[act = 'down p/parent-face/dbl-action p/parent-face]
945][
946if find[up alt-up]act[
947view*/focal-face: p
948view*/caret: tail p/text
949either find p/parent-face/options 'multi[
950unless any[event/control event/shift][clear picked]
951either all[event/control find picked data][
952remove find picked data
953][
954unless find picked data[insert tail picked data]
955]
956if all[event/shift 1 < length? picked][
957clear next picked
958repeat i (max data first picked) - (a: min data first picked) + 1[
959b: i + a - 1
960all[b <> first picked insert tail picked b]
961]
962]
963][insert clear picked data]
964show p
965unless find p/parent-face/options 'no-action[
966either act = 'up[
967p/parent-face/action p/parent-face
968][
969p/parent-face/alt-action p/parent-face
970]
971]
972]
973]
974]
975]
976]
977]
978if find options 'table[
979pane/1/line/pane: copy[]
980repeat i cols[
981insert tail pane/1/line/pane make subface[
982size: as-pair 0 sizes/line
983font: make default-font[align: aligns/:i]
984]
985]
986]
987insert tail pane make slider[
988tip: none
989offset: as-pair p/size/x - sizes/slider 0
990size: as-pair sizes/slider p/size/y
991span: case[
992none? p/span[none]
993all[find p/span #H find p/span #W][#XH]
994find p/span #H[#H]
995find p/span #W[#X]
996]
997options:[arrows]
998show?: either rows > lines[true][false]
999action: make default-action[
1000on-click: make function![face][
1001scroll: to integer! rows - lines * data
1002show face/parent-face
1003]
1004]
1005ratio: either rows > 0[lines / rows][1]
1006]
1007pane/2/init
1008]
1009]
1010choose: make function![
1011parent[object!]"Widget to appear in relation to"
1012width[integer!]"Width in pixels"
1013xy[pair!]"Offset of choice box"
1014items[block!]"Block of items to display"
1015/local popup result
1016][
1017result: none
1018popup: make face-iterator[
1019type: 'choose
1020offset: xy
1021size: as-pair width sizes/line * min length? items to-integer parent/parent-face/size/y - xy/y / sizes/line
1022color: colors/page
1023data: items
1024edge: outline-edge
1025feel: system/words/face/feel
1026options:[over]
1027action: make function![face][result: pick data first picked hide-popup]
1028alt-action: none
1029dbl-action: none
1030auto: none
1031]
1032popup/init
1033show-popup/window/away popup parent/parent-face
1034do-events
1035either parent/type = 'edit-list[popup/auto][result]
1036]
1037anim: make rebface[
1038tip:{USAGE:
1039anim data[%images/go-previous.png %images/go-next.png]
1040anim data[img1 img2 img3]rate 2
1041DESCRIPTION:
1042Cycles a set of images at a specified rate.}
1043size: -1x-1
1044effect: 'fit
1045feel: make default-feel[
1046engage: make function![face act event][
1047all[
1048act = 'time
1049face/image: first face/data
1050face/data: either tail? next face/data[head face/data][next face/data]
1051show face
1052]
1053]
1054]
1055rate: 1
1056init: make function![][
1057repeat i length? data: reduce data[
1058all[file? pick data i poke data i load pick data i]
1059]
1060image: first data
1061data: next data
1062all[negative? size/x size/x: image/size/x]
1063all[negative? size/y size/y: image/size/y]
1064]
1065]
1066pill: make rebface[
1067tip:{USAGE:
1068pill red
1069DESCRIPTION:
1070A rectangular area with rounded corners.}
1071size: 10x10
1072effect:[draw[pen none line-width sizes/edge fill-pen linear 0x0 0 0 90 1 1 none none none box 0x0 0x0 effects/radius]]
1073pen: none
1074fill: make function![][effect/draw/fill-pen]
1075feel: make default-feel[
1076redraw: make function![face act pos][
1077if act = 'show[
1078all[
1079face/color
1080poke face/effect/draw 13 face/color + 0.0.0.64
1081poke face/effect/draw 14 face/color + 0.0.0.32
1082poke face/effect/draw 15 face/color
1083face/color: none
1084]
1085]
1086]
1087]
1088action: make default-action[
1089on-resize: make function![face][
1090poke face/effect/draw 8 to integer! face/size/y * 0.25
1091poke face/effect/draw 9 to integer! face/size/y * 0.75
1092poke face/effect/draw 18 face/size - 1x1
1093poke face/effect/draw 19 either all[face/size/x > sizes/line face/size/y > sizes/line][effects/radius * 2][effects/radius]
1094]
1095]
1096init: make function![][
1097action/on-resize self
1098]
1099]
1100area: make rebface[
1101tip:{USAGE:
1102area
1103area "Text" -1
1104area "Text" 50x-1
1105DESCRIPTION:
1106Editable text area with wrapping and scroller.
1107OPTIONS:
1108'info specifies read-only}
1109size: 50x25
1110text: ""
1111color: colors/page
1112edge: theme-edge
1113font: default-font-top
1114para: make default-para-wrap[margin: as-pair sizes/slider + 2 2]
1115feel: make edit/feel[
1116redraw: func[face act pos /local height total visible][
1117if act = 'show[
1118if face/size <> face/old-size[
1119face/pane/offset/x: max 0 face/size/x - face/pane/size/x
1120face/pane/size/y: face/size/y
1121]
1122if any[
1123face/text-y <> height: second size-text face
1124face/size <> face/old-size
1125][
1126face/text-y: height
1127total: face/text-y
1128visible: face/size/y - (edge/size/y * 2) - para/origin/y - para/indent/y
1129face/pane/ratio: either total > 0[min 1 (visible / total)][1]
1130face/pane/step: either visible < total[min 1 (sizes/font-height / (total - visible))][0]
1131]
1132if all[face/pane/ratio < 1 face/key-scroll?][
1133do bind[
1134total: text-y
1135visible: size/y - (edge/size/y * 2) - para/origin/y - para/indent/y
1136pane/data: - para/scroll/y / (total - visible)
1137]face
1138face/key-scroll?: false
1139]
1140]
1141]
1142]
1143esc: none
1144caret: none
1145undo: copy[]
1146text-y: none
1147key-scroll?: false
1148action: make default-action[
1149on-scroll: make function![face scroll /page /local total visible][
1150total: second size-text face
1151visible: face/size/y - (face/edge/size/y * 2) - face/para/origin/y - face/para/indent/y
1152face/para/scroll/y: either page[
1153min max face/para/scroll/y - (visible * sign? scroll/y) (visible - total) 0
1154][
1155min max face/para/scroll/y - (scroll/y * sizes/font-height) (visible - total) 0
1156]
1157all[face/pane/data: - face/para/scroll/y / (total - visible)]
1158show face
1159]
1160]
1161rebind: make function![][
1162color: colors/page
1163para/margin/x: sizes/slider + 2
1164]
1165init: make function![/local p][
1166if find options 'info[
1167feel: make feel[engage: none]
1168all[color = colors/page color: colors/outline-light]
1169]
1170para: make para[]
1171p: self
1172text-y: second size-text self
1173all[negative? size/x size/x: 10000 size/x: 4 + first size-text self]
1174all[negative? size/y size/y: 10000 size/y: 8 + text-y]
1175pane: make slider[
1176tip: none
1177offset: as-pair p/size/x - sizes/slider 0
1178size: as-pair sizes/slider p/size/y
1179span: case[
1180none? p/span[none]
1181all[find p/span #H find p/span #W][#XH]
1182find p/span #W[#X]
1183find p/span #H[#H]
1184true[none]
1185]
1186options:[arrows]
1187action: make default-action[
1188on-click: make function![face /local visible][
1189unless parent-face/key-scroll?[
1190visible: (parent-face/size/y - (parent-face/edge/size/y * 2) - parent-face/para/origin/y - parent-face/para/indent/y)
1191parent-face/para/scroll/y: negate parent-face/text-y - visible * data
1192if all[
1193view*/caret
1194parent-face = view*/focal-face
1195][
1196]
1197show parent-face
1198]
1199parent-face/key-scroll?: false
1200]
1201]
1202ratio: p/size/y - 4 / text-y
1203]
1204pane/init
1205]
1206]
1207arrow: make rebface[
1208tip:{USAGE:
1209arrow
1210arrow 10
1211arrow data 'up
1212arrow data 'down
1213arrow data 'left
1214arrow data 'right
1215DESCRIPTION:
1216An arrow (default down) on a square button face with height set to width.}
1217size: 5x-1
1218data: 'down
1219feel: make default-feel[
1220redraw: make function![face act pos][
1221all[act = 'show face/color: either face/data[colors/state-light][colors/theme-light]]
1222]
1223engage: make function![face act event][
1224do select[
1225time[all[face/data face/action/on-click face]]
1226down[face/data: on]
1227up[face/data: off face/action/on-click face]
1228over[face/data: on]
1229away[face/data: off]
1230]act
1231show face
1232]
1233]
1234effect: reduce['arrow colors/page 'rotate 0]
1235rebind: make function![][effect/arrow: colors/page]
1236init: make function![][
1237all[negative? size/y size/y: size/x]
1238effect/rotate: select[up 0 right 90 down 180 left 270]data
1239data: off
1240]
1241]
1242bar: make rebface[
1243tip:{USAGE:
1244bar 100
1245DESCRIPTION:
1246A thin 3D bar used to separate widgets.
1247Defaults to maximum display width.}
1248size: -1x1
1249color: colors/outline-light
1250edge: make outline-edge[effect: 'bevel]
1251rebind: make function![][color: edge/color: colors/outline-light]
1252]
1253box: make rebface[
1254tip:{USAGE:
1255box red
1256DESCRIPTION:
1257The most basic of widgets, a rectangular area.}
1258size: 25x25
1259]
1260button: make pill[
1261tip:{USAGE:
1262button "Hello"
1263button -1 "Go!"
1264button "Click me!"[print "click"]
1265DESCRIPTION:
1266Performs action when clicked.
1267OPTIONS:
1268'info specifies read-only}
1269size: 15x5
1270text: ""
1271color: colors/theme-dark
1272data: color
1273font: default-font-heading
1274feel: make feel[
1275over: make function![face act pos][
1276set-color face either all[act not find face/options 'info][colors/theme-light][face/data]
1277]
1278engage: make function![face act event /local f][
1279unless find face/options 'info[
1280do select[
1281down[set-color face colors/state-light]
1282alt-down[set-color face colors/state-light]
1283up[set-color face colors/theme-dark face/action/on-click face]
1284alt-up[set-color face colors/theme-dark face/action/on-alt-click face]
1285away[set-color face face/data]
1286]act
1287]
1288]
1289]
1290rebind: make function![][
1291color: colors/theme-dark
1292]
1293init: make function![][
1294all[negative? size/x size/x: 10000 size/x: 8 + first size-text self]
1295all[find options 'info color = colors/theme-dark color: colors/outline-light]
1296data: color
1297action/on-resize self
1298]
1299]
1300calendar: make rebface[
1301tip:{USAGE:
1302calendar
1303calendar data 1-Jan-2000
1304DESCRIPTION:
1305Used to select a date, with face/data set to current selection.
1306Default selection is now/date.}
1307size: 70x48
1308feel: make default-feel[
1309redraw: make function![face act pos /local date month][
1310if act = 'show[
1311date: face/data
1312month: date/month
1313date/day: 1
1314date: date - date/weekday + 1
1315foreach sub-face skip face/pane 13[
1316sub-face/edge/size: 0x0
1317sub-face/text: either date/month = month[
1318all[date = first face/options sub-face/edge/size: 2x2]
1319form date/day
1320][none]
1321date: date + 1
1322]
1323face/pane/3/text: reform[pick locale*/months face/data/month face/data/year]
1324]
1325]
1326]
1327init: make function![][
1328insert options any[data now/date]
1329data: layout/only date-spec
1330pane: data/pane
1331size: data/size
1332data: first options
1333]
1334]
1335chat: make rebface[
1336tip:{USAGE:
1337chat 120 data["Bob" blue "My comment." yello 14-Apr-2007/10:58]
1338DESCRIPTION:
1339Three column chat display as found in IM apps such as AltME.
1340Messages are appended, with those exceeding 'limit not shown.
1341OPTIONS:
1342[limit n]where n specifies number of messages to show (default 100)
1343[id n]where n specifies id column width (default 10)
1344[user n]where n specifies user column width (default 15)
1345[date n]where n specifies date column width (default 25)}
1346size: 200x100
1347pane:[]
1348data:[]
1349edge: outline-edge
1350action: make default-action[
1351on-resize: make function![face][
1352poke face/pane/2/para/tabs 3 face/pane/1/size/x - (sizes/cell * any[select face/options 'date 25])
1353face/redraw/no-show
1354]
1355]
1356height: 0
1357rows: 0
1358limit: none
1359append-message: make function![
1360user[string!]
1361user-color[tuple! word! none!]
1362msg[string!]
1363msg-color[tuple! word! none!]
1364date[date!]
1365/no-show row
1366/local p y t1 t2 t3
1367][
1368t1: pick pane/2/para/tabs 1
1369t2: pick pane/2/para/tabs 2
1370t3: pick pane/2/para/tabs 3
1371y: max sizes/line 4 + second size-text make subface[
1372size: as-pair t3 - t2 10000
1373text: msg
1374font: default-font
1375para: default-para-wrap
1376]
1377p: self
1378insert tail pane/1/pane reduce[
1379make subface[
1380offset: as-pair 0 height
1381size: as-pair t1 y
1382text: form any[row rows: rows + 1]
1383color: colors/theme-dark
1384edge: make outline-edge[size: 0x1]
1385font: default-font-heading
1386]
1387make subface[
1388offset: as-pair t1 height
1389size: as-pair t2 - t1 y
1390text: user
1391edge: make outline-edge[size: 0x1]
1392font: make default-font-top[color: either word? user-color[get user-color][user-color]style: 'bold]
1393]
1394make subface[
1395offset: as-pair t2 height
1396size: as-pair t3 - t2 y
1397span: all[p/span find p/span #W #W]
1398text: form msg
1399color: either word? msg-color[get msg-color][msg-color]
1400edge: make outline-edge[size: 0x1]
1401font: default-font
1402para: default-para-wrap
1403]
1404make subface[
1405offset: as-pair t3 height
1406size: as-pair p/size/x - t3 - sizes/slider y
1407span: all[p/span find p/span #W #X]
1408text: form either now/date = date/date[date/time][date/date]
1409edge: make outline-edge[size: 0x1]
1410font: default-font-top
1411]
1412]
1413height: height + y - 1
1414if ((length? pane/1/pane) / 4) > limit[
1415y: pane/1/pane/1/size/y - 1
1416remove/part pane/1/pane 4
1417foreach[i u m d]pane/1/pane[
1418i/offset/y: u/offset/y: m/offset/y: d/offset/y: i/offset/y - y
1419]
1420height: height - y
1421]
1422unless no-show[
1423insert tail data reduce[user user-color msg msg-color date]
1424pane/1/size/y: height
1425pane/3/ratio: pane/3/size/y / height
1426show p
1427]
1428show pane/1
1429]
1430set-user-color: make function![id[integer!]color[tuple! word! none!]/local idx][
1431if any[zero? id id > rows][exit]
1432poke data id * 5 - 3 color
1433if limit > (rows - id)[
1434idx: either rows > limit[(id + limit - rows) * 4 - 2][id * 4 - 2]
1435pane/1/pane/:idx/font/color: either word? color[get color][color]
1436show pane/1/pane/:idx
1437]
1438]
1439set-message-text: make function![id[integer!]string[string!]/local idx][
1440if any[zero? id id > rows][exit]
1441poke data id * 5 - 2 string
1442if limit > (rows - id)[
1443idx: either rows > limit[(id + limit - rows) * 4 - 1][id * 4 - 1]
1444insert clear pane/1/pane/:idx/text string
1445redraw
1446]
1447]
1448set-message-color: make function![id[integer!]color[tuple! word! none!]/local idx][
1449if any[zero? id id > rows][exit]
1450poke data id * 5 - 1 color
1451if limit > (rows - id)[
1452idx: either rows > limit[(id + limit - rows) * 4 - 1][id * 4 - 1]
1453pane/1/pane/:idx/color: either word? color[get color][color]
1454show pane/1/pane/:idx
1455]
1456]
1457redraw: make function![/no-show /local row][
1458clear pane/1/pane
1459height: 0
1460rows: (length? data) / 5
1461row: max 0 rows - limit: any[select options 'limit 100]
1462foreach[user user-color msg msg-color date]skip data row * 5[
1463append-message/no-show user user-color msg msg-color date row: row + 1
1464]
1465pane/1/size/y: height
1466pane/3/ratio: either zero? height[1][pane/3/size/y / height]