;; =============================================
;; UTF-8 characters have been identified in this
;; script.
;; It may display badly in some text editors.
;; If so check if your text editor has any way
;; of setting the the charset to UTF-8
;; =============================================
;; ==============================================
;; Script: supercalculator.r
;; downloaded from: www.REBOL.org
;; on: 7-Jul-2010
;; at: 22:20:31 UTC
;; owner: crazyaxe [script library member who can
;; update this script]
;; ==============================================
Rebol [
    title: "Supercalculator"
    author: "Massimiliano Vessi"
    date:  17/02/2010
    email: %maxint--tiscali--it
    file: %supercalculator.r
    Purpose: {"Scientific calculator in Rebol!"}
    ;following data are for www.rebol.org library
    ;you can find a lot of rebol script there
    library: [ 
        level: 'beginner 
        platform: 'all 
        type: [tutorial  tool] 
        domain: [vid gui  text-processing ui user-interface scientific] 
        tested-under: [windows linux] 
        support: none 
        license: [gpl] 
        see-also: none 
        ] 
    version: 2.4.11
    ]

    
;*******REBGUI SCRIPT for beautifull BUTTON**********
;**************START*********************************
Rebol[version: 117]
if system/version < 1.3.2[make error! "RebGUI requires View 1.3.2 or greater"]
unless value? 'viewed?[
find-window: make function![
"Find a face's window face." 
face[object!]
][
while[face/parent-face][face: face/parent-face]
face
]
viewed?: make function![
"Returns TRUE if face is displayed." 
face[object!]
][
found? find system/view/screen-face/pane find-window face
]
]
system/locale: make system/locale[
colors:[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]
words:[]
language: "English" 
dictionary: none 
dict: none
]
ctx-rebgui: make object![
build: 117 
view*: system/view 
locale*: system/locale 
find-face: make function![pnt[pair!]f[object! block!]/local p result][
all[
object? :f 
f/show? 
within? pnt win-offset? f f/size 
return f
]
p: either object? :f[get in f 'pane][:f]
either block? :p[
result: none 
foreach face head reverse copy p[
if all[object? :face face/show? face: find-face pnt face][
result: face 
break
]
]
result
][
all[object? :p find-face pnt :p]
]
]
subface: make system/standard/face[
color: edge: font: para: feel: none
]
all-chars: make string! 256 
repeat i 256[insert tail all-chars to char! i - 1]
font?: make function![
font-name[string!]
][
all[font-name = font-sans-serif return true]
(size-text make subface[text: all-chars font: make view*/screen-face/font[name: font-sans-serif]]) <> 
(size-text make subface[text: all-chars font: make view*/screen-face/font[name: font-name]])
]
gui-error: make function![
error[string!]
/continue
][
write/append/lines %rebgui.log reform[now/date now/time error]
unless continue[make error! error]
]
span-resize: make function![face[object!]delta[pair!]][
if face/span[
face/old-size: face/size 
all[find face/span #X face/offset/x: face/offset/x + delta/x]
all[find face/span #Y face/offset/y: face/offset/y + delta/y]
all[find face/span #W face/size/x: face/size/x + delta/x]
all[find face/span #H face/size/y: face/size/y + delta/y]
all[face/old-size <> face/size object? get in face 'action face/action/on-resize face]
]
any[
if block? get in face 'pane[foreach f face/pane[span-resize f delta]]
if object? get in face 'pane[span-resize face/pane delta]
]
]
span-size: make function![face[object!]size[pair!]margin[pair!]][
if face/span[
all[
find face/span #L 
face/size/x: size/x - face/offset/x - margin/x 
all[find[drop-list edit-list]face/type face/pane/offset/x: face/size/x - sizes/line + 1]
]
all[find face/span #V face/size/y: size/y - face/offset/y - margin/y]
all[face/old-size <> face/size object? get in face 'action face/action/on-resize face]
if find face/span #O[
face/offset/x: either any[zero? face/offset/y size/y = (face/offset/y + face/size/y)][
size/x - face/size/x
][
size/x - face/size/x - margin/x
]
]
]
if block? get in face 'pane[
either face/type = 'tab-panel[
foreach f face/pane[span-size f face/size 0x0]
][
foreach f face/pane[span-size f face/size face/pane/1/offset]
]
]
if object? get in face 'pane[span-size face/pane face/size face/pane/offset]
]
unview-keep: make function![num[integer!]/local pane][
pane: head view*/screen-face/pane 
while[(length? pane) > num][remove back tail pane]
show view*/screen-face
]
words:[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]
select-face: make function![face][
face/color: colors/state-light 
face/font/color: colors/page 
show face
]
deselect-face: make function![face /fill][
face/color: either fill[colors/page][none]
face/font/color: colors/text 
show face
]
colors: construct/with either exists? %ui.dat[pick load %ui.dat 3][[]]make object![
page: ivory 
text: coal 
theme-light: 195.221.127 
theme-dark: 136.187.0 
state-light: 255.204.127 
state-dark: 255.153.0 
outline-light: 204.204.204 
outline-dark: 136.136.136
]
sizes: construct/with either exists? %ui.dat[pick load %ui.dat 6][[]]make object![
cell: 4 
edge: 1 
font: 12 
font-height: none 
gap: 2 
line: cell * 5 
margin: 4 
slider: cell * 4
]
behaviors: construct/with either exists? %ui.dat[pick load %ui.dat 9][[]]make object![
action-on-enter:[drop-list edit-list field password spinner]
action-on-tab:[field]
caret-on-focus:[area]
cyclic:[group-box panel sheet tab-panel]
hilight-on-focus:[edit-list field password spinner]
tabbed:[area button drop-list drop-tree edit-list field grid password spinner]
]
effects: construct/with either exists? %ui.dat[pick load %ui.dat 12][[]]make object![
arrows-together: false 
radius: 5 
font: either font? "arial"["verdana"][font-sans-serif]
fonts: sort reduce[font-sans-serif font-fixed font-serif "verdana"]
splash-delay: 1 
tooltip-delay: 0:00:01 
webdings: font? "webdings" 
window: none
]
on-fkey: make object![
f1: f2: f3: f4: f5: f6: f7: f8: f9: f10: f11: f12: none
]
edit: make object![
siblings: none 
caret: none 
letter: make bitset![#"A" - #"Z" #"a" - #"z" #"'"]
capital: make bitset![#"A" - #"Z"]
other: negate letter 
edits: make function![
words[block!]
/local result ln w
][
result: copy[]
foreach word words[
repeat n ln: length? word[
insert tail result head remove at copy word n
]
repeat n ln - 1[
insert tail result head change change at copy word n pick word n + 1 pick word n
]
foreach ch "abcdefghijklmnopqrstuvwxyz"[
repeat n ln[
poke w: copy word n ch 
insert tail result w
]
repeat n ln + 1[
insert tail result head insert at copy word n ch
]
]
]
result
]
lookup-word: make function![
word[string!]
/local result
][
any[
not empty? result: intersect locale*/dict make hash! word: reduce[word]
not empty? result: intersect locale*/dict make hash! edits word 
result: word
]
sort result
]
insert?: true 
keymap:[
#"^H" back-char 
#"^~" del-char 
#"^M" enter 
#"^A" all-text 
#"^C" copy-text 
#"^X" cut-text 
#"^V" paste-text 
#"^T" clear-tail 
#"^Z" undo 
#"^Y" redo 
#"^[" undo-all 
#"^S" spellcheck 
#"^/" ctrl-enter
]
hilight-text: make function![start end][
view*/highlight-start: start 
view*/highlight-end: end
]
hilight-all: make function![face][
either empty? face/text[unlight-text][
view*/highlight-start: head face/text 
view*/highlight-end: tail face/text
]
]
unlight-text: make function![][
view*/highlight-start: view*/highlight-end: none
]
hilight?: make function![][
all[
object? view*/focal-face 
string? view*/highlight-start 
string? view*/highlight-end 
not zero? offset? view*/highlight-end view*/highlight-start
]
]
hilight-range?: make function![/local start end][
start: view*/highlight-start 
end: view*/highlight-end 
if negative? offset? start end[start: end end: view*/highlight-start]
reduce[start end]
]
tabbed?: make function![
face[object!]
][
all[
face/show? 
find behaviors/tabbed face/type 
not find face/options 'info 
face
]
]
cyclic?: make function![
face[object!]
][
all[find behaviors/cyclic face/type face]
]
unfocus: make function![/local face][
if face: view*/focal-face[
if all[face/type <> 'face get in face/action 'on-unfocus][
unless face/action/on-unfocus face[return false]
]
all[
view*/caret 
in face 'caret 
face/caret: index? view*/caret
]
all[
face/type = 'button 
face/feel/over face false none
]
]
view*/focal-face: view*/caret: none 
unlight-text 
all[face show face]
true
]
copy-selected-text: make function![/local start end][
if hilight?[
set[start end]hilight-range? 
write clipboard:// copy/part start end 
true
]
]
delete-selected-text: make function![/local start end][
if hilight?[
set[start end]hilight-range? 
remove/part start end 
view*/caret: start 
view*/focal-face/line-list: none 
unlight-text 
true
]
]
cut-text: make function![][
undo-add face 
copy-selected-text face 
delete-selected-text
]
paste-text: make function![][
undo-add face 
delete-selected-text 
face/line-list: none 
view*/caret: insert view*/caret read clipboard://
]
undo-max: 20 
undo-add: make function![face][
if in face 'undo[
insert clear face/undo at copy face/text index? view*/caret 
if all[undo-max undo-max < length? head face/undo][remove head face/undo]
face/undo: tail face/undo
]
]
undo-get: make function![face][
face/text: head view*/caret: first face/undo 
face/line-list: none 
remove face/undo
]
word-limits: make bitset! { 
^-^M/[](){}"} 
word-limits: reduce[word-limits complement word-limits]
current-word: make function![str /local s ns][
unless string? str[gui-error/continue reform["Current word trap" type? str str]exit]
set[s]word-limits 
s: any[all[s: find/reverse str s next s]head str]
set[ns]word-limits 
ns: any[find str ns tail str]
hilight-text s ns 
show view*/focal-face
]
next-word: make function![str /local s ns][
set[s ns]word-limits 
any[all[s: find str s find s ns]tail str]
]
back-word: make function![str /local s ns][
set[s ns]word-limits 
any[all[ns: find/reverse str ns ns: find/reverse ns s next ns]head str]
]
end-of-line: make function![str][
any[find str "^/" tail str]
]
beg-of-line: make function![str /local nstr][
either nstr: find/reverse str "^/"[next nstr][head str]
]
next-field: make function![face /wrap][
unless face/parent-face[return none]
unless find[object! block!]type?/word get in face/parent-face 'pane[
return none
]
siblings: compose[(face/parent-face/pane)]
unless wrap[siblings: find/tail siblings face]
foreach sibling siblings[
if target: any[
tabbed? sibling 
into-widget/forwards sibling
][
return target
]
]
all[
not cyclic? face/parent-face 
target: next-field face/parent-face 
return target
]
all[
target: next-field/wrap face 
return target
]
]
back-field: make function![face /wrap][
unless face/parent-face[return none]
unless find[object! block!]type?/word get in face/parent-face 'pane[
return none
]
siblings: reverse compose[(face/parent-face/pane)]
unless wrap[siblings: find/tail siblings face]
foreach sibling siblings[
if target: any[
tabbed? sibling 
into-widget/backwards sibling
][
return target
]
]
all[
not cyclic? face/parent-face 
target: back-field face/parent-face 
return target
]
all[
target: back-field/wrap face 
return target
]
]
into-widget: make function![
{Recursivly returns the first tabbable face in parent's face pane tree.} 
face[object!]
/forwards 
/backwards 
/local 
target children
][
unless find[object! block!]type?/word get in face 'pane[
return none
]
unless face/show?[
return none
]
children: compose[(face/pane)]
catch[
foreach child either backwards[reverse children][children][
if target: any[
tabbed? child 
either backwards[
into-widget/backwards child
][
into-widget child
]
][
throw target
]
]
]
]
keys-to-insert: make bitset! #{
01000000FFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
} 
insert-char: make function![face char][
delete-selected-text 
unless any[insert? tail? view*/caret "^/" = first view*/caret][remove view*/caret]
insert view*/caret char 
view*/caret: next view*/caret
]
move: make function![event ctrl plain][
either event/shift[
any[view*/highlight-start view*/highlight-start: view*/caret]
][unlight-text]
view*/caret: either event/control ctrl plain 
if event/shift[
either view*/caret = view*/highlight-start[unlight-text][view*/highlight-end: view*/caret]
]
]
move-y: make function![face delta /local pos tmp tmp2][
tmp: offset-to-caret face 0x2 + delta + pos: caret-to-offset face view*/caret 
tmp2: caret-to-offset face tmp 
either tmp2/y <> pos/y[tmp][view*/caret]
]
edit-text: make function![
face event 
/local key edge para caret scroll page-up page-down face-size
][
face-size: face/size - either face/edge[2 * face/edge/size][0]
key: event/key 
if char? key[
either find keys-to-insert key[
undo-add face 
insert-char face key
][key: select keymap key]
]
if word? key[
page-up:[move-y face face-size - sizes/font-height - sizes/font-height * 0x-1]
page-down:[move-y face face-size - sizes/font-height * 0x1]
do select[
left[move event[back-word view*/caret][back view*/caret]]
right[move event[next-word view*/caret][next view*/caret]]
up[move event page-up[move-y face sizes/font-height * 0x-1]]
down[move event page-down[move-y face sizes/font-height * 0x1]]
page-up[move event[head view*/caret]page-up]
page-down[move event[tail view*/caret]page-down]
home[move event[head view*/caret][beg-of-line view*/caret]]
end[move event[tail view*/caret][end-of-line view*/caret]]
insert[either event/shift[paste-text][insert?: complement insert?]]
back-char[
undo-add face 
any[
delete-selected-text 
head? view*/caret 
either event/control[
tmp: view*/caret 
remove/part view*/caret: back-word tmp tmp
][remove view*/caret: back view*/caret]
]
]
del-char[
undo-add face 
either event/shift[unless face/type = 'password[cut-text]][
any[
delete-selected-text 
tail? view*/caret 
either event/control[
remove/part view*/caret back next-word view*/caret 
if tail? next view*/caret[remove back tail view*/caret]
][remove view*/caret]
]
]
]
enter[
either find behaviors/action-on-enter face/type[
all[face/type = 'spinner face/action/on-unfocus face]
set-focus face 
face/action/on-click face
][
undo-add face 
insert-char face "^/"
]
]
ctrl-enter[undo-add face insert-char face tab]
all-text[hilight-all face]
copy-text[unless face/type = 'password[copy-selected-text face unlight-text]]
cut-text[unless face/type = 'password[cut-text]]
paste-text[paste-text]
clear-tail[
undo-add face 
remove/part view*/caret end-of-line view*/caret
]
undo[
if all[in face 'undo not head? face/undo][
insert face/undo at copy face/text index? view*/caret 
face/undo: back face/undo 
undo-get face
]
]
redo[
if all[in face 'undo not tail? face/undo][
face/undo: insert face/undo at copy face/text index? view*/caret 
undo-get face
]
]
undo-all[
if in face 'esc[
clear face/text 
all[in face 'undo clear face/undo]
all[string? face/esc insert face/text face/esc]
view*/caret: tail face/text
]
]
spellcheck[
request-spellcheck face
]
]key
]
edge: face/edge 
para: face/para 
scroll: face/para/scroll 
if error? try[
caret: caret-to-offset face view*/caret 
if caret/y < (edge/size/y + para/origin/y + para/indent/y)[
scroll/y: round/to scroll/y - caret/y sizes/font-height
]
if caret/y > (face-size/y - sizes/font-height)[
scroll/y: round/to (scroll/y + ((face-size/y - sizes/font-height) - caret/y)) sizes/font-height
]
unless para/wrap?[
if caret/x < (edge/size/x + para/origin/x + para/indent/x)[
scroll/x: scroll/x - caret/x + (edge/size/x + para/origin/x + para/indent/x)
]
if caret/x > (face-size/x - para/margin/x)[
scroll/x: scroll/x + (face-size/x - para/margin/x - caret/x)
]
]
if scroll <> face/para/scroll[
face/para/scroll: scroll 
if face/type = 'area[face/key-scroll?: true]
]
][gui-error/continue reform["Caret trap" face/type face/para]]
show face
]
feel: make object![
redraw: detect: over: none 
engage: func[face act event /local txt][
do select[
key[
unless all[get in face/action 'on-key not face/action/on-key face event][
txt: copy face/text 
edit-text face event 
all[
get in face/action 'on-edit 
strict-not-equal? txt face/text 
face/action/on-edit face
]
]
]
down[
either event/double-click[
all[view*/caret not empty? view*/caret current-word view*/caret]
][
either face = view*/focal-face[
unlight-text 
view*/caret: offset-to-caret face event/offset 
show face
][
caret: offset-to-caret face event/offset 
set-focus face
]
]
]
over[
unless view*/caret = offset-to-caret face event/offset[
unless view*/highlight-start[view*/highlight-start: view*/caret]
view*/highlight-end: view*/caret: offset-to-caret face event/offset 
show face
]
]
alt-up[face/action/on-alt-click face]
scroll-line[face/action/on-scroll face event/offset]
scroll-page[face/action/on-scroll/page face event/offset]
]act
]
]
]
widgets: make object![
rebind: make function![][
default-edge/color: colors/text 
default-edge/size: as-pair sizes/edge sizes/edge 
theme-edge/color: colors/theme-dark 
theme-edge/size: default-edge/size 
outline-edge/color: colors/outline-light 
outline-edge/size: default-edge/size 
default-font/size: sizes/font 
default-font/name: effects/font 
default-font-bold: make default-font[style: 'bold]
default-font-heading: make default-font[style: 'bold color: colors/page align: 'center shadow: 1x1]
default-font-large: make default-font[size: sizes/font * 2]
default-font-right: make default-font[align: 'right]
default-font-top: make default-font[valign: 'top]
default-para-indented/origin/x: sizes/line 
default-text/text: copy "" 
sizes/font-height: second size-text default-text 
foreach w next find first self 'choose[
widgets/:w/rebind
]
]
default-edge: make object![
color: colors/text 
image: none 
effect: none 
size: as-pair sizes/edge sizes/edge
]
theme-edge: make default-edge[
color: colors/theme-dark
]
outline-edge: make default-edge[
color: colors/outline-light
]
default-font: make object![
name: effects/font 
style: none 
size: sizes/font 
color: colors/text 
offset: 0x0 
space: 0x0 
align: 'left 
valign: 'middle 
shadow: none
]
default-font-bold: make default-font[
style: 'bold
]
default-font-heading: make default-font[
style: 'bold 
color: colors/page 
align: 'center 
shadow: 1x1
]
default-font-large: make default-font[
size: sizes/font * 2
]
default-font-right: make default-font[
align: 'right
]
default-font-top: make default-font[
valign: 'top
]
default-para: make object![
origin: 2x2 
margin: 2x2 
indent: 0x0 
tabs: 0 
wrap?: false 
scroll: 0x0
]
default-para-wrap: make default-para[
origin: 2x0 
indent: 0x0 
wrap?: true
]
default-para-indented: make default-para[
origin: as-pair sizes/line 2
]
default-feel: make object![
redraw: 
detect: 
over: 
engage: none
]
default-action: make object![
on-alt-click: 
on-away: 
on-click: 
on-dbl-click: 
on-edit: 
on-focus: 
on-key: 
on-over: 
on-resize: 
on-scroll: 
on-unfocus: none
]
set 'rebface make subface[
feel: default-feel 
action: default-action 
options:[]
rebind: init: tip: none
]
default-text: make rebface[
size: 10000x10000 
text: "" 
font: default-font 
para: default-para
]
sizes/font-height: second size-text default-text 
date-spec:[
tight 
symbol 9x6 data 'rewind[face/parent-face/data/year: face/parent-face/data/year - 1 show face/parent-face]
symbol 9x6 data 'left[face/parent-face/data/month: face/parent-face/data/month - 1 show face/parent-face]
symbol 34x6[set-data face/parent-face first face/parent-face/options]
symbol 9x6 data 'right[face/parent-face/data/month: face/parent-face/data/month + 1 show face/parent-face]
symbol 9x6 data 'forward[face/parent-face/data/year: face/parent-face/data/year + 1 show face/parent-face]
return
]
foreach day locale*/days[
insert tail date-spec compose[label 10 (copy/part day 3) font[align: 'center]]
]
insert tail date-spec[return bar]
loop 6[
insert tail date-spec 'return 
loop 7[
insert tail date-spec[
box 10x6 font[align: 'center valign: 'middle]edge[size: 0x0 color: colors/state-dark]feel[
over: make function![face act pos][
either all[act face/text][
face/parent-face/data/day: to integer! face/text 
set-title face/parent-face form face/parent-face/data 
select-face face
][deselect-face face]
]
engage: make function![face act event][
all[
act = 'down 
face/text 
face/parent-face/data/day: to integer! face/text 
poke face/parent-face/options 1 face/parent-face/data 
face/parent-face/action/on-click face/parent-face
]
all[
find[up alt-up]act 
face/feel/over face false none
]
]
]
]
]
]
face-iterator: make rebface[
type: 'face-iterator 
pane:[]
data:[]
timeout: now/time/precise 
feel: make default-feel[
redraw: make function![face act pos][
if all[act = 'show face/size <> face/old-size][face/resize]
]
engage: make function![face act event /local i][
if act = 'time[
if (now/time/precise - face/timeout) > 0:00:00.2[
face/action face 
face/rate: none 
show face
]
]
if act = 'key[
do select[
#"^A"[
if find face/options 'multi[
clear face/picked 
repeat i face/rows[insert tail face/picked i]
face/action face
]
]
down[
i: 1 + last face/picked 
if i <= face/rows[
i: min face/rows i 
insert clear face/picked i 
if find[table text-list]face/parent-face/type[
face/timeout: now/time/precise 
face/rate: 60 
if i > (face/scroll + face/lines)[
face/pane/2/data: 1 / (face/rows - face/lines) * ((min (face/rows - face/lines + 1) (i - face/lines + 1)) - 1) 
face/scroll: face/scroll + 1
]
]
]
]
up[
i: -1 + last face/picked 
if i > 0[
i: max 1 i 
insert clear face/picked i 
if find[table text-list]face/parent-face/type[
face/timeout: now/time/precise 
face/rate: 60 
if i = face/scroll[
face/pane/2/data: 1 / (face/rows - face/lines) * ((min (face/rows - face/lines + 1) i) - 1) 
face/scroll: face/scroll - 1
]
]
]
]
#"^M"[
all[find[table text-list]face/parent-face/type face/action face]
]
]event/key 
show face
]
]
]
lines: none 
rows: none 
cols: 1 
widths: none 
aligns: none 
picked:[]
scroll: 0 
resize: make function![][
lines: to integer! size/y / sizes/line 
pane/2/show?: either rows > lines[
scroll: max 0 min scroll rows - lines 
true
][
scroll: 0 
false
]
]
redraw: make function![][
clear picked 
rows: either empty? data[0][(length? data) / cols]
resize 
pane/2/ratio: either zero? rows[1][lines / rows]
show self
]
selected: make function![/local blk][
if empty? picked[return none]
either any[find options 'multi parent-face/type = 'table][
all[rows = length? picked return data]
blk: copy[]
either cols = 1[
foreach row picked[insert tail blk pick data row]
][
foreach row picked[
repeat col cols[
insert tail blk pick data -1 + row * cols + col
]
]
]
blk
][
blk: pick data first picked
]
]
init: make function![/local p][
attempt[remove find span #X]
attempt[remove find span #Y]
lines: to integer! size/y / sizes/line 
rows: (length? data) / cols 
clear pane 
p: self 
insert pane make subface[
size: p/size 
span: p/span 
pane: make function![face index /local col-offset clr][
either integer? index[
if index <= min lines rows[
line/offset/y: index - 1 * sizes/line 
line/size/x: size/x 
index: index + scroll 
either p/parent-face/type = 'table[
col-offset: 0 
repeat i p/cols[
line/pane/:i/offset/x: col-offset 
line/pane/:i/size/x: p/widths/:i - sizes/cell 
all[
p/pane/2/show? 
i = p/cols 
line/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))
]
line/pane/:i/text: replace/all form pick p/data index - 1 * cols + i "^/" "¶" 
line/pane/:i/font/color: either find p/options 'no-action[
colors/text
][
either find picked index[colors/page][colors/text]
]
col-offset: col-offset + pick widths i
]
][
line/text: replace/all form pick face/parent-face/data index "^/" "¶" 
line/font/color: either find p/options 'no-action[
colors/text
][
either find picked index[colors/page][colors/text]
]
]
line/color: either find p/options 'no-action[none][if find picked index[colors/theme-light]]
if all[
line/color = colors/theme-light 
face/parent-face/type = 'choose
][face/parent-face/auto: pick face/parent-face/data index]
line/data: index 
line
]
][to integer! index/y / sizes/line + 1]
]
text: "" 
line: make rebface[
size: as-pair 0 sizes/line 
font: make default-font[]
feel: make default-feel[
over: make function![face into pos][
if find face/parent-face/parent-face/options 'over[
either into[insert clear picked data][clear picked]
show face
]
]
engage: make function![face act event /local p a b][
p: face/parent-face 
either event/double-click[
all[act = 'down p/parent-face/dbl-action p/parent-face]
][
if find[up alt-up]act[
view*/focal-face: p 
view*/caret: tail p/text 
either find p/parent-face/options 'multi[
unless any[event/control event/shift][clear picked]
either all[event/control find picked data][
remove find picked data
][
unless find picked data[insert tail picked data]
]
if all[event/shift 1 < length? picked][
clear next picked 
repeat i (max data first picked) - (a: min data first picked) + 1[
b: i + a - 1 
all[b <> first picked insert tail picked b]
]
]
][insert clear picked data]
show p 
unless find p/parent-face/options 'no-action[
either act = 'up[
p/parent-face/action p/parent-face
][
p/parent-face/alt-action p/parent-face
]
]
]
]
]
]
]
]
if find options 'table[
pane/1/line/pane: copy[]
repeat i cols[
insert tail pane/1/line/pane make subface[
size: as-pair 0 sizes/line 
font: make default-font[align: aligns/:i]
]
]
]
insert tail pane make slider[
tip: none 
offset: as-pair p/size/x - sizes/slider 0 
size: as-pair sizes/slider p/size/y 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#XH]
find p/span #H[#H]
find p/span #W[#X]
]
options:[arrows]
show?: either rows > lines[true][false]
action: make default-action[
on-click: make function![face][
scroll: to integer! rows - lines * data 
show face/parent-face
]
]
ratio: either rows > 0[lines / rows][1]
]
pane/2/init
]
]
choose: make function![
parent[object!]"Widget to appear in relation to" 
width[integer!]"Width in pixels" 
xy[pair!]"Offset of choice box" 
items[block!]"Block of items to display" 
/local popup result
][
result: none 
popup: make face-iterator[
type: 'choose 
offset: xy 
size: as-pair width sizes/line * min length? items to-integer parent/parent-face/size/y - xy/y / sizes/line 
color: colors/page 
data: items 
edge: outline-edge 
feel: system/words/face/feel 
options:[over]
action: make function![face][result: pick data first picked hide-popup]
alt-action: none 
dbl-action: none 
auto: none
]
popup/init 
show-popup/window/away popup parent/parent-face 
do-events 
either parent/type = 'edit-list[popup/auto][result]
]
anim: make rebface[
tip:{USAGE:
anim data[%images/go-previous.png %images/go-next.png]
anim data[img1 img2 img3]rate 2
DESCRIPTION:
Cycles a set of images at a specified rate.}
size: -1x-1 
effect: 'fit 
feel: make default-feel[
engage: make function![face act event][
all[
act = 'time 
face/image: first face/data 
face/data: either tail? next face/data[head face/data][next face/data]
show face
]
]
]
rate: 1 
init: make function![][
repeat i length? data: reduce data[
all[file? pick data i poke data i load pick data i]
]
image: first data 
data: next data 
all[negative? size/x size/x: image/size/x]
all[negative? size/y size/y: image/size/y]
]
]
pill: make rebface[
tip:{USAGE:
pill red
DESCRIPTION:
A rectangular area with rounded corners.}
size: 10x10 
effect:[draw[pen none line-width sizes/edge fill-pen linear 0x0 0 0 90 1 1 none none none box 0x0 0x0 effects/radius]]
pen: none 
fill: make function![][effect/draw/fill-pen]
feel: make default-feel[
redraw: make function![face act pos][
if act = 'show[
all[
face/color 
poke face/effect/draw 13 face/color + 0.0.0.64 
poke face/effect/draw 14 face/color + 0.0.0.32 
poke face/effect/draw 15 face/color 
face/color: none
]
]
]
]
action: make default-action[
on-resize: make function![face][
poke face/effect/draw 8 to integer! face/size/y * 0.25 
poke face/effect/draw 9 to integer! face/size/y * 0.75 
poke face/effect/draw 18 face/size - 1x1 
poke face/effect/draw 19 either all[face/size/x > sizes/line face/size/y > sizes/line][effects/radius * 2][effects/radius]
]
]
init: make function![][
action/on-resize self
]
]
area: make rebface[
tip:{USAGE:
area
area "Text" -1
area "Text" 50x-1
DESCRIPTION:
Editable text area with wrapping and scroller.
OPTIONS:
'info specifies read-only}
size: 50x25 
text: "" 
color: colors/page 
edge: theme-edge 
font: default-font-top 
para: make default-para-wrap[margin: as-pair sizes/slider + 2 2]
feel: make edit/feel[
redraw: func[face act pos /local height total visible][
if act = 'show[
if face/size <> face/old-size[
face/pane/offset/x: max 0 face/size/x - face/pane/size/x 
face/pane/size/y: face/size/y
]
if any[
face/text-y <> height: second size-text face 
face/size <> face/old-size
][
face/text-y: height 
total: face/text-y 
visible: face/size/y - (edge/size/y * 2) - para/origin/y - para/indent/y 
face/pane/ratio: either total > 0[min 1 (visible / total)][1]
face/pane/step: either visible < total[min 1 (sizes/font-height / (total - visible))][0]
]
if all[face/pane/ratio < 1 face/key-scroll?][
do bind[
total: text-y 
visible: size/y - (edge/size/y * 2) - para/origin/y - para/indent/y 
pane/data: - para/scroll/y / (total - visible)
]face 
face/key-scroll?: false
]
]
]
]
esc: none 
caret: none 
undo: copy[]
text-y: none 
key-scroll?: false 
action: make default-action[
on-scroll: make function![face scroll /page /local total visible][
total: second size-text face 
visible: face/size/y - (face/edge/size/y * 2) - face/para/origin/y - face/para/indent/y 
face/para/scroll/y: either page[
min max face/para/scroll/y - (visible * sign? scroll/y) (visible - total) 0
][
min max face/para/scroll/y - (scroll/y * sizes/font-height) (visible - total) 0
]
all[face/pane/data: - face/para/scroll/y / (total - visible)]
show face
]
]
rebind: make function![][
color: colors/page 
para/margin/x: sizes/slider + 2
]
init: make function![/local p][
if find options 'info[
feel: make feel[engage: none]
all[color = colors/page color: colors/outline-light]
]
para: make para[]
p: self 
text-y: second size-text self 
all[negative? size/x size/x: 10000 size/x: 4 + first size-text self]
all[negative? size/y size/y: 10000 size/y: 8 + text-y]
pane: make slider[
tip: none 
offset: as-pair p/size/x - sizes/slider 0 
size: as-pair sizes/slider p/size/y 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#XH]
find p/span #W[#X]
find p/span #H[#H]
true[none]
]
options:[arrows]
action: make default-action[
on-click: make function![face /local visible][
unless parent-face/key-scroll?[
visible: (parent-face/size/y - (parent-face/edge/size/y * 2) - parent-face/para/origin/y - parent-face/para/indent/y) 
parent-face/para/scroll/y: negate parent-face/text-y - visible * data 
if all[
view*/caret 
parent-face = view*/focal-face
][
]
show parent-face
]
parent-face/key-scroll?: false
]
]
ratio: p/size/y - 4 / text-y
]
pane/init
]
]
arrow: make rebface[
tip:{USAGE:
arrow
arrow 10
arrow data 'up
arrow data 'down
arrow data 'left
arrow data 'right
DESCRIPTION:
An arrow (default down) on a square button face with height set to width.}
size: 5x-1 
data: 'down 
feel: make default-feel[
redraw: make function![face act pos][
all[act = 'show face/color: either face/data[colors/state-light][colors/theme-light]]
]
engage: make function![face act event][
do select[
time[all[face/data face/action/on-click face]]
down[face/data: on]
up[face/data: off face/action/on-click face]
over[face/data: on]
away[face/data: off]
]act 
show face
]
]
effect: reduce['arrow colors/page 'rotate 0]
rebind: make function![][effect/arrow: colors/page]
init: make function![][
all[negative? size/y size/y: size/x]
effect/rotate: select[up 0 right 90 down 180 left 270]data 
data: off
]
]
bar: make rebface[
tip:{USAGE:
bar 100
DESCRIPTION:
A thin 3D bar used to separate widgets.
Defaults to maximum display width.}
size: -1x1 
color: colors/outline-light 
edge: make outline-edge[effect: 'bevel]
rebind: make function![][color: edge/color: colors/outline-light]
]
box: make rebface[
tip:{USAGE:
box red
DESCRIPTION:
The most basic of widgets, a rectangular area.}
size: 25x25
]
button: make pill[
tip:{USAGE:
button "Hello"
button -1 "Go!"
button "Click me!"[print "click"]
DESCRIPTION:
Performs action when clicked.
OPTIONS:
'info specifies read-only}
size: 15x5 
text: "" 
color: colors/theme-dark 
font: default-font-heading 
feel: make feel[
over: make function![face act pos][
set-color face either all[act not find face/options 'info][colors/theme-light][colors/theme-dark]
]
engage: make function![face act event /local f][
unless find face/options 'info[
do select[
down[set-color face colors/state-light]
alt-down[set-color face colors/state-light]
up[set-color face colors/theme-dark face/action/on-click face]
alt-up[set-color face colors/theme-dark face/action/on-alt-click face]
away[set-color face colors/theme-dark]
]act
]
]
]
rebind: make function![][
color: colors/theme-dark
]
init: make function![][
all[negative? size/x size/x: 10000 size/x: 8 + first size-text self]
all[find options 'info color = colors/theme-dark color: colors/outline-light]
action/on-resize self
]
]
calendar: make rebface[
tip:{USAGE:
calendar
calendar data 1-Jan-2000
DESCRIPTION:
Used to select a date, with face/data set to current selection.
Default selection is now/date.}
size: 70x48 
feel: make default-feel[
redraw: make function![face act pos /local date month][
if act = 'show[
date: face/data 
month: date/month 
date/day: 1 
date: date - date/weekday + 1 
foreach sub-face skip face/pane 13[
sub-face/edge/size: 0x0 
sub-face/text: either date/month = month[
all[date = first face/options sub-face/edge/size: 2x2]
form date/day
][none]
date: date + 1
]
face/pane/3/text: reform[pick locale*/months face/data/month face/data/year]
]
]
]
init: make function![][
insert options any[data now/date]
data: layout/only date-spec 
pane: data/pane 
size: data/size 
data: first options
]
]
chat: make rebface[
tip:{USAGE:
chat 120 data["Bob" blue "My comment." yello 14-Apr-2007/10:58]
DESCRIPTION:
Three column chat display as found in IM apps such as AltME.
Messages are appended, with those exceeding 'limit not shown.
OPTIONS:
[limit n]where n specifies number of messages to show (default 100)
[id n]where n specifies id column width (default 10)
[user n]where n specifies user column width (default 15)
[date n]where n specifies date column width (default 25)}
size: 200x100 
pane:[]
data:[]
edge: outline-edge 
action: make default-action[
on-resize: make function![face][
poke face/pane/2/para/tabs 3 face/pane/1/size/x - (sizes/cell * any[select face/options 'date 25]) 
face/redraw/no-show
]
]
height: 0 
rows: 0 
limit: none 
append-message: make function![
user[string!]
user-color[tuple! word! none!]
msg[string!]
msg-color[tuple! word! none!]
date[date!]
/no-show row 
/local p y t1 t2 t3
][
t1: pick pane/2/para/tabs 1 
t2: pick pane/2/para/tabs 2 
t3: pick pane/2/para/tabs 3 
y: max sizes/line 4 + second size-text make subface[
size: as-pair t3 - t2 10000 
text: msg 
font: default-font 
para: default-para-wrap
]
p: self 
insert tail pane/1/pane reduce[
make subface[
offset: as-pair 0 height 
size: as-pair t1 y 
text: form any[row rows: rows + 1]
color: colors/theme-dark 
edge: make outline-edge[size: 0x1]
font: default-font-heading
]
make subface[
offset: as-pair t1 height 
size: as-pair t2 - t1 y 
text: user 
edge: make outline-edge[size: 0x1]
font: make default-font-top[color: either word? user-color[get user-color][user-color]style: 'bold]
]
make subface[
offset: as-pair t2 height 
size: as-pair t3 - t2 y 
span: all[p/span find p/span #W #W]
text: form msg 
color: either word? msg-color[get msg-color][msg-color]
edge: make outline-edge[size: 0x1]
font: default-font 
para: default-para-wrap
]
make subface[
offset: as-pair t3 height 
size: as-pair p/size/x - t3 - sizes/slider y 
span: all[p/span find p/span #W #X]
text: form either now/date = date/date[date/time][date/date]
edge: make outline-edge[size: 0x1]
font: default-font-top
]
]
height: height + y - 1 
if ((length? pane/1/pane) / 4) > limit[
y: pane/1/pane/1/size/y - 1 
remove/part pane/1/pane 4 
foreach[i u m d]pane/1/pane[
i/offset/y: u/offset/y: m/offset/y: d/offset/y: i/offset/y - y
]
height: height - y
]
unless no-show[
insert tail data reduce[user user-color msg msg-color date]
pane/1/size/y: height 
pane/3/ratio: pane/3/size/y / height 
show p
]
show pane/1
]
set-user-color: make function![id[integer!]color[tuple! word! none!]/local idx][
if any[zero? id id > rows][exit]
poke data id * 5 - 3 color 
if limit > (rows - id)[
idx: either rows > limit[(id + limit - rows) * 4 - 2][id * 4 - 2]
pane/1/pane/:idx/font/color: either word? color[get color][color]
show pane/1/pane/:idx
]
]
set-message-text: make function![id[integer!]string[string!]/local idx][
if any[zero? id id > rows][exit]
poke data id * 5 - 2 string 
if limit > (rows - id)[
idx: either rows > limit[(id + limit - rows) * 4 - 1][id * 4 - 1]
insert clear pane/1/pane/:idx/text string 
redraw
]
]
set-message-color: make function![id[integer!]color[tuple! word! none!]/local idx][
if any[zero? id id > rows][exit]
poke data id * 5 - 1 color 
if limit > (rows - id)[
idx: either rows > limit[(id + limit - rows) * 4 - 1][id * 4 - 1]
pane/1/pane/:idx/color: either word? color[get color][color]
show pane/1/pane/:idx
]
]
redraw: make function![/no-show /local row][
clear pane/1/pane 
height: 0 
rows: (length? data) / 5 
row: max 0 rows - limit: any[select options 'limit 100]
foreach[user user-color msg msg-color date]skip data row * 5[
append-message/no-show user user-color msg msg-color date row: row + 1
]
pane/1/size/y: height 
pane/3/ratio: either zero? height[1][pane/3/size/y / height]
unless no-show[show self]
]
init: make function![/local p][
p: self 
limit: any[select options 'limit 100]
insert pane make subface[
offset: as-pair 0 sizes/line 
size: p/size - as-pair sizes/slider sizes/line 
span: all[p/span find p/span #W #W]
pane:[]
]
insert tail pane make subface[
size: as-pair p/size/x sizes/line 
text: {ID^-User^-Message^-Sent} 
span: all[p/span find p/span #W #W]
color: colors/theme-dark 
font: make default-font-heading[align: 'left]
para: make default-para[tabs:[0 0 0]]
]
poke pane/2/para/tabs 1 sizes/cell * any[select options 'id 10]
poke pane/2/para/tabs 2 sizes/cell * (any[select options 'user 15]) + pick pane/2/para/tabs 1 
poke pane/2/para/tabs 3 size/x - sizes/slider - (sizes/cell * any[select options 'date 25]) 
insert tail pane make slider[
tip: none 
offset: as-pair p/size/x - sizes/slider sizes/line 
size: as-pair sizes/slider p/size/y - sizes/line 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#XH]
find p/span #H[#H]
find p/span #W[#X]
]
options:[arrows]
action: make default-action[
on-click: make function![face /local p][
p: face/parent-face 
p/pane/1/offset/y: sizes/line + negate (height - face/size/y) * face/data 
show p
]
]
]
pane/3/init 
action/on-resize self
]
]
check: make rebface[
tip:{USAGE:
check "Option"
check "Option" data true
check "Option" data false
DESCRIPTION:
Tristate check-box with a green tick for Yes, a red cross for No, and empty being Unknown.
Left and right mouse clicks alternate between Yes/No and Unknown respectively.
OPTIONS:
'info specifies read-only
'bistate disables right-click state}
size: -1x5 
text: "" 
effect:[draw[pen colors/outline-light fill-pen colors/page box 0x0 0x0]]
font: default-font 
para: default-para-indented 
feel: make default-feel[
p1: as-pair 2 sizes/cell + 2 
p2: -4x-4 + p1 + as-pair sizes/cell * 3 sizes/cell * 3 
redraw: make function![face act pos][
all[
act = 'show 
clear skip face/effect/draw 7 
unless none? face/data[
insert tail face/effect/draw reduce either face/data[
['pen colors/state-dark 'line-width sizes/cell / 3 'line as-pair 2 sizes/cell * 3 as-pair sizes/cell * 1.5 p2/y as-pair p2/x p1/y]
][
['pen colors/state-dark 'line-width sizes/cell / 3 'line p1 p2 'line as-pair p2/x p1/y as-pair p1/x p2/y]
]
]
]
]
over: make function![face act pos][
face/effect/draw/pen: either act[colors/state-dark][colors/outline-light]
show face
]
engage: make function![face act event][
do select[
down[face/data: either none? face/data[true][none]face/action/on-click face]
alt-down[
unless find face/options 'bistate[
face/data: either none? face/data[false][none]face/action/on-click face
]
]
away[face/feel/over face false 0x0]
]act
]
]
rebind: make function![][
feel/p1: as-pair 2 sizes/cell + 2 
feel/p2: -4x-4 + feel/p1 + as-pair sizes/cell * 3 sizes/cell * 3
]
init: make function![][
all[negative? size/x size/x: 10000 size/x: 4 + para/origin/x + first size-text self]
effect/draw/6/y: sizes/cell 
effect/draw/7: as-pair sizes/cell * 3 sizes/cell * 4 
if find options 'info[
feel/redraw self 'show none 
effect/draw/4: colors/outline-light 
feel: make default-feel[]
]
]
]
check-group: make rebface[
tip:{USAGE:
check-group data["Option-1" true "Option-2" false "Option-3" none]
DESCRIPTION:
Group of check boxes.
Alignment is vertical unless height is specified as line height.
At runtime face/data is a block of logic (or none) indicating state of each check box.
OPTIONS:
'info specifies read-only
'bistate disables right-click state}
size: 50x-1 
pane:[]
init: make function![/local off siz pos last-pane][
data: reduce data 
all[negative? size/y size/y: 0.5 * sizes/line * length? data]
off: either size/y > sizes/line[
siz: as-pair size/x sizes/line 
as-pair 0 sizes/line
][
siz: as-pair 2 * size/x / length? data sizes/line 
as-pair siz/x 0
]
pos: 0x0 
foreach[label state]data[
insert tail pane make check[
tip: none 
offset: pos 
size: siz 
text: label 
data: state
]
pos: pos + off 
last-pane: last pane 
last-pane/options: options 
last-pane/init 
last-pane/init: none
]
data: make function![/local states][
states: copy[]
foreach check pane[insert tail states check/data]
states
]
]
]
drop-list: make rebface[
tip:{USAGE:
drop-list "1" data[1 2 3]
drop-list data["One" "Two" "Three"]
drop-list data ctx-rebgui/locale*/colors
DESCRIPTION:
Single column modal selection list.
At runtime face/text contains current selection.}
size: 25x5 
text: "" 
color: colors/outline-light 
data:[]
edge: outline-edge 
font: default-font 
para: make default-para[margin: as-pair sizes/slider + 2 2]
feel: make default-feel[
engage: make function![face action event][
face/pane/feel/engage face/pane action event
]
]
action: make default-action[
on-unfocus: make function![face][
hide-popup 
face/hidden-text: face/hidden-caret: none 
true
]
]
options:[info]
hidden-caret: hidden-text: none 
picked: make function![][
index? find data text
]
rebind: make function![][
color: colors/outline-light 
para/margin/x: sizes/line + 2
]
init: make function![/local p][
unless block? data[gui-error "drop-list expected data block"]
para: make para[]
p: self 
pane: make arrow[
tip: none 
offset: as-pair p/size/x - p/size/y + 1 1 
size: as-pair p/size/y - 4 p/size/y - 4 
span: if all[p/span find p/span #W][#X]
edge: none 
action: make default-action[
on-click: make function![face /filter-data fd[block!]/local data p v lines oft][
unless filter-data[edit/unfocus]
p: face/parent-face 
all[find p/options 'no-click exit]
data: either fd[fd][p/data]
unless zero? lines: length? data[
oft: either (lines * sizes/line) < (p/parent-face/size/y - p/offset/y - p/size/y)[
p/offset + as-pair 0 p/size/y - 1
][
either (lines * sizes/line) <= (p/parent-face/size/y - 4)[
as-pair p/offset/x p/parent-face/size/y - 2 - (lines * sizes/line)
][
as-pair p/offset/x p/parent-face/size/y - 2 - (sizes/line * to integer! p/parent-face/size/y / sizes/line)
]
]
if v: choose p p/size/x oft data[
p/text: form v 
p/hidden-text: p/hidden-caret: none 
p/action/on-click p 
either p/type = 'drop-list[show p edit/unfocus][set-focus p]
]
]
]
]
]
pane/init
]
]
edit-list: make drop-list[
tip:{USAGE:
edit-list "1" data[1 2 3]
edit-list data["One" "Two" "Three"]
edit-list data ctx-rebgui/locale*/colors
DESCRIPTION:
Editable single column modal selection list.
At runtime face/text contains current selection.}
color: colors/page 
edge: theme-edge 
feel: make edit/feel bind[
engage: make function![face action event /local start end total visible fd pf][
switch action[
key[
if event/key = #"^M"[
edit-text face event 
hide-popup 
edit/unfocus 
exit
]
if event/key = 'down[
either view*/pop-face[set-focus view*/pop-face][face/pane/action/on-click face/pane]
exit
]
prev-caret: index? view*/caret 
face/text: any[face/hidden-text head view*/caret]
view*/caret: any[face/hidden-caret view*/caret]
all[view*/highlight-start view*/highlight-start: at face/text index? view*/highlight-start]
all[view*/highlight-end view*/highlight-end: at face/text index? view*/highlight-end]
edit-text face event 
face/hidden-text: copy face/text 
face/hidden-caret: at face/hidden-text index? view*/caret 
fd: copy[]
if find face/text edit/letter[
foreach ln sort face/data[
if find/match ln face/text[
face/text: copy ln 
view*/caret: at face/text index? view*/caret 
unless char? event/key[
view*/caret: at face/text prev-caret 
edit-text face event 
face/hidden-text: copy face/text 
face/hidden-caret: at face/hidden-text index? view*/caret
]
]
if find/match ln face/hidden-text[
insert tail fd ln
]
]
]
either not empty? fd[
either none? view*/pop-face[
face/pane/action/on-click/filter-data face/pane fd
][
pf: view*/pop-face 
pf/data: copy fd 
pf/pane/1/size/y: pf/size/y: sizes/line * (length? fd) 
pf/lines: to integer! pf/size/y / sizes/line 
pf/rows: length? fd 
show pf
]
][
hide-popup
]
show face
]
down[
either event/double-click[
all[view*/caret not empty? view*/caret current-word view*/caret]
][
either face <> view*/focal-face[set-focus face][unlight-text]
view*/caret: offset-to-caret face event/offset 
show face
]
]
over[
unless equal? view*/caret offset-to-caret face event/offset[
unless view*/highlight-start[view*/highlight-start: view*/caret]
view*/highlight-end: view*/caret: offset-to-caret face event/offset 
show face
]
]
]
]
]in edit 'self 
options:[]
caret: none 
rebind: make function![][color: colors/page]
]
field: make rebface[
tip:{USAGE:
field
field -1 "String"
DESCRIPTION:
Editable text field with no text wrapping.
OPTIONS:
'info specifies read-only}
size: 50x5 
text: "" 
color: colors/page 
edge: theme-edge 
font: default-font 
para: default-para 
feel: edit/feel 
rebind: make function![][color: colors/page]
init: make function![][
if find options 'info[
feel: none 
all[color = colors/page color: colors/outline-light]
]
para: make para[]
all[negative? size/x size/x: 10000 size/x: 4 + first size-text self]
]
esc: none 
caret: none 
undo: copy[]
]
group-box: make rebface[
tip:{USAGE:
group-box "Title" data[field field]
DESCRIPTION:
A static widget used to group widgets within a bounded container.}
size: -1x-1 
text: "Untitled" 
effect:[draw[pen colors/outline-dark line-width sizes/edge fill-pen none box 0x0 0x0 effects/radius pen colors/page line 0x0 0x0]]
font: make default-font-top[color: colors/outline-dark]
para: make default-para[origin: as-pair sizes/cell * 4 0]
feel: make default-feel[
redraw: make function![face act pos][
if act = 'show[
all[
face/color 
face/effect/draw/fill-pen: face/color 
poke face/effect/draw 12 colors/page 
face/color: none
]
face/effect/draw/15/x: sizes/cell * 5 + first size-text face
]
]
]
action: make default-action[
on-resize: make function![face][poke face/effect/draw 9 face/size - 1x1]
]
rebind: make function![][
font/name: effects/font 
font/size: sizes/font 
font/color: colors/outline-dark 
para/origin/x: sizes/cell * 4
]
init: make function![][
data: layout/only data 
pane: data/pane 
foreach face pane[face/offset: face/offset + as-pair 0 sizes/cell * sizes/gap]
all[negative? size/x size/x: max 16 + first size-text self data/size/x]
all[negative? size/y size/y: sizes/cell * sizes/gap + data/size/y]
effect/draw/box/y: effect/draw/14/y: effect/draw/15/y: sizes/cell * 2 
effect/draw/14/x: sizes/cell * 3 
data: none 
action/on-resize self
]
]
heading: make rebface[
tip:{USAGE:
heading "A text heading."
DESCRIPTION:
Large text.}
size: -1x-1 
text: "" 
font: default-font-large 
para: default-para-wrap 
init: make function![][
all[negative? size/x negative? size/y size: 10000x10000 size: 4x4 + size-text self]
all[negative? size/x size/x: 10000 size/x: 4 + first size-text self]
all[negative? size/y size/y: 10000 size/y: 4 + second size-text self]
all[size/y > sizes/line font/align <> 'center font: make font[valign: 'top]]
size/y: max size/y sizes/line
]
]
image: make rebface[
tip:{USAGE:
image %images/logo.png
image logo
image logo effect[crop 10x10 50x50]
DESCRIPTION:
An image.}
size: -1x-1 
effect: 'fit 
init: make function![][
all[negative? size/x size/x: image/size/x]
all[negative? size/y size/y: image/size/y]
]
]
label: make heading[
tip:{USAGE:
label "A text label."
DESCRIPTION:
Bold text.}
font: default-font-bold
]
led: make rebface[
tip:{USAGE:
led "Option"
led "Option" data true
led "Option" data false
led "Option" data none
DESCRIPTION:
Tristate indicator box with colors representing Yes & No, and empty being Unknown.}
size: -1x5 
effect:[draw[pen colors/outline-light fill-pen none box 0x0 0x0]]
font: default-font 
para: default-para-indented 
feel: make default-feel[
redraw: make function![face act pos][
all[
act = 'show 
face/effect/draw/4: select reduce[true colors/state-dark false colors/state-light]face/data
]
]
]
init: make function![][
if negative? size/x[size/x: 10000 size/x: 4 + para/origin/x + first size-text self]
effect/draw/6/y: sizes/cell 
effect/draw/7: as-pair sizes/cell * 3 sizes/cell * 2.5
]
]
led-group: make rebface[
tip:{USAGE:
led-group data["Option-1" true "Option-2" false "Option-3" none]
DESCRIPTION:
Group of LED indicators.
Alignment is vertical unless height is specified as line height.
At runtime face/data is a block of logic (or none) indicating state of each LED indicator.}
size: 50x-1 
pane:[]
feel: make default-feel[
redraw: make function![face act pos][
if act = 'show[
face/data: reduce face/data 
repeat i length? face/pane[
face/pane/:i/data: pick face/data i
]
]
]
]
init: make function![/local off siz pos last-pane][
data: reduce data 
all[negative? size/y size/y: 0.5 * sizes/line * length? data]
off: either size/y > sizes/line[
siz: as-pair size/x sizes/line 
as-pair 0 sizes/line
][
siz: as-pair 2 * size/x / length? data sizes/line 
as-pair siz/x 0
]
pos: 0x0 
foreach[label state]data[
insert tail pane make led[
tip: none 
offset: pos 
size: siz 
text: label 
data: state
]
pos: pos + off 
last-pane: last pane 
last-pane/init 
last-pane/init: none
]
clear data 
foreach led pane[insert tail data led/data]
]
]
link: make rebface[
tip:{USAGE:
link
link http://www.dobeash.com
link "RebGUI" http://www.dobeash.com/rebgui
DESCRIPTION:
Hypertext link.}
size: -1x5 
font: make default-font[color: blue style: 'underline]
para: default-para 
feel: make default-feel[
over: make function![face act pos][
face/font/color: either act[colors/state-light][blue]
show face
]
engage: make function![face act event][
all[
act = 'up 
browse face/data
]
]
]
rebind: make function![][
font/name: effects/font 
font/size: sizes/font
]
init: make function![][
unless text[text: either data[form data]["http://www.rebol.com"]]
unless data[data: to url! text]
all[negative? size/x size/x: 10000 size/x: 4 + first size-text self]
]
]
menu: make rebface[
tip:{USAGE:
menu data["Item-1"["Choice 1"[alert "1"]"Choice 2"[alert "2"]]"Item-2"[]]
DESCRIPTION:
Simple one-level text-only menu system.}
size: 100x5 
pane:[]
color: colors/outline-light 
rebind: make function![][color: colors/outline-light]
init: make function![/local item item-offset][
item-offset: 2x0 
foreach[label block]data[
insert tail pane make subface[
offset: item-offset 
size: as-pair 1 sizes/line 
text: label 
data: block 
font: make default-font[align: 'center]
para: default-para 
feel: make default-feel[
over: make function![face act pos][
either act[select-face face][deselect-face face]
]
engage: make function![face act event][
if act = 'up[
do select face/data choose face/parent-face face/options face/parent-face/offset + face/offset + as-pair 0 face/size/y extract face/data 2 
deselect-face face
]
]
]
]
item: last pane 
item/options: item/size/x: sizes/line + first size-text item 
item-offset/x: item-offset/x + item/size/x 
foreach i extract item/data 2[
default-text/text: i 
item/options: max item/options sizes/cell + first size-text default-text
]
]
data: first pane
]
]
panel: make pill[
tip:{USAGE:
panel sky data[after 1 field field]
DESCRIPTION:
A static widget used to group widgets within a container.}
size: -1x-1 
color: colors/outline-light + 32.32.32 
rebind: make function![][color: colors/outline-light + 32.32.32]
init: make function![][
data: layout/only data 
pane: data/pane 
all[negative? size/x size/x: data/size/x]
all[negative? size/y size/y: data/size/y]
data: none 
action/on-resize self
]
]
password: make field[
tip:{USAGE:
password
password "Secret"
DESCRIPTION:
Editable password field with text displayed as a series of large dots.}
size: 50x5 
color: colors/page 
font: make default-font[size: to integer! sizes/font * 1.5 name: font-fixed]
rebind: make function![][
color: colors/page 
font/size: to integer! sizes/font * 1.5
]
init: make function![/local p char-width radius][
p: self 
para: make para[]
pane: make subface[
color: colors/page 
effect:[draw[pen colors/text fill-pen colors/text]]
feel: make default-feel[]
span: all[p/span find p/span #W #W]
]
char-width: first size-text make rebface[
text: "M" font: make default-font[
size: to integer! sizes/font * 1.5 name: font-fixed
]
]
radius: to integer! char-width + 1 / 3 
pane/size: size 
pane/feel/redraw: make function![face act pos /local offset]compose/deep[
if act = 'show[
clear skip face/effect/draw 4 
either all[view*/focal-face = face/parent-face face/parent-face/text = head view*/caret][
repeat i length? head view*/caret[
insert tail face/effect/draw reduce['circle i * (as-pair char-width 0) + (as-pair 1 - radius sizes/line / 2) (radius)]
]
offset: (as-pair char-width 0) * index? view*/caret 
offset/x: offset/x - (char-width) 
insert tail face/effect/draw reduce[
'box offset + (as-pair 2 2) offset + (as-pair 3 sizes/line - 4)
]
][
repeat i length? face/parent-face/text[
insert tail face/effect/draw reduce['circle i * (as-pair char-width 0) + (as-pair 1 - radius sizes/line / 2) (radius)]
]
]
]
]
]
]
pie-chart: make rebface[
tip:{USAGE:
pie-chart data["Red" red 60 "Green" green 30 "Blue" blue 10]
DESCRIPTION:
A pie-chart.
OPTIONS:
'no-label to turn labels off
[start n]where n is the degrees value
[explode n]when n is the number of pixels}
size: 50x50 
feel: make default-feel[
redraw: make function![face act pos /local plot total angle pie-size label-offset label-distance label-size][
if act = 'show[
clear plot: skip last face/effect 4 
total: face/degrees 
pie-size: face/size / 2 - 1x1 - as-pair face/explode face/explode 
label-distance: pie-size * 0.75 
foreach[label color val]face/data[
angle: 360 * val / face/sum 
insert plot reduce[
'fill-pen color 
'arc face/size / 2 + as-pair face/explode * (cosine (total + (angle / 2))) - 1 face/explode * (sine (total + (angle / 2))) - 1 pie-size total angle 
'closed
]
unless find face/options 'no-label[
default-text/text: label 
label-size: size-text default-text 
label-offset: as-pair label-distance/x * (cosine (total + (angle / 2))) face/explode + label-distance/y * (sine (total + (angle / 2))) 
label-offset/x: label-offset/x - (label-size/x / 2) 
label-offset/y: label-offset/y - (label-size/y / 2) 
insert tail plot reduce['text 'anti-aliased form label face/size / 2 + label-offset]
]
total: total + angle 
if total >= 360[total: total - 360]
]
]
]
]
effect:[draw[pen colors/text font default-font]]
sum: 0 
explode: 0 
degrees: 270 
init: make function![][
data: reduce data 
explode: any[select options 'explode 0]
if select options 'start[
degrees: 270 + select options 'start 
if degrees >= 360[degrees: degrees - 360]
if degrees < 0[degrees: degrees + 360]
]
foreach[label color val]data[sum: sum + val]
]
]
progress: make rebface[
tip:{USAGE:
progress
progress data .5
DESCRIPTION:
A horizontal progress indicator.
At runtime face/data ranges from 0 to 1 indicating percentage.}
size: 50x5 
effect:[draw[pen colors/state-dark fill-pen colors/state-dark box 1x1 1x1]]
data: 0 
edge: default-edge 
feel: make default-feel[
redraw: make function![face act pos][
all[
act = 'show 
face/effect/draw/7/x: max 1 face/size/x - 2 - sizes/edge - sizes/edge * face/data: min 1 max 0 face/data
]
]
]
action: make default-action[
on-resize: make function![face][face/effect/draw/6/y: face/size/y - 2 - sizes/edge - sizes/edge]
]
init: make function![][action/on-resize self]
]
radio-group: make rebface[
tip:{USAGE:
radio-group data["Option A" "Option B"]
radio-group data[2 "On" "Off"]
DESCRIPTION:
Group of mutually exclusive radio buttons.
Alignment is vertical unless height is specified as line height.
An integer provided as the first entry in the block indicates the default selection.}
size: 50x-1 
pane:[]
picked: none 
selected: make function![][
all[picked pick data picked]
]
select-item: make function![item[integer! none!]][
either any[none? item zero? item][
item: either picked = 1[2][1]
pane/:item/feel/engage/reset pane/:item 'down none
][
all[item <> picked pane/:item/feel/engage pane/:item 'down none]
]
]
init: make function![/local off siz pos index][
unless string? first data: reduce data[
picked: first data 
remove data
]
all[negative? size/y size/y: sizes/line * length? data]
off: either size/y > sizes/line[
siz: as-pair size/x sizes/line 
as-pair 0 sizes/line
][
siz: as-pair size/x / length? data sizes/line 
as-pair siz/x 0
]
pos: 0x0 
index: 1 
foreach label data[
insert tail pane make subface[
offset: pos 
size: siz 
text: label 
effect: compose/deep[draw[pen (colors/outline-light) fill-pen (colors/page) circle (as-pair sizes/cell * 1.5 sizes/cell * 2.5) (sizes/cell * 1.5)]]
data: index 
font: default-font 
para: default-para-indented 
feel: make default-feel[
over: make function![face act pos][
face/effect/draw/pen: either act[colors/outline-dark][colors/outline-light]
show face
]
engage: make function![face act event /reset /local pf][
do select[
down[
if all[pf: face/parent-face pf/picked <> face/data][
all[
pf/picked 
clear skip pf/pane/(pf/picked)/effect/draw 7 
show pf/pane/(pf/picked)
]
either reset[pf/picked: none][
pf/picked: face/data 
insert tail face/effect/draw reduce[
'pen colors/state-dark 'fill-pen colors/state-dark 'circle as-pair sizes/cell * 1.5 sizes/cell * 2.5 sizes/cell - 1
]
show face 
pf/action/on-click pf
]
]
]
away[face/feel/over face false 0x0]
]act
]
]
]
pos: pos + off 
index: index + 1
]
all[
integer? picked 
insert tail pane/:picked/effect/draw reduce[
'pen colors/state-dark 'fill-pen colors/state-dark 'circle as-pair sizes/cell * 1.5 sizes/cell * 2.5 sizes/cell - 1
]
]
]
]
scroll-panel: make rebface[
tip:{USAGE:
scroll-panel data[sheet]
DESCRIPTION:
A panel used to group widgets within a scrollable container.
OPTIONS:
'offset keeps the original offset}
size: 50x50 
pane:[]
edge: outline-edge 
action: make default-action[
on-click: make function![face][system/view/focal-face: face]
on-scroll: make function![face scroll /page][
either page[
all[face/pane/3/show? face/pane/3/set-data scroll]
][
all[face/pane/2/show? face/pane/2/set-data scroll]
]
]
on-resize: make function![face /child /local p1 p2 p3 p4][
p1: face/pane/1 
p2: face/pane/2 
p3: face/pane/3 
p4: face/pane/4 
p2/show?: either p1/size/y <= face/size/y[face/sld-offset/x: 0 false][face/sld-offset/x: sizes/slider true]
p3/show?: either p1/size/x <= face/size/x[face/sld-offset/y: 0 false][face/sld-offset/y: sizes/slider true]
p4/show?: either any[p2/show? p3/show?][true][false]
p2/ratio: min 1 face/size/y - face/sld-offset/y / p1/size/y 
p3/ratio: min 1 face/size/x - face/sld-offset/x / p1/size/x 
if child[
all[p2/ratio = 1 p2/data: p1/offset/y: 0]
all[p3/ratio = 1 p3/data: p1/offset/x: 0]
show face
]
]
]
p1: p2: p3: p4: none 
sld-offset: 0x0 
init: make function![/local p][
p: self 
data: layout/only data 
insert pane either 1 = length? data/pane[first data/pane][data]
all[negative? size/x size/x: data/size/x]
all[negative? size/y size/y: data/size/y]
data: none 
p1: first pane 
color: p1/color 
unless find options 'offset[p1/offset: 0x0]
p1/edge: none 
if span[
all[find span #H p1/span: #H]
all[find span #W p1/span: #W]
all[find span #H find span #W p1/span: #HW]
]
insert tail pane make slider[
tip: none 
offset: as-pair p/size/x - sizes/slider 0 
size: as-pair sizes/slider p/size/y - sizes/slider 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#XH]
find p/span #H[#H]
find p/span #W[#X]
]
options:[arrows]
action: make default-action[
on-click: make function![face][
p1/offset/y: negate p1/size/y + sld-offset/y - p/size/y * face/data 
show p1
]
]
]
p2: second pane 
p2/init 
insert tail pane make slider[
tip: none 
offset: as-pair 0 p/size/y - sizes/slider 
size: as-pair p/size/x - sizes/slider sizes/slider 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#YW]
find p/span #H[#Y]
find p/span #W[#W]
]
options:[arrows]
action: make default-action[
on-click: make function![face][
p1/offset/x: negate p1/size/x + sld-offset/x - p/size/x * face/data 
show p1
]
]
]
p3: third pane 
p3/init 
insert tail pane make symbol[
offset: p/size - as-pair sizes/slider sizes/slider 
size: as-pair sizes/slider sizes/slider 
span: case[
none? p/span[none]
all[find p/span #H find p/span #W][#XY]
find p/span #H[#Y]
find p/span #W[#X]
]
edge: none 
data: 'record 
action: make default-action[
on-click: make function![face /local p][
p: face/parent-face 
either p1/offset = 0x0[
p2/data: p3/data: 1
][
p2/data: p3/data: 0
]
all[p2/show? show p2]
all[p3/show? show p3]
]
]
]
p4: fourth pane 
p4/init 
action/on-resize self
]
]
sheet: make rebface[
tip:{USAGE:
sheet
sheet options[size 3x3 width 2]
sheet options[size 3x3 widths[2 3 4]]
sheet data[A1 1 A2 2 A3 "=A1 + A2"]
DESCRIPTION:
Simple spreadsheet, based on rebocalc.r, with formulas calculated left to right, top to bottom.
A cell is either a scalar value, string, or a formula starting with "=".
Scalar values are automatically right-justified, series values left-justified.
Remember to put spaces between each item in a formula and use () where needed.
OPTIONS:
'size specifies number of columns and rows
'width specifies cell width in relation to cell height
'widths specifies n cell widths}
size: -1x-1 
color: colors/outline-light 
pane:[]
data:[]
cells: none 
load-data: make function![dat /local v][
insert clear data dat 
foreach cell cells[
cell/text: either v: select data cell/data[form v][copy ""]
enter cell
]
compute 
show cells
]
save-data: make function![][
clear data 
foreach cell cells[
unless empty? cell/text[
insert tail data either cell/init[
reduce[cell/data join "=" form cell/init]
][
reduce[cell/data get cell/data]
]
]
]
]
enter: make function![face /local v][
face/color: colors/page 
face/font/align: 'left 
attempt[unset face/data]
face/init: none 
all[empty? trim face/text exit]
v: attempt[load either #"=" = first face/text[next face/text][face/text]]
either any[series? v word? v][
either #"=" = first face/text[face/color: colors/outline-light face/init: :v][set face/data face/text]
][
face/font/align: 'right 
set face/data v
]
]
compute: make function![/local v][
foreach cell cells[
if cell/init[
either all[word? cell/init string? get cell/init][v: get cell/init][
unless v: attempt[do cell/init][cell/text: "ERROR!"]
]
cell/font/align: either series? v['left]['right]
cell/text: form v 
set cell/data cell/text 
show cell
]
]
]
init: make function![/local cols rows p pos char v widths row-size][
either pair? v: select options 'size[cols: v/x rows: v/y][
either empty? data[cols: 6 rows: 12][
cols: #"A" 
rows: 1 
foreach[cell val]data[
cols: max cols uppercase first form cell 
rows: max rows to integer! next form cell
]
cols: to integer! cols - 64
]
]
widths: copy[]
case[
v: select options 'widths[insert widths v]
v: select options 'width[insert/dup widths v cols]
true[insert/dup widths 4 cols]
]
row-size: as-pair sizes/line * 2 sizes/line 
if negative? size/x[
size/x: row-size/x + cols + 1 
foreach w widths[size/x: w * sizes/line + size/x]
]
all[negative? size/y size/y: rows * sizes/line + rows + row-size/y + 1]
char: #"A" 
pos: as-pair row-size/x + 1 0 
repeat x cols[
insert tail pane make subface[
offset: pos 
size: as-pair sizes/line * pick widths x sizes/line 
text: form char 
color: colors/theme-dark 
font: default-font-heading
]
char: char + 1 
pos/x: sizes/line * (pick widths x) + pos/x + 1
]
pos: as-pair 0 sizes/line + 1 
repeat y rows[
insert tail pane make subface[
offset: pos 
size: row-size 
text: form y 
color: colors/theme-dark 
font: default-font-heading
]
pos/y: pos/y + sizes/line + 1
]
p: self 
cells: tail pane 
pos: row-size + 1x1 
repeat y rows[
pos/x: row-size/x + 1 
char: #"A" 
repeat x cols[
v: to word! join char y 
insert tail pane make rebface[
type: 'field 
offset: pos 
size: as-pair sizes/line * pick widths x sizes/line 
text: form any[select p/data v ""]
color: colors/page 
font: make default-font[]
para: make default-para[]
feel: edit/feel 
data: v 
action: make default-action[
on-focus: make function![face][
all[face/init face/text: join "=" form face/init]
face/font/align: 'left 
select-face face 
true
]
on-unfocus: make function![face][
deselect-face/fill face 
enter face compute face/para/scroll: 0x0 
true
]
]
]
char: char + 1 
pos/x: sizes/line * (pick widths x) + pos/x + 1
]
pos/y: pos/y + sizes/line + 1
]
unless empty? data[
foreach cell cells[
unless empty? cell/text[enter cell]
]
compute
]
]
]
slider: make rebface[
tip:{USAGE:
slider
slider data .5[print face/data]
DESCRIPTION:
A slider control. Its size determines whether it is vertical or horizontal.
At runtime face/data ranges from 0 to 1 indicating percentage.
OPTIONS:
'arrows adds an arrow to each end of the slider creating a scroller
'together forces the arrows to appear together
[ratio n]where n indicates the initial dragger size}
size: 5x50 
data: 0 
color: colors/outline-light 
effect:[
draw[
pen colors/outline-dark fill-pen colors/theme-light box 0x0 10x10 
fill-pen colors/theme-light box 0x0 0x0 
fill-pen colors/theme-light box 0x0 0x0 
pen colors/page 
fill-pen colors/page triangle 0x0 0x0 0x0 
fill-pen colors/page triangle 0x0 0x0 0x0
]
]
ratio: 0.1 
step: 5E-2 
hold: none 
state: none 
flags: none 
set-data: make function![new[integer! decimal! pair!]/local old][
old: data 
data: min 1 max 0 either pair? new[
data + either negative? new/y[negate step][step]
][new]
all[data <> old show self]
]
feel: make default-feel[
redraw: make function![
face act pos 
/local width state-blk freedom axis dragdom arrow-width arrows? together? draw-blk arrow-blk arrow-size
][
if act = 'draw[
if face/state <> compose state-blk:[(face/data) (face/size) (face/ratio) (face/flags)][
width: min face/size/x face/size/y 
face/ratio: any[face/ratio 0.1]
freedom: 1 - face/ratio 
axis: either face/size/y > face/size/x['y]['x]
dragdom: face/size/:axis 
arrow-width: 0 
if all[face/flags arrows?: find face/flags 'arrows][
arrow-width: min face/size/x face/size/y 
dragdom: dragdom - (2 * arrow-width) 
together?: find face/flags 'together
]
draw-blk: face/effect/draw 
arrow-blk: at draw-blk 8 
either arrows?[
arrow-size: as-pair arrow-width - 1 arrow-width - 1 
arrow-blk/4: either together?[dragdom * either axis = 'y[0x1][1x0]][0x0]
arrow-blk/5: arrow-blk/4 + arrow-size 
arrow-blk/9: dragdom + arrow-width * either axis = 'y[0x1][1x0]
arrow-blk/10: arrow-blk/9 + arrow-size 
arrow-blk/16: arrow-blk/4 + (width * 0.1 * either axis = 'y[5x2][2x5]) 
arrow-blk/17: arrow-blk/4 + (width * 0.1 * either axis = 'y[2x7][7x8]) 
arrow-blk/18: arrow-blk/4 + (width * 0.1 * either axis = 'y[8x7][7x2]) 
arrow-blk/22: arrow-blk/9 + (width * 0.1 * either axis = 'y[5x8][8x5]) 
arrow-blk/23: arrow-blk/9 + (width * 0.1 * either axis = 'y[8x3][3x2]) 
arrow-blk/24: arrow-blk/9 + (width * 0.1 * either axis = 'y[2x3][3x8])
][
repeat pos[4 5 9 10 16 17 18 22 23 24][arrow-blk/:pos: 0x0]
]
draw-blk/6: 0x0 
draw-blk/6/:axis: (dragdom * freedom * min 1 max 0 face/data) + either together?[0][arrow-width]
draw-blk/7: draw-blk/6 + width - 1 
draw-blk/7/:axis: (freedom * min 1 max 0 face/data) + face/ratio * (dragdom - 1) + either together?[0][arrow-width]
draw-blk/7: max draw-blk/7 draw-blk/6 + as-pair sizes/cell * 2 sizes/cell * 2 
either none? face/state[
face/state: compose state-blk
][
face/state: compose state-blk 
face/action/on-click face
]
]
]
]
engage: make function![
face act event 
/local freedom axis dragdom arrows? together? arrow-width offset more? page oft win-face
][
freedom: 1 - face/ratio 
axis: either face/size/y > face/size/x['y]['x]
dragdom: face/size/:axis 
arrow-width: 0 
if all[face/flags arrows?: find face/flags 'arrows][
arrow-width: min face/size/x face/size/y 
dragdom: dragdom - (2 * arrow-width) 
together?: find face/flags 'together
]
oft: event/offset 
if all[act = 'time event/face = view*/screen-face/pane/1][
win-face: find-window face 
oft: oft + (event/face/offset - win-face/offset)
]
offset: oft - either act = 'time[win-offset? face][0]
offset: offset/:axis - either together?[0][arrow-width]
if find[over away]act[
if all[
number? face/hold 
freedom > 0
][
face/set-data (offset - face/hold / (dragdom * freedom))
]
exit
]
if find[down time]act[
if act = 'down[face/rate: 16]
either all[
more?: offset >= (dragdom * (freedom * face/data)) 
offset < (dragdom * ((freedom * face/data) + face/ratio))
][
if act = 'down[
face/hold: offset - (dragdom * (freedom * face/data)) 
face/effect/draw/4: colors/state-light show face
]
][
case[
offset < 0[
if act = 'down[
face/hold: 'top-arrow 
face/effect/draw/9: colors/state-light show face
]
if face/hold = 'top-arrow[
face/set-data (face/data - face/step)
]
]
all[together? offset > dragdom offset < (dragdom + arrow-width)][
if act = 'down[
face/hold: 'top-arrow 
face/effect/draw/9: colors/state-light show face
]
if face/hold = 'top-arrow[
face/set-data (face/data - face/step)
]
]
offset > (dragdom + either together?[arrow-width][0])[
if act = 'down[
face/hold: 'bottom-arrow 
face/effect/draw/14: colors/state-light show face
]
if face/hold = 'bottom-arrow[
face/set-data (face/data + face/step)
]
]
true[
if act = 'down[face/hold: 'page]
if face/hold = 'page[
page: any[all[freedom = 0 0]face/ratio / freedom]
face/set-data (face/data + either more?[page][negate page])
]
]
]
]
]
if act = 'up[
face/rate: none face/hold: none 
face/effect/draw/4: face/effect/draw/9: face/effect/draw/14: colors/theme-light show face
]
]
]
rebind: make function![][color: colors/outline-light]
init: make function![][
all[number? data data: min 1 max 0 data]
flags: copy[]
all[find options 'arrows insert tail flags 'arrows]
if any[effects/arrows-together find options 'together][insert tail flags 'together]
all[find options 'ratio ratio: select options 'ratio]
]
]
spinner: make rebface[
tip:{USAGE:
spinner
spinner options[$1 $10 $1]data $5
DESCRIPTION:
Similar to a field, with arrows to increment/decrement a value by a nominated step amount.
OPTIONS:
[min max step]block of minimum, maximum and step amounts}
size: 20x5 
color: colors/page 
text: "" 
edge: theme-edge 
font: default-font-right 
para: make default-para[]
feel: edit/feel 
options:[1 10 1]
pane: copy[]
action: make default-action[
on-scroll: make function![face scroll /page][
face/text: either any[none? face/data page][
form data: either negative? scroll/y[second face/options][first face/options]
][
form face/data + either negative? scroll/y[last face/options][negate last face/options]
]
face/action/on-unfocus face
]
on-unfocus: make function![face][
either empty? face/text[
face/data: none
][
face/data: any[attempt[to type? first face/options face/text]face/data]
face/text: either face/data[form face/data: min max face/data first face/options second face/options][copy ""]
show face
]
face/action/on-click face 
true
]
]
rebind: make function![][color: colors/page]
init: make function![/local p][
all[data text: form data]
all[not empty? text data: to type? first options text]
para/margin/x: size/y - sizes/cell 
p: self 
insert pane make arrow[
tip: none 
offset: as-pair p/size/x - p/size/y + sizes/cell 0 
size: as-pair p/size/y - sizes/cell p/size/y / 2 
span: all[
p/span 
case[
all[find p/span #L find p/span #W][#OX]
find p/span #W[#X]
find p/span #L[#O]
]
]
data: 'up 
edge: none 
action: make default-action[
on-click: make function![face /local p][
p: face/parent-face 
p/data: any[attempt[to type? first p/options p/text]p/data first p/options]
p/data: p/data + third p/options 
if p/data > second p/options[p/data: second p/options]
p/text: form p/data 
edit/unlight-text 
view*/caret: none 
show p 
p/action/on-click p
]
]
]
pane/1/init 
insert tail pane make arrow[
tip: none 
offset: as-pair p/size/x - p/size/y + sizes/cell p/size/y / 2 
size: as-pair p/size/y - sizes/cell p/size/y / 2 
span: all[
p/span 
case[
all[find p/span #L find p/span #W][#OX]
find p/span #W[#X]
find p/span #L[#O]
]
]
edge: none 
action: make default-action[
on-click: make function![face /local p][
p: face/parent-face 
p/data: any[attempt[to type? first p/options p/text]p/data first p/options]
p/data: p/data - third p/options 
if p/data < first p/options[p/data: first p/options]
p/text: form p/data 
edit/unlight-text 
view*/caret: none 
show p 
p/action/on-click p
]
]
]
pane/2/init
]
esc: none 
caret: none 
undo: copy[]
]
splitter: make rebface[
tip:{USAGE:
area splitter area
DESCRIPTION:
Placed between two widgets on the same row or column.
Allows both to be resized by dragging the splitter left/right or up/down respectively.
Its size determines whether it is vertical or horizontal.}
size: 1x25 
color: colors/outline-light 
feel: make default-feel[
redraw: make function![face act pos /local f p n][
unless face/data[
f: find face/parent-face/pane face 
p: back f 
n: next f 
if face/size/y <= face/size/x[
while[face/offset/x <> p/1/offset/x][
if head? p[gui-error "Splitter failed to find previous widget"]
p: back p
]
while[face/offset/x <> n/1/offset/x][
if tail? p[gui-error "Splitter failed to find next widget"]
n: next n
]
]
face/data: reduce[first p first n]
]
]
over: make function![face act pos][
face/color: either act[colors/state-dark][colors/outline-light]
show face
]
engage: make function![face act event /local p n delta][
if event/type = 'move[
p: first face/data 
n: second face/data 
either face/size/y > face/size/x[
delta: face/offset/x - face/offset/x: min n/offset/x + n/size/x - face/size/x - 1 max p/offset/x + 1 face/offset/x + event/offset/x 
p/size/x: p/size/x - delta 
n/size/x: n/size/x + delta 
n/offset/x: n/offset/x - delta
][
delta: face/offset/y - face/offset/y: min n/offset/y + n/size/y - face/size/y - 1 max p/offset/y + 1 face/offset/y + event/offset/y 
p/size/y: p/size/y - delta 
n/size/y: n/size/y + delta 
n/offset/y: n/offset/y - delta
]
show[p face n]
]
all[act = 'away face/feel/over face false 0x0]
]
]
rebind: make function![][color: colors/outline-light]
]
style: make rebface[
tip:{USAGE:
style 20x20 data[btn "VID btn"]
style data[btn 20x20]options[size]
DESCRIPTION:
A container for a VID style.
OPTIONS:
'size use VID style size.}
size: 5x5 
data:[]
init: make function![][
unless find options 'size[insert next data size]
data: system/words/layout/tight data 
pane: data/pane/1 
size: pane/size 
data: none
]
]
symbol: make rebface[
tip:{USAGE:
symbol data 'start
symbol data 'rewind
symbol data 'left
symbol data 'pause
symbol data 'stop
symbol data 'record
symbol data 'right
symbol data 'forward
symbol data 'end
symbol data 'up
symbol data 'down
symbol -1 "Some text"
DESCRIPTION:
Basic single-color shapes, such as those found on media players, on an "arrow" type button.
Uses "Webdings" if available, otherwise simple ASCII equivalents.}
size: 5x-1 
text: "" 
edge: default-edge 
font: default-font-heading 
feel: make default-feel[
redraw: make function![face act pos][
if act = 'show[
face/color: either face/data[colors/state-light][colors/theme-light]
]
]
engage: make function![face act event][
do select[
time[all[face/data face/action/on-click face]]
down[face/data: on]
up[face/data: off face/action/on-click face]
over[face/data: on]
away[face/data: off]
]act 
show face
]
]
action: make default-action[
on-resize: make function![face][
face/font/size: to integer! (min face/size/x face/size/y) * either face/font/style[0.6][0.8]
all[odd? face/font/size face/font/size: face/font/size + 1]
all[
not effects/webdings 
negative? face/font/space/x 
face/font/space/x: face/font/size * -0.2
]
]
]
init: make function![][
either all[data empty? text][
font: make font either effects/webdings[[name: "webdings"]][[space: -1x0 style: 'bold]]
all[negative? size/y size/y: size/x]
text: pick do select[
start[["9" "|<<"]]
rewind[["7" "<<"]]
left[["3" "<"]]
pause[[";" "| |"]]
stop[["<" "[]"]]
record[["=" "O"]]
right[["4" ">"]]
forward[["8" ">>"]]
end[[":" ">>|"]]
up[["5" "^^"]]
down[["6" "v"]]
]data effects/webdings
][
font: make font[style: 'bold]
all[negative? size/y size/y: sizes/line]
font/size: to integer! size/y * 0.6 
all[negative? size/x size/x: 6 + first size-text self]
]
data: off 
action/on-resize self
]
]
table: make rebface[
tip:{USAGE:
table options["Name" left .6 "Age" right .4]data["Bob" 32 "Pete" 45 "Jack" 29]
DESCRIPTION:
Columns and rows of values formatted according to a header definition block.
OPTIONS:
'multi allows multiple rows to be selected at once
'no-dividers hides column dividers
["Title" align width]triplets for each column}
size: 50x25 
color: colors/page 
pane:[]
data:[]
edge: default-edge 
redraw: make function![][]
selected: make function![][]
picked:[]
widths:[]
aligns:[]
cols: none 
rows: make function![][pane/1/rows]
total-width: none 
add-row: func[
row[block!]
/position 
pos[integer!]
][
either pos[
pos: (pos - 1) * cols
][
pos: 1 + length? data
]
insert at data pos row 
redraw
]
remove-row: func[
row[integer! block!]
/local rows removed
][
if integer? row[row: to-block row]
rows: sort/reverse copy row 
repeat n length? rows[
row: max 1 min rows/:n (length? data) / cols 
remove/part skip data (row - 1) * cols cols
]
redraw
]
alter-row: func[
row[integer! block!]
values[block!]
/local rows last-picked
][
last-picked: copy picked 
if integer? row[row: to-block row]
rows: row 
if (length? rows) <> (length? values)[
values: reduce[values]
]
if (length? rows) = (length? values)[
repeat n length? rows[
row: max 1 min rows/:n (length? data) / cols 
change skip data (row - 1) * cols copy/part values/:n cols
]
]
redraw 
unless empty? last-picked[select-row/no-action last-picked]
]
select-row: func[
row[integer! none! block!]
/no-action 
/local rows lines
][
clear picked 
if row[
row: either integer? row[to block! row][sort copy row]
rows: pane/1/rows 
lines: pane/1/lines 
foreach r row[
r: max 1 min rows r 
insert picked r
]
if any[
row/1 < (pane/1/scroll + 1) 
row/1 > (pane/1/scroll + pane/1/lines)
][
pane/1/pane/2/data: 1 / (rows - lines) * ((min (rows - lines + 1) row/1) - 1)
]
unless no-action[action/on-click self]
]
system/view/caret: pane/1/pane/1/text 
system/view/focal-face: pane/1/pane/1 
show self
]
set-columns: func[
options[block!]
/no-show 
/no-dividers 
/local col-offset p last-col dividers?
][
p: self 
if (length? pane) > 2[
remove/part next pane 2 * cols - 1
]
clear widths 
clear aligns 
cols: (length? options) / 3 
p/pane/1/cols: cols 
p/pane/1/data: p/data 
col-offset: total-width: 0 
foreach[column halign width]options[
unless any[string? column word? column][
gui-error "Table expected column name to be a string or word"
]
unless find[left center right]halign[
gui-error {Table expected column align to be one of left, center or right}
]
unless decimal? width[
gui-error "Table expected column width to be a decimal"
]
insert tail aligns halign 
insert tail widths width: to integer! p/size/x * width 
total-width: total-width + width 
insert back tail pane make subface[
offset: as-pair col-offset 0 
size: as-pair width - sizes/cell sizes/line 
text: form column 
color: colors/theme-dark 
col: length? widths 
para: make default-para[margin: as-pair sizes/line + 2 2]
font: make default-font-heading[align: aligns/:col]
feel: make default-feel[
over: make function![face act pos][
face/color: either act[colors/theme-light][colors/theme-dark]
show face
]
engage: make function![face act event /local arrow][
if act = 'down[
arrow: last parent-face/pane 
unless arrow/col = col[
arrow/col: col 
arrow/asc: none 
arrow/offset/x: offset/x + size/x - (sizes/cell * 3)
]
arrow/action arrow
]
]
]
]
col-offset: col-offset + width 
if cols > length? widths[
insert back tail pane make subface[
offset: as-pair col-offset - sizes/cell 0 
size: as-pair 2 either no-dividers[sizes/line][p/size/y]
color: colors/outline-dark 
span: unless no-dividers[all[p/span find p/span #H #H]]
col-1: length? widths 
col-2: 1 + length? widths 
feel: make default-feel[
over: make function![face act pos][
color: either act[colors/state-dark][colors/outline-dark]
show face
]
engage: make function![face act event /local delta arrow][
switch/default act[
down[data: event/offset/x]
up[data: none feel/over face false 0x0]
alt-up[data: none feel/over face false 0x0]
][
if all[
data 
event/type = 'move 
event/offset/x <> data
][
delta: event/offset/x - data 
delta: either positive? delta[
min delta parent-face/pane/(col-2 * 2)/size/x - (sizes/line * 2)
][
max delta negate parent-face/pane/(col-1 * 2)/size/x - (sizes/line * 2)
]
unless zero? delta[
arrow: last parent-face/pane 
if arrow/col = col-1[arrow/offset/x: arrow/offset/x + delta]
offset/x: offset/x + delta 
widths/:col-1: widths/:col-1 + delta 
widths/:col-2: widths/:col-2 - delta 
parent-face/pane/(col-1 * 2)/size/x: widths/:col-1 - sizes/cell 
parent-face/pane/(col-2 * 2)/offset/x: offset/x + sizes/cell 
either cols = col-2[
parent-face/pane/(col-2 * 2)/size/x: widths/:col-2
][
parent-face/pane/(col-2 * 2)/size/x: widths/:col-2 - sizes/cell
]
show parent-face
]
]
]
]
]
]
]
]
p/options: pane/1/options 
last-col: first back back tail pane 
last-col/size/x: last-col/size/x + sizes/cell + size/x - total-width 
if negative? last-col/size/x[
gui-error "Table column widths are too large"
]
widths/:cols: widths/:cols + size/x - total-width 
if all[span find span #W][
last-col/span: #W
]
pane/1/init 
unless no-show[
show self
]
]
rebind: make function![][color: colors/page]
init: make function![/local p opts dividers?][
opts:[table]
if 'multi = first options[remove options insert tail opts 'multi]
dividers?: either 'no-dividers = first options[remove options false][true]
if 'multi = first options[remove options insert tail opts 'multi]
unless integer? cols: divide length? options 3[
gui-error "Table has an invalid options block"
]
if all[not empty? data decimal? divide length? data cols][
gui-error "Table has an invalid data block"
]
p: self 
insert tail pane make face-iterator[
offset: as-pair 0 sizes/line 
size: p/size - as-pair 0 sizes/line 
span: either p/span[copy p/span][none]
data: p/data 
cols: p/cols 
widths: p/widths 
aligns: p/aligns 
options: opts 
picked: p/picked 
action: get in p/action 'on-click 
alt-action: get in p/action 'on-alt-click 
dbl-action: get in p/action 'on-dbl-click
]
insert tail pane make subface[
offset: as-pair negate sizes/line sizes/cell 
size: as-pair sizes/cell * 3 sizes/cell * 3 
effect:[arrow colors/text rotate 0]
cols: p/cols 
col: none 
asc: true 
feel: make default-feel[
engage: make function![face act event][
all[act = 'down face/action face]
]
]
action: make function![face /local last-selected][
asc: either none? asc[true][complement asc]
effect/rotate: either asc[0][180]
last-selected: selected 
either asc[
sort/skip/compare parent-face/data cols col
][
sort/skip/compare/reverse parent-face/data cols col
]
all[
last-selected 
select-row/no-action (((index? find parent-face/data last-selected) - 1) / cols) + 1
]
show parent-face
]
]
either dividers?[set-columns/no-show options][set-columns/no-show/no-dividers options]
redraw: get in pane/1 'redraw 
selected: get in pane/1 'selected 
feel: make default-feel[
redraw: make function![face act pos /local total arrow][
if act = 'show[
total: 0 
foreach width widths[total: total + width]
widths/:cols: widths/:cols + size/x - total 
arrow: last pane 
if arrow/col = cols[arrow/offset/x: size/x + sizes/cell - sizes/line]
]
]
]
]
]
tab-panel: make rebface[
tip:{USAGE:
tab-panel data["A"[field]"B"[field]"C"[field]]
tab-panel data["1"[field]action[face/color: red]"2"[field]]
DESCRIPTION:
A panel with a set of tabs.
Each tab spec may be preceded by an action block spec.
OPTIONS:
'action do action of initial tab (if any)
[tab n]where n specifies tab to initially open with (default 1)
no-tabs do not display tabs (overlay mode)}
size: -1x-1 
pane: copy[]
tabs: 0 
selected: make function![][
either find options 'no-tabs[data][pane/(tabs + data)/text]
]
select-tab: make function![num[integer!]][
if any[num < 1 num > tabs][exit]
pane/:data/show?: false 
edit/unfocus 
either find options 'no-tabs[
pane/(data: num)/show?: true
][
pane/(tabs + data)/color: colors/theme-dark 
pane/(tabs + data)/font/color: colors/page 
pane/(data: num)/show?: true 
pane/(tabs + data)/color: colors/page 
pane/(tabs + data)/font/color: colors/text
]
pane/(data)/action pane/:data 
show self
]
replace-tab: make function![num[integer!]block[block!]/title text[string!]][
pane/:num: layout/only block 
pane/:num/offset: as-pair 0 either find options 'no-tabs[0][sizes/line]
pane/:num/color: colors/page 
pane/:num/edge: outline-edge 
all[title pane/(tabs + num)/text: text]
if data <> num[pane/:num/show?: false]
show self
]
init: make function![/local tab tab-offset trigger][
tab-offset: 0x0 
foreach[title spec]data[
either title = 'action[
trigger: spec
][
tabs: tabs + 1 
tab: layout/only spec 
tab/offset/y: either find options 'no-tabs[0][sizes/line]
tab/color: colors/page 
tab/edge: outline-edge 
tab/show?: false 
tab/span: #LV 
tab/action: either trigger[make function![face /local var]trigger][none]
insert at pane tabs tab 
unless find options 'no-tabs[
insert tail pane make subface[
offset: tab-offset 
size: as-pair 1 sizes/line + 1 
text: title 
effect: reduce['round colors/outline-light effects/radius sizes/edge]
data: tabs 
color: colors/theme-dark 
font: make default-font-heading[color: colors/page]
para: default-para 
feel: make default-feel[
over: make function![face act pos][
face/color: either act[colors/theme-light][
either face/data = face/parent-face/data[colors/page][colors/theme-dark]
]
show face
]
engage: make function![face act event /local p][
all[find[down alt-down]act face/parent-face/select-tab face/data]
]
]
]
tab: last pane 
tab/size/x: sizes/line + first size-text tab 
tab-offset/x: tab-offset/x + tab/size/x + 2
]
trigger: none
]
]
all[
negative? size/x 
repeat i tabs[size/x: max size/x pane/:i/size/x]
]
all[
negative? size/y 
repeat i tabs[size/y: max size/y pane/:i/size/y]
size/y: size/y + either find options 'no-tabs[0][sizes/line]
]
repeat i tabs[
all[span find span #H insert pane/:i/span #H]
all[span find span #W insert pane/:i/span #W]
]
pane/(data: any[select options 'tab 1])/show?: true 
unless find options 'no-tabs[select-tab data]
all[find options 'action pane/(data)/action pane/:data]
]
]
text: make heading[
tip:{USAGE:
text "A text string."
text "Blue text" text-color blue
text "Bold text" bold
text "Italic text" italic
text "Underline text" underline
DESCRIPTION:
Normal text.}
font: default-font
]
text-list: make rebface[
tip:{USAGE:
text-list data["One" "Two"]
text-list data ctx-rebgui/locale*/colors
text-list data[1 2][print face/selected]
DESCRIPTION:
A single column list with a scroller.
OPTIONS:
'multi allows multiple rows to be selected at once}
size: 50x25 
color: colors/page 
data:[]
edge: outline-edge 
redraw: make function![][]
selected: make function![][]
picked:[]
rows: make function![][pane/rows]
select-row: make function![
row[integer! none! block!]
/no-action 
/local rows lines
][
clear picked 
if row[
row: either integer? row[to block! row][sort copy row]
rows: pane/rows 
lines: pane/lines 
foreach r row[
r: max 1 min rows r 
insert picked r
]
unless no-action[action/on-click self]
]
show self
]
rebind: make function![][color: colors/page]
init: make function![/local p][
p: self 
pane: make face-iterator[
size: p/size 
span: either p/span[copy p/span][none]
data: p/data 
options: p/options 
picked: p/picked 
action: get in p/action 'on-click 
alt-action: get in p/action 'on-alt-click 
dbl-action: get in p/action 'on-dbl-click
]
pane/init 
redraw: get in pane 'redraw 
selected: get in pane 'selected
]
]
title-group: make rebface[
tip:{USAGE:
title-group %images/setup.png data "Title" "Body"
DESCRIPTION:
A title and text with an optional image to the left.
If an image is specified then height is set to image height.}
font: default-font-top 
rebind: make function![][
font/name: effects/font 
font/size: sizes/font
]
init: make function![/local p indent][
indent: either image[size/y: image/size/y image/size/x + sizes/line][sizes/line]
p: self 
pane: make subface[
offset: as-pair indent sizes/line 
size: as-pair p/size/x - indent - sizes/line 10000 
text: p/data 
font: make default-font-bold[size: to integer! sizes/font / 0.75]
para: default-para-wrap
]
pane/size: 5x5 + size-text pane 
para: make default-para-wrap compose[
origin: (as-pair indent p/pane/size/y + sizes/line + sizes/line) 
margin: (as-pair sizes/line 0)
]
all[not image negative? size/y size/y: 10000 size/y: para/origin/y + second size-text self]
data: none
]
]
tool-bar: make rebface[
tip:{USAGE:
tool-bar silver data["Open" %images/document-open.png[request-file]pad 2 none "Save" %images/document-save.png[]]
DESCRIPTION:
An iconic toolbar. Height is set to 30 pixels.
[pad n none]sequence works as per 'pad in the display function.}
size: 100x-1 
pane:[]
color: colors/outline-light 
rebind: make function![][color: colors/outline-light]
init: make function![/local icon-offset][
size/y: 30 
icon-offset: 2x2 
foreach[txt icon spec]data[
either string? txt[
insert tail pane make subface[
offset: icon-offset 
size: 22x22 
text: "" 
image: any[
if word? icon[get icon]
if file? icon[load icon]
icon
]
tip: txt 
feel: make default-feel[
over: make function![face act pos][
face/color: either act[colors/state-light][none]
show face
]
engage: make function![face act event][
do select[
down[face/action face]
up[face/feel/over face false none]
away[face/feel/over face false none]
]act
]
]
action: make function![face /local var]spec
]
icon-offset: icon-offset + 24x0
][
icon-offset/x: icon * sizes/cell + icon-offset/x
]
]
data: none
]
]
tooltip: make rebface[
tip:{USAGE:
tooltip "Some text."
DESCRIPTION:
Tooltip text.}
size: -1x-1 
effect:[draw[pen colors/outline-dark line-width sizes/edge fill-pen yello box 0x0 0x0 effects/radius]]
font: default-font 
para: make default-para[origin: 4x4 margin: 4x4]
rate: 2 
init: make function![][
either all[negative? size/x negative? size/y][
size: 10000x10000 
size: 8 + size-text self
][
all[negative? size/x para: default-para-wrap size/x: 10000 size/x: 8 + first size-text self]
all[negative? size/y para: default-para-wrap size/y: 10000 size/y: 8 + second size-text self]
]
poke effect/draw 9 size - 1x1
]
]
tree: make rebface[
tip:{USAGE:
tree data["Pets"["Cat" "Dog"]"Numbers"[1 2 3]]
DESCRIPTION:
Values arranged in a collapsible hierarchy.
OPTIONS:
'expand starts with all nodes expanded
'resize change face/size as tree is expanded / collapsed}
size: 50x25 
color: colors/page 
pane:[]
data:[]
edge: outline-edge 
chain: 
pos: 
expand?: 
p: 
old-face: none 
width: 
height: 0 
show-node: make function![items /no-expand][
foreach item items[
either block? item[
either expand?[show-node item][show-node/no-expand item]
][
expand?: either no-expand[
pane/1/offset/y: negate sizes/line 
false
][
pane/1/offset/y: pos 
pos: pos + sizes/line 
if find options 'resize[
height: height + sizes/line 
width: max width pane/1/offset/x + pane/1/size/x
]
either pane/1/expand?[true][false]
]
pane: next pane
]
]
]
show-tree: make function![][
pos: height: width: 0 
show-node data 
pane: head pane 
if find options 'resize[
size: as-pair width height 
all[parent-face parent-face/action/on-resize/child parent-face]
]
show self
]
build-tree: make function![items /local last-item][
foreach item items[
either block? item[
last-item: last pane 
last-item/pane/effect/rotate: either find options 'expand[last-item/expand?: true 180][last-item/expand?: false 90]
insert tail chain last last-item/data 
pos: pos + sizes/line 
build-tree item 
pos: pos - sizes/line 
remove back tail chain
][
insert tail pane make subface[
offset: as-pair pos 0 
size: as-pair sizes/line + 4 + first size-text make default-text[text: form item]sizes/line 
text: form item 
data: compose[(chain) (item)]
span: all[p/span find p/span #W #W]
pane: make subface[
size: as-pair sizes/line sizes/line 
effect: copy[arrow rotate 90]
]
font: make default-font[]
para: default-para-indented 
feel: make default-feel[
engage: make function![face act event][
if act = 'down[
all[old-face old-face/font/color: colors/text set-color old-face none]
unless none? face/expand?[
face/pane/effect/rotate: either face/expand?[face/expand?: false 90][face/expand?: true 180]
show-tree
]
face/font/color: colors/page 
set-color face colors/state-light 
old-face: face 
face/parent-face/action/on-click face
]
]
]
expand?: none
]
]
]
]
rebind: make function![][color: colors/page]
init: make function![][
p: self 
pos: 0 
chain: copy[]
build-tree data 
show-tree
]
]
]
layout: make function![
spec[block!]"Block of widgets, attributes and keywords" 
/only "Do not change face offset" 
/local 
view-face 
here 
margin-size indent-width xy gap-size max-width max-height last-widget widget-face arg append-widget left-to-right? 
after-count after-limit 
word 
widget 
button-size 
field-size 
label-size 
text-size 
action-alt-click 
action-away 
action-click 
action-dbl-click 
action-edit 
action-focus 
action-key 
action-over 
action-resize 
action-scroll 
action-unfocus 
attribute-size 
attribute-span 
attribute-text 
attribute-text-color 
attribute-text-style 
attribute-color 
attribute-image 
attribute-effect 
attribute-data 
attribute-tip 
attribute-edge 
attribute-font 
attribute-para 
attribute-feel 
attribute-rate 
attribute-show? 
attribute-options 
attribute-keycode
][
margin-size: xy: sizes/cell * as-pair sizes/margin sizes/margin 
gap-size: sizes/cell * as-pair sizes/gap sizes/gap 
indent-width: 0 
max-width: xy/x 
max-height: xy/y 
left-to-right?: true 
after-count: 1 
after-limit: 10000 
view-face: make rebface[
pane: copy[]
color: colors/page 
effect: all[not only effects/window]
options: copy[activate-on-show]
keycodes: copy[]
]
word: 
widget: 
button-size: 
field-size: 
label-size: 
text-size: 
action-alt-click: 
action-away: 
action-click: 
action-dbl-click: 
action-edit: 
action-focus: 
action-key: 
action-over: 
action-resize: 
action-scroll: 
action-unfocus: 
attribute-size: 
attribute-span: 
attribute-text: 
attribute-text-color: 
attribute-text-style: 
attribute-color: 
attribute-image: 
attribute-effect: 
attribute-data: 
attribute-tip: 
attribute-edge: 
attribute-font: 
attribute-para: 
attribute-feel: 
attribute-rate: 
attribute-show?: 
attribute-options: 
attribute-keycode: none 
append-widget: make function![][
if widget[
insert tail view-face/pane make widgets/:widget[
type: either widgets/:widget/type = 'face[widget][widgets/:widget/type]
offset: xy 
size: sizes/cell * any[
if attribute-size[either pair? attribute-size[attribute-size][as-pair attribute-size size/y]]
if widget = 'bar[as-pair max-width - margin-size/x / sizes/cell size/y]
if all[button-size widget = 'button][either pair? button-size[button-size][as-pair button-size size/y]]
if all[field-size widget = 'field][either pair? field-size[field-size][as-pair field-size size/y]]
if all[label-size widget = 'label][either pair? label-size[label-size][as-pair label-size size/y]]
if all[text-size widget = 'text][either pair? text-size[text-size][as-pair text-size size/y]]
size
]
span: any[attribute-span span]
text: any[attribute-text text][text: copy text]
effect: any[attribute-effect effect]
data: either any[attribute-data = false data = false][false][any[attribute-data data]]
rate: any[attribute-rate rate]
show?: either none? attribute-show?[show?][attribute-show?]
options: copy any[attribute-options options]
color: any[attribute-color color]
image: any[attribute-image image]
text: translate text 
data: translate data 
tip: attribute-tip 
if attribute-text-color[
font: make any[font widgets/default-font][color: attribute-text-color]
]
if attribute-text-style[
font: make any[font widgets/default-font][style: attribute-text-style]
]
if attribute-edge[edge: make any[edge widgets/default-edge]attribute-edge]
if attribute-font[font: make any[font widgets/default-font]attribute-font]
if attribute-para[para: make any[para widgets/default-para]attribute-para]
if attribute-feel[feel: make feel attribute-feel]
action: make action[]
all[action-alt-click action/on-alt-click: make function![face /local var]action-alt-click]
all[action-away action/on-away: make function![face /local var]action-away]
all[action-click action/on-click: make function![face /local var]action-click]
all[action-dbl-click action/on-dbl-click: make function![face /local var]action-dbl-click]
all[action-edit action/on-edit: make function![face /local var]action-edit]
all[action-focus action/on-focus: make function![face /local var]action-focus]
all[action-key action/on-key: make function![face event /local var]action-key]
all[action-over action/on-over: make function![face /local var]action-over]
all[action-resize action/on-resize: make function![face /local var]action-resize]
all[action-scroll action/on-scroll: make function![face scroll /page /local var]action-scroll]
all[action-unfocus action/on-unfocus: make function![face /local var]action-unfocus]
if any[
get in action 'on-alt-click 
get in action 'on-click 
get in action 'on-dbl-click 
get in action 'on-edit 
get in action 'on-key 
get in action 'on-scroll
][
unless get in feel 'engage[
feel: make feel[
engage: make function![face act event][
case[
event/double-click[face/action/on-dbl-click face]
act = 'up[face/action/on-click face]
act = 'alt-up[face/action/on-alt-click face]
act = 'key[
face/action/on-key face event 
face/action/on-edit face
]
act = 'scroll-line[face/action/on-scroll face event/offset]
act = 'scroll-page[face/action/on-scroll/page face event/offset]
]
]
]
]
]
if any[
get in action 'on-away 
get in action 'on-over
][
unless get in feel 'over[
feel: make feel[
over: make function![face into pos][
either into[face/action/on-over face][face/action/on-away face]
]
]
]
]
]
last-widget: last view-face/pane 
if attribute-keycode[
insert tail view-face/keycodes reduce[attribute-keycode last-widget]
]
last-widget/init 
last-widget/init: none 
unless left-to-right?[
last-widget/offset/x: last-widget/offset/x - last-widget/size/x
]
xy: last-widget/offset 
max-height: max max-height xy/y + last-widget/size/y 
if left-to-right?[
xy/x: xy/x + last-widget/size/x 
max-width: max max-width xy/x
]
after-count: either after-count < after-limit[
xy/x: xy/x + either left-to-right?[gap-size/x][negate gap-size/x]
after-count + 1
][
xy: as-pair margin-size/x + indent-width max-height + gap-size/y 
after-count: 1
]
if :word[set :word last-widget]
word: 
widget: 
action-alt-click: 
action-away: 
action-click: 
action-dbl-click: 
action-edit: 
action-focus: 
action-key: 
action-over: 
action-resize: 
action-scroll: 
action-unfocus: 
attribute-size: 
attribute-span: 
attribute-text: 
attribute-text-color: 
attribute-text-style: 
attribute-color: 
attribute-image: 
attribute-effect: 
attribute-data: 
attribute-tip: 
attribute-edge: 
attribute-font: 
attribute-para: 
attribute-feel: 
attribute-rate: 
attribute-show?: 
attribute-options: 
attribute-keycode: none
]
]
parse reduce/only spec words[
any[
opt[here: set arg paren! (here/1: do arg) :here][
'return (
append-widget 
xy: as-pair margin-size/x + indent-width max-height + gap-size/y 
left-to-right?: true 
after-limit: 10000
) 
| 'reverse (
append-widget 
xy: as-pair max-width max-height + gap-size/y 
left-to-right?: false 
after-limit: 10000
) 
| 'after set arg integer! (
if widget[
append-widget 
xy: as-pair margin-size/x + indent-width max-height + gap-size/y
]
after-count: 1 
after-limit: arg
) 
| 'button-size[set arg integer! | set arg pair! | | set arg none!](button-size: arg) 
| 'field-size[set arg integer! | set arg pair! | | set arg none!](field-size: arg) 
| 'label-size[set arg integer! | set arg pair! | | set arg none!](label-size: arg) 
| 'text-size[set arg integer! | set arg pair! | | set arg none!](text-size: arg) 
| 'pad[set arg integer! | set arg paren!](
append-widget 
all[paren? arg arg: do arg]
arg: either left-to-right?[arg * sizes/cell][negate arg * sizes/cell]
either after-count = 1[xy/y: xy/y + arg][xy/x: xy/x + arg]
) 
| 'do set arg block! (view-face/init: make function![face /local var]arg) 
| 'margin set arg pair! (append-widget margin-size: xy: arg * sizes/cell) 
| 'indent set arg integer! (
append-widget 
indent-width: arg * sizes/cell 
xy/x: margin-size/x + indent-width
) 
| 'space set arg pair! (append-widget gap-size: arg * sizes/cell) 
| 'tight (append-widget margin-size: xy: gap-size: 0x0) 
| 'at set arg pair! (append-widget xy: arg * sizes/cell + margin-size after-limit: 10000) 
| 'effect[set arg word! | set arg block!](attribute-effect: arg) 
| 'options set arg block! (attribute-options: arg) 
| 'data set arg any-type! (attribute-data: either paren? arg[do arg][arg]) 
| 'edge set arg block! (attribute-edge: arg) 
| 'font set arg block! (attribute-font: arg) 
| 'para set arg block! (attribute-para: arg) 
| 'feel set arg block! (attribute-feel: arg) 
| 'on set arg block! (
action-click: any[action-click select arg 'click]
action-alt-click: any[action-alt-click select arg 'alt-click]
action-dbl-click: any[action-dbl-click select arg 'dbl-click]
action-away: select arg 'away 
action-edit: select arg 'edit 
action-focus: select arg 'focus 
action-key: select arg 'key 
action-over: select arg 'over 
action-resize: select arg 'resize 
action-scroll: select arg 'scroll 
action-unfocus: select arg 'unfocus
) 
| 'on-alt-click set arg block! (action-alt-click: arg) 
| 'on-away set arg block! (action-away: arg) 
| 'on-click set arg block! (action-click: arg) 
| 'on-dbl-click set arg block! (action-dbl-click: arg) 
| 'on-edit set arg block! (action-edit: arg) 
| 'on-focus set arg block! (action-focus: arg) 
| 'on-key set arg block! (action-key: arg) 
| 'on-over set arg block! (action-over: arg) 
| 'on-resize set arg block! (action-resize: arg) 
| 'on-scroll set arg block! (action-scroll: arg) 
| 'on-unfocus set arg block! (action-unfocus: arg) 
| 'rate[set arg integer! | set arg time!](attribute-rate: arg) 
| 'tip set arg string! (attribute-tip: arg) 
| 'text-color set arg tuple! (attribute-text-color: arg) 
| 'bold (attribute-text-style: 'bold) 
| 'italic (attribute-text-style: 'italic) 
| 'underline (attribute-text-style: 'underline) 
|[set arg integer! | set arg pair!](attribute-size: arg) 
| set arg issue! (attribute-span: sort arg) 
| set arg string! (attribute-text: arg) 
|[set arg tuple! | set arg none!](attribute-color: arg) 
| set arg image! (attribute-image: arg) 
| set arg file! (attribute-image: load arg) 
| set arg url! (attribute-data: arg) 
| set arg block! (
case[
none? action-click[action-click: arg]
none? action-alt-click[action-alt-click: arg]
none? action-dbl-click[action-dbl-click: arg]
]
) 
| set arg logic! (attribute-show?: arg) 
| set arg char! (attribute-keycode: arg) 
| set arg set-word! (append-widget word: :arg) 
| set arg word! (append-widget widget: arg)
]
]
]
append-widget 
view-face/init view-face 
view-face/init: none 
view-face/size: margin-size + as-pair max-width max-height 
unless only[
foreach face view-face/pane[span-size face view-face/size margin-size]
all[
zero? view-face/offset 
view-face/offset: max 0x0 view*/screen-face/size - view-face/size / 2
]
]
view-face
]
requestors: make object![
color-spec: copy[text-size 15 margin 2x2 space 1x1]
do make function![/local bx r g b i][
bx: 4 + length? locale*/colors 
r: bx - 1 
g: bx + 2 
b: bx + 4 
i: 1 
foreach color locale*/colors[
insert tail color-spec compose/deep[
box 5x5 (color)[face/parent-face/pane/(bx)/action/on-click face]edge[]feel[
over: make function![face act pos /local p][
all[
act 
p: face/parent-face/pane 
p/(bx)/color: face/color 
p/(r)/text: form face/color/1 
p/(g)/text: form face/color/2 
p/(b)/text: form face/color/3 
set-title face/parent-face (uppercase/part form color 1)
]
]
]
]
all[zero? i // 8 insert tail color-spec 'return]
i: i + 1
]
all['return <> last color-spec insert tail color-spec 'return]
]
read-dir: make function![path /local blk dirs][
blk: copy[]
if dirs: attempt[read path][
foreach dir remove-each file sort dirs[any[#"/" <> last file #"." = first file]][
insert tail blk head remove back tail dir 
insert/only tail blk read-dir dirize path/:dir 
if empty? last blk[remove back tail blk]
]
]
blk
]
alert: make function![
"Prompts to acknowledge a message." 
message[string!]"Message text" 
/title text[string!]"Title text"
][
display/dialog any[text "Alert"][
text 60x-1 message 
return 
bar 
reverse 
button "OK"[hide-popup]
do[set-focus last face/pane]
]
]
question: make function![
"Requests a Yes/No answer to a question." 
message[string!]"Message text" 
/title text[string!]"Title text" 
/local result
][
result: none 
display/dialog any[text "Question"][
text 50x-1 message 
return 
bar 
reverse 
button #"N" "No"[result: false hide-popup]
button #"Y" "Yes"[result: true hide-popup]
do[set-focus last face/pane]
]
result
]
request-char: make function![
"Requests a character." 
/title text[string!]"Title text" 
/font name[string!]"Font to use" 
/local result char-spec size
][
result: none 
char-spec: copy[text-size 7x7 tight]
name: any[name either effects/webdings["webdings"][effects/font]]
size: to integer! sizes/font * 1.5 
repeat i 256[
if i > 32[
insert tail char-spec compose/deep[
text (colors/page) (form to char! i - 1) font[name: (name) size: (size) align: 'center][result: to char! face/text hide-popup]on[
over[select-face face]
away[deselect-face face]
]
]
if zero? remainder i 16[insert tail char-spec 'return]
]
]
display/dialog any[text "Character Map"]char-spec 
result
]
request-color: make function![
"Requests a color." 
/title text[string!]"Title text" 
/color clr[tuple!]"Default color" 
/allow-none "Allow none as a value" 
/local result bx btn
][
clr: any[clr colors/text]
result: false 
display/dialog any[text "Color Palette"]compose/deep[
(color-spec) 
return bar return 
text "Red" spinner 15 data (clr/1) options[0 255 1][bx/color/1: face/data show bx]
bx: box 5x5 #L clr edge[][result: bx/color hide-popup]
return 
text "Green" spinner 15 data (clr/2) options[0 255 1][bx/color/2: face/data show bx]
return 
text "Blue" spinner 15 data (clr/3) options[0 255 1][bx/color/3: face/data show bx]
return 
bar 
reverse 
button "OK"[result: bx/color hide-popup]
btn: button "None" false[result: none hide-popup]
do[
all[allow-none btn/show?: true]
bx/size/y: sizes/cell * 17
]
]
result
]
request-date: make function![
"Requests a date." 
/title text[string!]"Title text" 
/date dt[date!]"Initial date to show (default is today)" 
/local result
][
result: none 
display/dialog any[text "Calender"][
tight 
calendar data (any[dt now/date])[result: face/data hide-popup]
]
result
]
request-dir: make function![
"Requests a directory." 
/title text[string!]"Title text" 
/path dir[file!]"Set starting directory" 
/expand "Start with all nodes expanded" 
/local result txt opts
][
if any[none? dir not exists? dir][dir: clean-path %.]
dir: dirize dir 
opts: either expand[[resize expand]][[resize]]
result: none 
display/dialog any[text "Select a Directory:"][
after 1 
txt: text 100 (form to-local-file dir) 
scroll-panel #HW 100x50 data[
tree 100x50 options opts data (read-dir dir)[
var: dir 
foreach item face/data[var: rejoin[var item #"/"]]
set-text txt to-local-file var
]
]
bar #WY 
reverse 
button #XY "Open"[result: dirize to-rebol-file txt/text hide-popup]
]
result
]
request-file: make function![
{Requests a file using a popup list of files and directories.} 
/title text[string!]"Title text" 
/file path[file! block!]"Default file name or block of file names" 
/filter name[string!]mask[string!]
/only "Return only a single file, not a block" 
/save "Request file for saving, otherwise loading" 
/local result blk
][
text: any[text either save["Save"]["Open"]]
if file[
set[path file]split-path clean-path path
]
if any[none? path not exists? path][path: clean-path %.]
file: either any[none? file not exists? path/:file][copy[]][compose[(file)]]
if local-request-file result: reduce[
any[select locale*/words text text]
"" 
path 
file 
compose[(any[select locale*/words name name select locale*/words "All" "All"])]
compose/deep[[(any[mask "*"])]]
logic? only 
logic? save
][
either only[join result/3 first result/4][
blk: copy[]
foreach file result/4[insert tail blk join result/3 file]
blk
]
]
]
request-font: make function![
"Requests a font name, returning a string." 
/title text[string!]"Title text" 
/style "Adds a style selector (returns font! object!)" 
/size "Adds a size selector (returns font! object!)" 
/align "Adds an alignment selector (returns font! object!)" 
/local result f blk
][
result: none 
blk: copy[
group-box "Font" data[
margin 2x2 
text-list (as-pair 50 30 + sizes/gap) data effects/fonts[f/font/name: f/text: copy face/selected show f]
]
]
all[
style 
insert tail blk[
group-box 30 "Style" data[
margin 2x2 
radio-group data[1 "Normal" "Bold" "Italic" "Underline"][
f/font/style: pick reduce[none 'bold 'italic 'underline]face/picked 
show f
]
]
]
]
if size[
all[style insert tail blk reduce['at as-pair 54 + sizes/gap 25 + sizes/gap]]
insert tail blk[
group-box 30 "Size" data[
margin 2x2 
spinner #L options[8 36 2]data 24[f/font/size: face/data show f]
]
]
all[style align insert tail blk reduce['at as-pair 86 + sizes/gap 0]]
]
all[
align 
insert tail blk[
group-box 30 "Align" data[
margin 2x2 
radio-group data[2 "left" "center" "right"][
f/font/align: to word! face/selected 
show f
]
return 
radio-group data[2 "top" "middle" "bottom"][
f/font/valign: to word! face/selected 
show f
]
]
]
]
insert tail blk[
return 
f: field #L effects/font 20x20 edge[size: 0x0]font[size: 24 align: 'center]
return 
bar 
reverse 
button "Cancel"[hide-popup]
button "OK"[result: either any[style size align][f/font][f/font/name]hide-popup]
]
display/dialog any[text "Available Fonts"]blk 
result
]
request-menu: make function![
"Requests a menu choice." 
face[object!]"Widget to appear in relation to" 
menu[block!]"Label/Action block pairs" 
/width x[integer!]"Width in pixels (defaults to 25 units)" 
/offset xy[pair!]"Offset relative to widget (defaults to top right)" 
/local result
][
result: none 
do select menu result: widgets/choose face any[x 25 * sizes/cell]any[xy face/offset + as-pair face/size/x 0]extract menu 2 
result
]
request-password: make function![
"Requests a username and password." 
/title text[string!]"Title text" 
/user username[string!]"Default username" 
/pass password[string!]"Default password" 
/check rules[block!]{Rules to test password against (fails if string returned)} 
/only "Password only" 
/verify "Verify password" 
/local result s blk u p v
][
blk: copy[text-size 20]
all[check rules: make function![text[string!]]rules]
all[not only insert tail blk compose[text "Username:" u: field (any[username ""]) return]]
insert tail blk compose[text "Password:" p: password (any[password ""]) return]
all[verify insert tail blk[text "Verify:" v: password return]]
result: none 
display/dialog any[text "Password"]compose[
(blk) 
bar 
reverse 
button "OK"[
case[
all[not only empty? u/text][
alert "Username must be provided." 
set-focus u
]
all[check string? s: rules p/text][
alert s 
set-focus p
]
all[verify p/text <> v/text][
alert "Please try again." 
set-focus v
]
true[
result: either only[copy p/text][reduce[u/text p/text]]
hide-popup
]
]
]
]
result
]
request-progress: make function![
"Requests a progress dialog for an action block." 
steps[integer!]"Number of iterations" 
block[block!]"Action block" 
/title text[string!]"Title text" 
/local step s p
][
s: 1 / steps 
step: make function![][p/data: p/data + s show p]
display/parent any[text "Loading ..."][
after 1 
label (any[text "Loading ..."]) 
p: progress 
do[face/options:[no-title]]
]
do bind block 'step 
unview
]
request-spellcheck: make function![
"Requests spellcheck on a widget's text." 
face[object!]
/title text[string!]"Title text" 
/anagram "Anagram option" 
/local ignore new next-word word start end txt fld lst a
][
if any[not string? face/text empty? face/text][exit]
ignore: copy[]
new: copy[]
unless exists? %dictionary[make-dir %dictionary]
unless locale*/dict[locale*/dict: make hash! 1000]
next-word: make function![/init][
while[any[init start <> end]][
either init[
start: end: head face/text 
unless find edit/letter first start[
while[all[not tail? start: next start find edit/other first start]][]
]
init: false
][
start: end 
while[all[not tail? start: next start find edit/other first start]][]
]
end: start 
while[all[not tail? end: next end find edit/letter first end]][]
word: copy/part start end 
unless any[
empty? word 
find ignore word 
find new word 
find locale*/dict word
][break]
word: none
]
if all[none? init word][
txt/text: fld/text: word 
show[txt fld]
insert clear lst/data edit/lookup-word word lst/redraw 
view*/focal-face: face 
view*/caret: none 
edit/hilight-text start end 
show face
]
string? word
]
if next-word/init[
view*/caret: none 
edit/hilight-text start end 
show face 
display/dialog any[text rejoin["Spellcheck (" locale*/language ")"]][
label-size 25 
after 2 
label "Original" txt: text 75 word 
label "Word" fld: field 75 word 
label "Suggestions" lst: text-list data (edit/lookup-word word) 75x50[set-text fld face/selected]
bar 
reverse 
button "Close"[
hide-popup
]
button "Add"[
insert tail new fld/text 
unless next-word[hide-popup]
]
button "Replace"[
change/part start fld/text end 
end: skip start length? fld/text 
unless next-word[hide-popup]
]
button "Ignore"[
insert tail ignore word 
unless next-word[hide-popup]
]
a: button "Anagram" false[
either 2 < var: length? fld/text[
face/data: lowercase sort copy fld/text 
clear lst/data 
foreach word locale*/dict[
all[var = length? word face/data = sort copy word insert tail lst/data word]
]
lst/redraw
][alert "Requires a word with at least 3 characters."]
]
do[all[anagram a/show?: true]]
]
set-focus face 
unless empty? new[
insert tail locale*/dict new 
write locale*/dictionary form locale*/dict
]
]
]
request-ui: make function![
"Requests UI changes." 
/title text[string!]"Title text" 
/file name[file!]"Set file to save changes (default is ui.dat)" 
/local result c1 c2 c3 c4 c5 c6 c7 c8 s1 s2 s3 s4 s5 s6 b1 b2 b3 b4 b5 b6 e1 e2 e3 e4 e5 e6 e7 e8
][
result: none 
display/dialog any[text "User Interface"][
tab-panel data[
"Colors"[
group-box "General" data[
text-size 15 
after 2 
text "Page" c1: box 10x5 edge[color: colors/text]colors/page[all[var: request-color/color face/color set-color face var]]
text "Text" c2: box 10x5 edge[color: colors/text]colors/text[all[var: request-color/color face/color set-color face var]]
]
return 
group-box "Theme" data[
text-size 15 
after 2 
text "Light" c3: box 10x5 edge[color: colors/text]colors/theme-light[all[var: request-color/color face/color set-color face var]]
text "Dark" c4: box 10x5 edge[color: colors/text]colors/theme-dark[all[var: request-color/color face/color set-color face var]]
drop-list #L data["Butter" "Orange" "Chocolate" "Chameleon" "Sky Blue" "Plum" "Scarlet Red"][
set-color c3 pick[252.233.79 252.175.62 233.185.110 138.226.52 114.159.207 173.127.168 239.41.41]face/picked 
set-color c4 pick[196.160.0 206.92.0 143.89.2 78.154.6 32.74.135 92.53.102 164.0.0]face/picked
]
]
group-box "State" data[
text-size 15 
after 2 
text "Light" c5: box 10x5 edge[color: colors/text]colors/state-light[all[var: request-color/color face/color set-color face var]]
text "Dark" c6: box 10x5 edge[color: colors/text]colors/state-dark[all[var: request-color/color face/color set-color face var]]
drop-list #L data["Butter" "Orange" "Chocolate" "Chameleon" "Sky Blue" "Plum" "Scarlet Red"][
set-color c5 pick[252.233.79 252.175.62 233.185.110 138.226.52 114.159.207 173.127.168 239.41.41]face/picked 
set-color c6 pick[196.160.0 206.92.0 143.89.2 78.154.6 32.74.135 92.53.102 164.0.0]face/picked
]
]
group-box "Outline" data[
text-size 15 
after 2 
text "Light" c7: box 10x5 edge[color: colors/text]colors/outline-light[all[var: request-color/color face/color set-color face var]]
text "Dark" c8: box 10x5 edge[color: colors/text]colors/outline-dark[all[var: request-color/color face/color set-color face var]]
]
]
"Sizes"[
group-box "Pixels & Points" 60 data[
label-size 15 
after 3 
label "Cell" s1: drop-list 15 (form sizes/cell) data[3 4 5 6 7 8]text "pixels" 
label "Edge" s2: drop-list 15 (form sizes/edge) data[1 2 3]text "pixel(s)" 
label "Font" s3: drop-list 15 (form sizes/font) data[8 9 10 11 12 14 16 18 20 22 24]text "points"
]
return 
group-box "Cells" 60 data[
label-size 15 
after 3 
label "Gap" s4: drop-list 15 (form sizes/gap) data[1 2 3 4]text "cell(s)" 
label "Margin" s5: drop-list 15 (form sizes/margin) data[2 4 6 8]text "cells" 
label "Slider" s6: drop-list 15 (form sizes/slider / sizes/cell) data[2 3 4]text "cells"
]
]
"Behaviors"[
after 1 
group-box "Action" #L data[
label-size 20 
after 2 
label "On enter" b1: field #L (form behaviors/action-on-enter) 
label "On tab" b2: field #L (form behaviors/action-on-tab)
]
group-box "Focus" #L data[
label-size 20 
after 2 
label "Caret" b3: field #L (form behaviors/caret-on-focus) 
label "Hilight" b4: field #L (form behaviors/hilight-on-focus)
]
group-box "Tabbing" #L data[
label-size 20 
after 2 
label "Cyclic" b5: field #L (form behaviors/cyclic) 
label "Tabbable" b6: field #L (form behaviors/tabbed)
]
]
"Effects"[
after 1 
group-box "Window effect(s)" #L data[
e1: field #L (either effects/window[mold/only effects/window][copy ""])
]
group-box "General" #L data[
label-size 20 
label "Font" e2: button 50x5 #L effects/font[all[var: request-font set-text face var]]
return 
label "Fonts" e3: field #L (mold/only effects/fonts) 
return 
label "Radius" e4: spinner 25 options[0 15 1](form effects/radius) text "pixel(s)" 
return 
label "Arrows" e5: radio-group 25x5 data[pick[2 1]effects/arrows-together "Win" "Mac"]
label "Symbols" e6: radio-group 25x5 data[pick[1 2]effects/webdings "On" "Off"]
]
group-box "Delay (in seconds)" #L data[
label-size 20 
label "Splash" e7: spinner 25 (form effects/splash-delay) 
label "Tooltip" e8: spinner 25 options[0 10 1](either none? effects/tooltip-delay["0"][form to integer! effects/tooltip-delay])
]
]
]
reverse 
button "Cancel"[result: none hide-popup]
button "Reset"[
either exists? %ui.dat[
if question {This action will delete your preferences and exit the application, do you wish to proceed?}[
either none? attempt[delete %ui.dat][
alert "Could not delete %ui.dat. File read-only?"
][quit]
]
][result: none hide-popup]
]
button "Save"[
colors/page: c1/color 
colors/text: c2/color 
colors/theme-light: c3/color 
colors/theme-dark: c4/color 
colors/state-light: c5/color 
colors/state-dark: c6/color 
colors/outline-light: c7/color 
colors/outline-dark: c8/color 
sizes/cell: to integer! s1/text 
sizes/edge: to integer! s2/text 
sizes/font: to integer! s3/text 
sizes/gap: to integer! s4/text 
sizes/margin: to integer! s5/text 
sizes/slider: sizes/cell * to integer! s6/text 
sizes/line: sizes/cell * 5 
behaviors/action-on-enter: load/all b1/text 
behaviors/action-on-tab: load/all b2/text 
behaviors/caret-on-focus: load/all b3/text 
behaviors/hilight-on-focus: load/all b4/text 
behaviors/cyclic: load/all b5/text 
behaviors/tabbed: load/all b6/text 
effects/window: either empty? e1/text[none][load/all e1/text]
effects/font: form e2/text 
effects/fonts: load/all e3/text 
effects/radius: e4/data 
effects/arrows-together: either e5/selected = "Mac"[true][false]
effects/webdings: either e6/selected = "On"[true][false]
effects/splash-delay: e7/data 
effects/tooltip-delay: either zero? e8/data[none][to time! e8/data]
widgets/rebind 
save any[name %ui.dat]reduce[colors sizes behaviors effects]
result: true 
hide-popup
]
]
result
]
request-value: make function![
"Requests a value." 
prompt[string!]"Prompt text" 
/title text[string!]"Title text" 
/default value[any-type!]"Default value" 
/type datatype[datatype!]"Return type" 
/local result f b
][
value: form any[value ""]
result: none 
display/dialog any[text "Ask"][
text prompt 
f: field value[b/action/on-click b]
return 
bar 
reverse 
button "Cancel"[hide-popup]
b: button "OK"[
either type[
var: attempt[to datatype f/text]
either var[
result: var 
hide-popup
][alert reform[f/text "is not a valid" join datatype "!"]]
][
result: f/text 
hide-popup
]
]
do[set-focus f]
]
result
]
splash: make function![
{Displays a centered splash screen for one or more seconds.} 
spec[block! file! image!]"The face spec or image to display"
][
spec: either block? spec[make subface spec][
make subface[
image: either file? spec[load spec][spec]
size: image/size
]
]
spec/type: 'splash 
spec/offset: max 0x0 view*/screen-face/size - spec/size / 2 
spec/color: any[spec/color colors/page]
view/new/options spec 'no-title 
wait effects/splash-delay
]
]
foreach word find first requestors 'alert[
either word = 'request-file[
all[
find[2 3]fourth system/version 
value? 'local-request-file 
set to word! word get in requestors word
]
][
set to word! word get in requestors word
]
]
functions: make object![
append-widget: make function![
"Append a custom widget to widgets context." 
spec[block!]"Widget spec" 
/local word
][
all[
find words word: to word! first spec 
gui-error reform[word "is already in use"]
]
widgets: make widgets spec 
all[
find words third spec 
widgets/:word/type: third spec
]
insert tail words word
]
clear-text: make function![
{Clear text attribute of a widget or block of widgets.} 
face[object! block!]
/no-show "Don't show" 
/focus
][
foreach f reduce either object? face[[face]][face][
if string? f/text[
clear f/text 
all[f/type = 'area f/para/scroll: 0x0 f/pane/data: 0]
f/line-list: none
]
]
unless no-show[
either all[focus object? face][set-focus face][show face]
]
]
display: make function![
{Displays widgets in a centered window with a title.} 
title[string!]"Window title" 
spec[block!]"Block of widgets, attributes and keywords" 
/dialog {Displays widgets in a modal popup window with /parent option} 
/maximize "Maximize window" 
/parent "Force parent to be last window (default is first)" 
/position "Use an alternative positioning scheme" 
offset[pair! word! block!]{Offset pair or one or more of 'left 'right 'top 'bottom 'first 'second} 
/min-size "Specify a minimum OS window resize size" 
size[pair!]{Minimum display size (including window border/title)} 
/close "Handle window close event" 
closer[block!]"The close handler block" 
/local tooltip-time tooltip
][
foreach window view*/screen-face/pane[all[title = window/text exit]]
spec: layout spec 
spec/text: title 
if position[
either pair? offset[
spec/offset: max 0x0 offset
][
foreach word compose[(offset)][
if word = 'first[word: either view*/screen-face/size/x > view*/screen-face/size/y['left]['top]]
if word = 'second[word: either view*/screen-face/size/x > view*/screen-face/size/y['right]['bottom]]
do select[
left[spec/offset/x: max 0 view*/screen-face/size/x / 2 - spec/size/x / 2]
right[spec/offset/x: max 0 view*/screen-face/size/x / 2 - spec/size/x / 2 + (view*/screen-face/size/x / 2)]
top[spec/offset/y: max 0 view*/screen-face/size/y / 2 - spec/size/y / 2]
bottom[spec/offset/y: max 0 view*/screen-face/size/y / 2 - spec/size/y / 2 + (view*/screen-face/size/y / 2)]
]word
]
]
]
unless empty? view*/screen-face/pane[
either view*/screen-face/pane/1/type <> 'splash[
insert tail spec/options reduce['parent either any[dialog parent][last view*/screen-face/pane][first view*/screen-face/pane]]
][unview]
]
either any[min-size maximize][
insert tail spec/options 'resize 
all[maximize spec/changes:[maximize]]
][
foreach sub-face spec/pane[
all[
sub-face/span 
not empty? intersect sub-face/span #HWXY 
insert tail spec/options 'resize 
break
]
]
]
all[
find spec/options 'resize 
insert tail spec/options reduce['min-size either min-size[size][spec/size + view*/title-size + view*/resize-border]]
]
either dialog[
spec/type: 'popup 
spec/feel: system/words/face/feel 
show-popup spec
][view/new spec]
all[close spec/action: make function![face /local var]closer]
spec/feel: make any[spec/feel widgets/default-feel][
orig-size: spec/size 
mouse-offset: 0x0 
if all[not dialog effects/tooltip-delay][
tooltip-time: now/time/precise 
insert tail spec/pane tooltip: make widgets/tooltip[type: 'tooltip offset: -10000x-10000 tip: none]
]
detect: make function![face event /local f][
if none? tooltip[
f: last face/pane 
if f/type = 'tooltip[
tooltip-time: now/time/precise 
tooltip: last face/pane
]
]
if all[
face/type <> 'popup 
effects/tooltip-delay 
tooltip/data 
event/type <> 'time 
mouse-offset <> event/offset
][
tooltip-time: now/time/precise 
tooltip/data: false 
tooltip/offset: -10000x-10000 
show tooltip
]
if all[
face/type <> 'popup 
effects/tooltip-delay 
not tooltip/data 
(now/time/precise - tooltip-time) > effects/tooltip-delay
][
f: event/face 
while[f: find-face event/offset f][
if all[f/type <> 'face f/tip][
tooltip/text: f/tip 
tooltip/init 
tooltip/size: 10000x10000 
tooltip/size: 8 + size-text tooltip 
poke tooltip/effect/draw 9 tooltip/size - 1x1 
tooltip/offset: min event/face/size - tooltip/size - 2 max 2x2 event/offset - as-pair 0 tooltip/size/y 
tooltip/data: true 
if all[
tooltip/parent-face 
block? tooltip/parent-face/pane
][
remove find tooltip/parent-face/pane tooltip
]
insert tail event/face/pane tooltip 
show tooltip 
break
]
if function? get in f 'pane[break]
unless f: f/pane[break]
]
]
if find[down up alt-down alt-up]event/type[
if all[
view*/focal-face 
not within? event/offset win-offset? view*/focal-face view*/focal-face/size
][unless edit/unfocus[exit]]
]
do select[
key[
case[
event/key = #"^-"[
if all[view*/focal-face viewed? view*/focal-face][
f: either event/shift[edit/back-field view*/focal-face][edit/next-field view*/focal-face]
if find behaviors/action-on-tab view*/focal-face/type[
view*/focal-face/action/on-click view*/focal-face
]
if :f[set-focus f]
exit
]
]
find[#" " #"^M"]event/key[
if all[view*/focal-face view*/focal-face/type = 'button][
view*/focal-face/action/on-click view*/focal-face 
exit
]
]
all[
find[f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12]event/key 
get in on-fkey event/key
][
on-fkey/(event/key) face event 
exit
]
any[not view*/focal-face view*/focal-face/type = 'button][
either f: select face/keycodes event/key[
f/action/on-click f exit
][
if event/key = #"^["[
if find view*/pop-list view*/pop-face[hide-popup exit]
if all[view*/pop-face view*/pop-face/type = 'choose][hide-popup exit]
all[get in face 'action not face/action face exit]
if all[face = pick view*/screen-face/pane 1 1 <> length? view*/screen-face/pane][
either question "Do you really want to quit this application?"[quit][exit]
]
unview/only face 
exit
]
]
]
]
]
move[mouse-offset: event/offset]
resize[
all[face/size <> orig-size span-resize face face/size - orig-size]
show face 
orig-size: face/size 
exit
]
close[
if view*/focal-face[
view*/focal-face: view*/caret: none 
edit/unlight-text
]
all[get in face 'action not face/action face exit]
if all[face = pick view*/screen-face/pane 1 1 <> length? view*/screen-face/pane][
either question "Do you really want to quit this application?"[quit][exit]
]
]
]event/type 
event
]
]
either dialog[do-events][show spec spec]
]
examine: make function![
"Prints information about widgets and attributes." 
'widget 
/indent "Indent output as an MD2 ready string" 
/no-print "Do not print output to console" 
/local string tmp blk funcs
][
unless word? widget[widget: to word! widget]
unless find tmp: next find first widgets 'choose widget[
print "Unknown widget. Supported widgets are:^/" 
foreach widget tmp[print join "^-" widget]
exit
]
widget: widgets/:widget 
string: replace/all copy widget/tip "^/" "^/^-" 
replace/all string "[" join " " "[" 
replace/all string "]" join "]" " " 
replace/all string "^- " "^-" 
replace/all string " ^/" "^/" 
replace string "^-DESCRIPTION:" "^/DESCRIPTION:" 
replace string "^-OPTIONS:" "^/OPTIONS:" 
insert tail string {

ATTRIBUTES:} 
foreach attribute skip first rebface 3[
if all[
not find[show? face-flags feel action tip]attribute 
get tmp: in widget attribute
][
tmp: either find["function" "object" "block" "bitset"]form type? get tmp[join type? get tmp "!"][mold get tmp]
insert tail string rejoin[
"^/^-" 
head insert/dup tail form attribute " " 16 - length? form attribute 
tmp
]
]
]
unless widget/feel = widgets/default-feel[
insert tail string "^/^/PREDEFINED FEELS:" 
foreach attribute next first widgets/default-feel[
if get in widget/feel attribute[
insert tail string join "^/^-" attribute
]
]
]
unless widget/action = widgets/default-action[
insert tail string "^/^/PREDEFINED ACTIONS:" 
foreach attribute next first widgets/default-action[
if get in widget/action attribute[
insert tail string join "^/^-" attribute
]
]
]
funcs: copy[]
unless empty? blk: difference first rebface first widget[
insert tail string "^/^/EXTENDED ATTRIBUTES:" 
foreach attribute blk[
if tmp: in widget attribute[
either function? get tmp[
insert tail funcs attribute
][
tmp: either find["object" "block" "bitset"]form type? get tmp[join type? get tmp "!"][mold get tmp]
insert tail string rejoin["^/^-" head insert/dup tail form attribute " " 16 - length? form attribute tmp]
]
]
]
]
unless empty? funcs[
insert tail string "^/^/ACCESSOR FUNCTIONS:" 
foreach attribute funcs[
tmp: copy "" 
foreach w third get in widget attribute[
all[word? w insert tail tmp join " " w]
if refinement? w[
either w = /local[break][insert tail tmp join " /" w]
]
]
insert tail string rejoin["^/^-" uppercase form attribute tmp]
]
]
if indent[
replace/all string "^/" "^/^-" 
replace/all string "^-^/" "^/" 
insert string "^-"
]
if no-print[
replace/all string "^-" "    "
]
either any[indent no-print][string][print string]
]
get-values: make function![
{Gets values from input widgets within a display or grouping widget.} 
face[object!]"Display face" 
/type "Precede each value with its type" 
/local blk
][
all[
find[scroll-panel tab-panel]face/type 
face: either block? face/pane[face: face/pane/1][face/pane]
]
blk: copy[]
foreach widget face/pane[
if find[
area check check-group drop-list edit-list field group-box password radio-group scroll-panel slider tab-panel table text-list
]widget/type[
all[type insert tail blk widget/type]
insert/only tail blk case[
find[area drop-list edit-list field password]widget/type[widget/text]
find[check check-group slider]widget/type[widget/data]
find[radio-group table text-list]widget/type[widget/picked]
find[scroll-panel group-box tab-panel]widget/type[
either type[get-values/type widget][get-values widget]
]
]
]
]
blk
]
set-color: make function![
"Set and show a widget's color attribute." 
face[object!]
color[tuple! none!]
/no-show "Don't show"
][
face/color: color 
unless no-show[show face]
]
set-data: make function![
"Set and show a widget's data attribute." 
face[object!]
data[any-type!]
/no-show "Don't show"
][
face/data: either series? data[copy data][data]
unless no-show[show face]
]
set-focus: make function![
"Set and show widget focus." 
face[object!]
/caret
][
unless edit/unfocus[exit]
if face/show?[
if get in face/action 'on-focus[
unless face/action/on-focus face[return false]
]
view*/focal-face: face 
view*/caret: case[
all[caret in face 'caret face/caret][at face/text face/caret]
find behaviors/caret-on-focus face/type[either none? edit/caret[tail face/text][edit/caret]]
find behaviors/hilight-on-focus face/type[edit/hilight-all face face/text]
]
edit/caret: none 
all[in face 'esc face/esc: copy face/text]
either face/type = 'button[face/feel/over face true none][show face]
]
]
set-locale: make function![
"Dynamically set/change locale." 
language[string! none!]
/local dat-file
][
clear system/locale/words 
system/locale/dict: none 
all[
exists? dat-file: join what-dir either language[rejoin[%language/ language %.dat]][%locale.dat]
system/locale: construct/with load dat-file system/locale
]
all[
exists? system/locale/dictionary: rejoin[what-dir %dictionary/ system/locale/language %.dat]
system/locale/dict: make hash! parse read system/locale/dictionary " "
]
locale*: system/locale
]
set-state: make function![
"Toggle and show widget state." 
face[object!]
/info "Exit if already info." 
/edit "Exit if already edit." 
/local temp
][
all[info find face/options 'info exit]
all[edit not find face/options 'info exit]
either temp: find face/options 'info[remove temp][insert tail face/options 'info]
case[
find[area edit-list field]face/type[
face/color: either find face/options 'info[
face/action: make face/action[on-focus: make function![face][false]]
all[face/type = 'edit-list insert tail face/options 'no-click]
colors/outline-light
][
face/action: make face/action[on-focus: make function![face][true]]
all[face/type = 'edit-list remove find face/options 'no-click]
colors/page
]
]
face/type = 'button[
unless find face/options 'info[face/feel/over face false 0x0]
]
]
show face
]
set-text: make function![
"Set and show a widget's text attribute." 
face[object!]"Widget" 
text[any-type!]"Text" 
/caret "Insert at cursor position (tail if none)" 
/no-show "Don't show" 
/focus
][
unless string? face/text[exit]
either caret[
if all[
face = view*/focal-face 
view*/caret
][face/caret: index? view*/caret]
either face/caret[
insert at face/text face/caret form text 
view*/caret: at face/text face/caret + length? form text 
face/caret: index? view*/caret
][insert tail face/text form text]
][insert clear face/text form text]
all[
face/para 
face/para/scroll: 0x0 
all[face/type = 'area face/pane/data: 0]
]
face/line-list: none 
unless no-show[either focus[set-focus face][show face]]
]
set-text-color: make function![
"Set and show a widget's font color attribute." 
face[object!]
color[tuple! none!]
/no-show "Don't show"
][
unless string? face/text[exit]
all[
widgets/(face/type)/font 
face/font = widgets/(face/type)/font 
face/font: make face/font[]
]
face/font/color: color 
unless no-show[show face]
]
set-texts: make function![
"Set and show text attribute of a block of widgets." 
faces[block!]"Widgets" 
text[any-type!]"Text or block of text" 
/no-show "Don't show"
][
unless block? text[text: reduce[text]]
foreach face reduce faces[
set-text face first text 
unless 1 = length? text[text: next text]
]
text: head text 
unless no-show[show faces]
]
set-title: make function![
"Set and show window title." 
face[object!]"Window dialog face" 
title[string!]"Window bar title"
][
face/text: title 
face/changes: 'text 
show face
]
set-values: make function![
{Puts values into input widgets within a display or grouping widget.} 
face[object!]"Display face" 
blk[block!]"Block of values (or 'skip)" 
/no-show "Don't show" 
/local val
][
all[
find[scroll-panel tab-panel]face/type 
face: either block? face/pane[face: face/pane/1][face/pane]
]
foreach widget face/pane[
if find[
area check check-group drop-list edit-list field group-box password radio-group scroll-panel slider tab-panel table text-list
]widget/type[
unless 'skip = val: first blk[
switch/default widget/type[
check[widget/data: val]
check-group[all[block? val insert clear widget/data val]]
group-box[all[block? val set-values/no-show widget copy/deep val]]
radio-group[widget/select-item to integer! val]
scroll-panel[all[block? val set-values/no-show widget copy/deep val]]
slider[widget/data: to decimal! val]
tab-panel[all[block? val set-values/no-show widget copy/deep val]]
table[widget/select-row val]
text-list[widget/select-row val]
][
widget/line-list: none 
insert clear widget/text val 
all[widget/type = 'area widget/para widget/para/scroll: 0x0 widget/pane/data: 0]
]
]
if tail? blk[gui-error "set-values had insufficient values"]
blk: next blk
]
]
blk: head blk 
unless no-show[show face]
]
translate: make function![
{Dynamically translate a string or block of strings.} 
text "String (or block of strings) to translate" 
/local match
][
if all[series? text locale*/words][
text: copy/deep text 
all[
string? text 
match: select/skip locale*/words text 2 
insert clear text match
]
if block? text[
foreach word text[
all[
string? word 
match: select/skip locale*/words word 2 
insert clear word match
]
]
]
]
text
]
]
foreach word find first functions 'append-widget[
set to word! word get in functions word
]
remove-each font effects/fonts[not font? font]
set-locale none 
insert tail words next find first widgets 'choose
]
system/view/screen-face/feel: none 
open-events 
recycle
;**************END of REBGUI script******************
;****************************************************       

;Here starts supercalculator script:

    
;following lines are to obtain current file version
header-script: system/script/header
version: "Version: "
append version header-script/version
    

risultato2: " "
ultimo: 0


decimali: 0.01     
; We define a function to round the values to the specified digits
troncare: func [ misura2 ]
   [
   esatto: round/to misura2 decimali
   return esatto
   ]


valuta: func [frase][
    frase: to-string frase
    frase: trim/all frase  ;we avoid spaces
    
    ;let's check if want to reuse last result
    if (parse frase  [ ["+"|"-"|"*"|"/"|"^^" ] to end ])  [ insert frase ultimo]
    
    replace/all frase "("  " ((( " ;so we don't mix original parentheisis with the followings
    replace/all frase ")"  " ))) " ;so we don't mix original parentheisis with the followings
    replace/all frase  "abs-"   "  abs  " ;it's tricky but necessary
    replace/all frase  "abs+"   "  abs  "
    replace/all frase "exp-"   "  exp  negate "
    replace/all frase "log-"   "  log negate  "
    replace/all frase "ln-"   "  ln negate  "
    replace/all frase "sin-"   "  sin negate  " 
    replace/all frase "cos-"   "  cos negate  "
    replace/all frase "tangent-"   "  tangent  negate "
    replace/all frase "arcs-"   "  arcs negate  " ;bad change, but necessary
    replace/all frase "arcc-"   "  arcc negate  " ;bad change, but necessary
    replace/all frase "arct-"   "  arct negate  " ;bad change, but necessary
    replace/all frase "*"  " ) * ( "
    replace/all frase "/"   " ) / ( "
    replace/all frase "+"   " )) + (( "
    replace/all frase "-"   " )) - (( "
    replace/all frase "^^"   "  **  " ;bad change, but necessary
    replace/all frase "exp"   "  exp  "
    replace/all frase "log"   "  log-10  "
    replace/all frase "ln"   "  log-e  "
    replace/all frase "sqrt"   "  square-root  " ;bad change, but necessary
    replace/all frase  "abs"   "  abs  "
    replace/all frase "sin"   "  sine  " 
    replace/all frase "cos"   "  cosine  "
    replace/all frase "tangent"   "  tangent  "
    replace/all frase "arcs"   "  arcsine  " ;bad change, but necessary
    replace/all frase "arcc"   "  arccosine  " ;bad change, but necessary
    replace/all frase "arct"   "  arctangent  " ;bad change, but necessary
    replace/all frase "e )) - (( "   "e-" ;bad change, but necessary
    insert frase " (( "
    append frase " )) " 
    
    ;uncomment the following line to debug or to see what happen... 
    ;print frase
    
    risultato: do frase 
    ultimo: risultato ;the last result
    ;check if user wants to round result
    if y_chk/data = true [  risultato: troncare risultato ]
    
    ;print risultato
    ;restore the origina string
    replace/all frase    "  **  " "^^"
    replace/all frase   "  arcsine  "  "arcs" 
    replace/all frase    "  arccosine  " "arcc"
    replace/all frase   "  arctangent  " "arct" 
    replace/all frase    "  square-root  " "sqrt"
    replace/all frase    "  abs  "  "abs"
    replace/all frase    "  sine  "  "sin"
    replace/all frase   "  cosine  " "cos" 
    replace/all frase    "  log-10  " "log"
    replace/all frase    "  log-e  " "ln"
    
    replace/all frase    "  exp  negate " "exp-"
    replace/all frase    "  log negate  " "log-"
    replace/all frase    "  ln negate  "  "ln-"
    replace/all frase    "  sin negate  "  "sin-"
    replace/all frase    "  cos negate  " "cos-"
    replace/all frase    "  tangent  negate " "tangent-"
    replace/all frase   "  arcs negate  "   "arcs-" 
    replace/all frase    "  arcc negate  "  "arcc-"
    replace/all frase   "  arct negate  "  "arct-" 
    
    replace/all  frase " ) " "" ;remove al simple parenthesis
    replace/all  frase " ( " "" ;remove al simple parenthesis
    replace/all  frase " (( " "" ;remove al double parenthesis
    replace/all  frase " )) " "" ;remove al double parenthesis
    replace/all frase   " ((( "  "(" ;
    replace/all frase   " ))) "  ")"
    
    
    
    pretty_frase: trim/all frase
    ;riga is the separetor line
    riga: copy "-------"
    n_riga: length? pretty_frase
    for i 1 n_riga 1 [ append riga "-" ]
    
    risultato2: head risultato2
    
    risultato2: insert risultato2  (reform [ "^/" pretty_frase "^/" riga "^/= " risultato "^/"])
    risultato2: head risultato2
    return risultato2
    ]



solve_all: func [] [
    
    ]

display "Supercalculator" [

    text "History:"
    return
    a_field: area 130x50
    
    
    
    
    return
    text "Write expression:"
    b_field: field 100x5 [ 
        if  b_field/text = "" [ b_field/text: "0"]
        a_field/text: to-string (valuta b_field/text)
        ;b_field/text: copy []
        clear-text/focus b_field
        ;b_field/text: to-string b_field/text
        show [ a_field b_field]
        ]
    return 
    button   "1" [ append b_field/text "1"  show b_field]
    button   "2" [ append b_field/text "2"  show b_field]
    button   "3" [ append b_field/text "3"  show b_field]
    button   "+" [ append b_field/text "+"  show b_field]
    button   "-" [ append b_field/text "-"  show b_field]
    button "sin"   [ append b_field/text "sin"  show b_field]
    button "cos"  [ append b_field/text "cos"  show b_field]
    button "tan"  [ append b_field/text "tangent"  show b_field]
    return
    button   "4" [ append b_field/text "4"  show b_field]
    button   "5" [ append b_field/text "5"  show b_field]
    button   "6" [ append b_field/text "6"  show b_field]
    button   "*" [ append b_field/text "*"  show b_field]
    button   "/" [ append b_field/text "/"  show b_field]
    button "asin"  [ append b_field/text "arcs"  show b_field]
    button "acos"  [ append b_field/text "arcc"  show b_field]
    button "atan"  [ append b_field/text "arct"  show b_field]
    return
    button   "7" [ append b_field/text "7"  show b_field]
    button   "8" [ append b_field/text "8"  show b_field]
    button   "9" [ append b_field/text "9"  show b_field]
    button   "0" [ append b_field/text "0"  show b_field]
    button   green "=" [ 
        if  b_field/text = "" [ b_field/text: "0"]
        a_field/text: to-string (valuta b_field/text)
        b_field/text: copy []
        b_field/text: to-string b_field/text
        show [ a_field b_field]
        ]
    button  "log"  [ append b_field/text "log"  show b_field]   
    button  "ln" [ append b_field/text "ln"  show b_field]  
    button  "e^^"  [ append b_field/text " exp "  show b_field] 
    
    return
    button   "." [ append b_field/text "."  show b_field]
    button   " ^^ " [ append b_field/text "^^"  show b_field]
    button    "SQRT" [ append b_field/text "sqrt"  show b_field]
    button  "EE" [ append b_field/text "e"  show b_field]
    button   "(" [ append b_field/text "("  show b_field]
    button   ")" [ append b_field/text ")"  show b_field]
    button red  "CC" [ b_field/text: copy []   show b_field]
    button  "abs"   [ append b_field/text "abs"  show b_field]  
        
        
    return
    
    y_chk: check "Fixed decimal digits?" data false
    ;return
    text "Digits"
    ;cifredecimali: text "2"
    cifredecimali: spinner data  2 [decimali: 0.1 ** (  cifredecimali/data )]
    button blue "?" [ display "Help"  [ 
            heading "HELP"
            return
            text {Welcome to Supercalculator, a Scientific calculator written in Rebol.
You can use it on Windows, Liunx, Mac and whatever Rebol works!
You can write directly the formulas in the field an press ENTER or press =.
You can use parethesis to write correctly the formulas.
You can contact me for help: 
Massimiliano Vessi 
%maxint--tiscali--it}
            return
            text  version
            return
            image logo.gif
            ]
        ]
    return
    text version ;to visualize version               
     
    ]

do-events