-
Notifications
You must be signed in to change notification settings - Fork 0
/
cloudsheet.opa
76 lines (65 loc) · 2.44 KB
/
cloudsheet.opa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//import stdlib.core.xhtml
type celltype = {value:string}
type rowtype = {cells:intmap(celltype)}
type page = {rows:intmap(rowtype)}
type sheet = {pages:stringmap(page)}
type msgtype = {valueupdate} / {cursorfocus}
type message = {updatetype:msgtype row:int col:int newvalue:option(string)}
db /cloudsheet/sheets : stringmap(sheet)
clouds = Mutable.make([] : list((string,Network.network(message))))
select_cell(sheetname, row,col) = (
Network.broadcast({updatetype={cursorfocus} row=row col=col newvalue={none}}, getcloud(sheetname))
)
keyboard_navigate(evt:Dom.event, sheetname, from_row, from_col) = (
if evt.key_code == {some=Dom.Key.RIGHT} then
select_cell(sheetname, from_row, from_col+1)
else if evt.key_code == {some=Dom.Key.LEFT} then
select_cell(sheetname, from_row, from_col-1)
else if evt.key_code == {some=Dom.Key.UP} then
select_cell(sheetname, from_row-1, from_col)
else if evt.key_code == {some=Dom.Key.DOWN} || evt.key_code == {some=Dom.Key.RETURN} then
select_cell(sheetname, from_row+1, from_col)
//void
)
// This is a cloud sheet
//Show a cell
showcell(sheetname,row,col):xhtml = (
<td><input id="cell-R{row}C{col}" onkeydown={evt->keyboard_navigate(evt,sheetname,row,col)} type="text" value="{/cloudsheet/sheets[sheetname]/pages["default"]/rows[row]/cells[col]/value}"/></td>
)
//Show a hole row
showrow(sheetname,row) = (
<tr>
{
for({col=1 trow=<></>},
(~{col trow} -> {col=col+1 trow=<>{trow} {showcell(sheetname,row,col)}</>}),
(~{col ...} -> col <= 10)).trow
}
</tr>
)
execute_update(msg:message) = (
do println("Received cloud mesasge {Debug.dump(msg)}")
match msg
| {updatetype={cursorfocus} ~row ~col ...} -> Dom.give_focus(#{"cell-R{row}C{col}"})
//| {updatetype={valueupdate} newvalue={some=newval} ~row ~col ...}-> Dom.set_text(#{"cell-R{row}C{col}"},newval)
| any -> println("Error : bad message ? {Debug.dump(any)}")
)
getcloud(name) = (
match List.assoc(name,clouds.get())
| {none} ->
newcloud = Network.cloud(name) : Network.network(message)
do clouds.set((name, newcloud) +> clouds.get())
newcloud
| {some=thecloud} -> thecloud
)
//Show the spreadsheet
showsheet(sheetname)=(
<h1>{sheetname}</h1>
<table onready={_->Network.add_callback(execute_update,getcloud(sheetname))}>
{
for({row=1 table=<></>},
(~{row table} -> {row=row+1 table=<>{table} {showrow(sheetname,row)}</>}),
(~{row ...} -> row <= 10)).table
}
</table>
)
server = one_page_server("Hello", -> showsheet("somesheet"))