Mercurial > gui
comparison remotePager.ur @ 16:2e397d373289
Add RemotePager.
author | Karn Kallio <kkallio@eka> |
---|---|
date | Thu, 18 Aug 2011 12:53:17 -0430 |
parents | |
children | b5432d74841a |
comparison
equal
deleted
inserted
replaced
15:8300d5f0dc19 | 16:2e397d373289 |
---|---|
1 type formatCtl = {Width : int, | |
2 RangeCtl : $(mapU (transaction {} -> xbody) [First, Back, Next, Last]), | |
3 PageCtl : $(mapU (int -> transaction {} -> xbody) [Unsel, Sel]), | |
4 WrapPageCtl : xbody -> xbody, | |
5 Wrap : $(mapU xbody [First, Back, Pages, Next, Last]) -> xbody} | |
6 | |
7 style firstCtl | |
8 style backCtl | |
9 style nextCtl | |
10 style lastCtl | |
11 style curPage | |
12 style rangeCtl | |
13 | |
14 fun defaultFormatLbl {First = fLbl, Back = bLbl, Next = nLbl, Last = lLbl} = | |
15 let | |
16 fun mkLink c txt = fn a => <xml><li onclick={a} class={c}><a class={c} onclick={return ()}>{[txt]}</a></li></xml> | |
17 in | |
18 {Width = 5, | |
19 RangeCtl = {First = mkLink firstCtl fLbl, | |
20 Back = mkLink backCtl bLbl, | |
21 Next = mkLink nextCtl nLbl, | |
22 Last = mkLink lastCtl lLbl}, | |
23 PageCtl = {Unsel = fn n a => <xml><li onclick={a}><a onclick={return ()}>{[n + 1]}</a></li></xml>, | |
24 Sel = fn n a => <xml><li onclick={a} class={curPage}><a class={curPage} onclick={return ()}>{[n + 1]}</a></li></xml>}, | |
25 WrapPageCtl = fn x => x, | |
26 Wrap = fn {First = f, Back = b, Pages = p, Next = n, Last = l} => <xml><ul class={rangeCtl}>{f}{b}{p}{n}{l}</ul></xml>} | |
27 end | |
28 | |
29 val defaultFormat = defaultFormatLbl {First = "<<", Back = "<", Next = ">", Last = ">>"} | |
30 | |
31 type pageData = {Content : xbody, Available : int} | |
32 datatype response err = Good of pageData | Bad of err | |
33 | |
34 functor Make(M : sig | |
35 type errorMarker | |
36 type pageGroup | |
37 val initPage : pageGroup -> transaction pageData | |
38 val getPage : pageGroup -> int -> transaction (response errorMarker) | |
39 end) : sig | |
40 type t | |
41 val createFmt : formatCtl -> M.pageGroup -> transaction t | |
42 val create : M.pageGroup -> transaction t | |
43 val onError : t -> (M.errorMarker -> transaction {}) -> transaction {} | |
44 val panelXml : t -> xbody | |
45 val ctlXml : t -> xbody | |
46 end = struct | |
47 open M | |
48 | |
49 type t = {FormatCtl : formatCtl, | |
50 PageGroup : pageGroup, | |
51 OnError : source (errorMarker -> transaction {}), | |
52 CurrentPage : source int, | |
53 RangeStart : source int, | |
54 Available : source int, | |
55 Content : source xbody} | |
56 | |
57 fun max x y = if x > y then x else y | |
58 fun min x y = if x < y then x else y | |
59 | |
60 fun loadPage t pg = | |
61 ret <- rpc (getPage t.PageGroup pg); | |
62 | |
63 case ret of | |
64 Good pageData => | |
65 let | |
66 val lst = max 0 (pageData.Available - 1) | |
67 val rgtRange = max 0 (pageData.Available - t.FormatCtl.Width) | |
68 in | |
69 if pg > lst then | |
70 loadPage t lst | |
71 else | |
72 rg <- get t.RangeStart; | |
73 (if rg > rgtRange then | |
74 set t.RangeStart rgtRange | |
75 else | |
76 return ()); | |
77 set t.CurrentPage pg; | |
78 set t.Content pageData.Content; | |
79 set t.Available pageData.Available | |
80 end | |
81 | Bad e => | |
82 handler <- get t.OnError; | |
83 handler e | |
84 | |
85 fun createFmt fmt grp = | |
86 pg <- source 0; | |
87 rg <- source 0; | |
88 | |
89 pageData <- initPage grp; | |
90 | |
91 av <- source (pageData.Available); | |
92 c <- source (pageData.Content); | |
93 | |
94 e <- source (fn _ => return {}); | |
95 | |
96 return {FormatCtl = fmt, | |
97 PageGroup = grp, | |
98 OnError = e, | |
99 CurrentPage = pg, | |
100 RangeStart = rg, | |
101 Available = av, | |
102 Content = c} | |
103 | |
104 val create = createFmt defaultFormat | |
105 | |
106 fun onError t f = | |
107 set t.OnError f | |
108 | |
109 fun panelXml t = | |
110 <xml> | |
111 <dyn signal={signal t.Content}/> | |
112 </xml> | |
113 | |
114 fun ctlXml t = | |
115 let | |
116 val fmt = t.FormatCtl | |
117 val width = fmt.Width | |
118 | |
119 fun floor pg = | |
120 return (max 0 pg) | |
121 | |
122 fun lastPage () = | |
123 av <- get t.Available; | |
124 floor (av - 1) | |
125 | |
126 fun rightRange () = | |
127 lst <- lastPage (); | |
128 floor (lst - width + 1) | |
129 | |
130 fun ceil pg = | |
131 rgt <- rightRange (); | |
132 return (min rgt pg) | |
133 | |
134 fun setRange startPage = | |
135 startPage <- ceil startPage; | |
136 startPage <- floor startPage; | |
137 set t.RangeStart startPage | |
138 | |
139 fun printLinks start cur available = | |
140 let | |
141 val wanted = start + width - 1 | |
142 val have = max 0 (available - 1) | |
143 val lst = min wanted have | |
144 | |
145 fun printLinks' n (acc : xbody) = | |
146 if n > lst then | |
147 acc | |
148 else | |
149 printLinks' (n + 1) | |
150 <xml>{acc}{(if n = cur then | |
151 fmt.PageCtl.Sel | |
152 else | |
153 fmt.PageCtl.Unsel) n (loadPage t n)}</xml> | |
154 in | |
155 printLinks' start <xml/> | |
156 end | |
157 in | |
158 fmt.Wrap {First = fmt.RangeCtl.First (setRange 0), | |
159 Back = fmt.RangeCtl.Back (pg <- get t.RangeStart; setRange (pg - 1)), | |
160 Pages = fmt.WrapPageCtl | |
161 <xml> | |
162 <dyn signal={start <- signal t.RangeStart; | |
163 av <- signal t.Available; | |
164 cur <- signal t.CurrentPage; | |
165 return (printLinks start cur av)}/> | |
166 </xml>, | |
167 Next = fmt.RangeCtl.Next (pg <- get t.RangeStart; setRange (pg + 1)), | |
168 Last = fmt.RangeCtl.Last (pg <- rightRange (); setRange pg)} | |
169 end | |
170 end |