wee 0.1.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. data/INSTALL +7 -0
  2. data/README +268 -0
  3. data/Rakefile +26 -0
  4. data/TODO +116 -0
  5. data/benchmark/Centrino1300/result.2000.counter.action +45 -0
  6. data/benchmark/Centrino1300/result.2000.counter.render +43 -0
  7. data/benchmark/Centrino1300/result.2000.filehandler +43 -0
  8. data/benchmark/Centrino600/result.2000.counter.action +47 -0
  9. data/benchmark/Centrino600/result.2000.counter.render +45 -0
  10. data/benchmark/Centrino600/result.2000.filehandler +43 -0
  11. data/benchmark/Makefile +48 -0
  12. data/benchmark/bench.sh +24 -0
  13. data/benchmark/counter.rb +96 -0
  14. data/benchmark/filehandler.rb +6 -0
  15. data/doc/rdoc/classes/Array.html +172 -0
  16. data/doc/rdoc/classes/Cache.html +126 -0
  17. data/doc/rdoc/classes/Cache/StorageCache.html +320 -0
  18. data/doc/rdoc/classes/Cache/Strategy.html +128 -0
  19. data/doc/rdoc/classes/Cache/Strategy/CapacityBounded.html +269 -0
  20. data/doc/rdoc/classes/Cache/Strategy/LFU.html +238 -0
  21. data/doc/rdoc/classes/Cache/Strategy/LFU/Item.html +111 -0
  22. data/doc/rdoc/classes/Cache/Strategy/LRU.html +238 -0
  23. data/doc/rdoc/classes/Cache/Strategy/LRU/Item.html +111 -0
  24. data/doc/rdoc/classes/Cache/Strategy/Unbounded.html +225 -0
  25. data/doc/rdoc/classes/Cache/Strategy/Unbounded/Item.html +111 -0
  26. data/doc/rdoc/classes/Enumerable.html +146 -0
  27. data/doc/rdoc/classes/LiteralMethod.html +196 -0
  28. data/doc/rdoc/classes/Object.html +178 -0
  29. data/doc/rdoc/classes/String.html +172 -0
  30. data/doc/rdoc/classes/Struct.html +174 -0
  31. data/doc/rdoc/classes/Wee.html +160 -0
  32. data/doc/rdoc/classes/Wee/AnswerDecoration.html +182 -0
  33. data/doc/rdoc/classes/Wee/Application.html +337 -0
  34. data/doc/rdoc/classes/Wee/Brush.html +245 -0
  35. data/doc/rdoc/classes/Wee/Brush/ActionCallbackMixin.html +149 -0
  36. data/doc/rdoc/classes/Wee/Brush/ActionMixin.html +146 -0
  37. data/doc/rdoc/classes/Wee/Brush/ActionURLCallbackMixin.html +157 -0
  38. data/doc/rdoc/classes/Wee/Brush/AnchorTag.html +210 -0
  39. data/doc/rdoc/classes/Wee/Brush/AssignMixin.html +141 -0
  40. data/doc/rdoc/classes/Wee/Brush/CallbackMixin.html +141 -0
  41. data/doc/rdoc/classes/Wee/Brush/FormTag.html +225 -0
  42. data/doc/rdoc/classes/Wee/Brush/GenericEncodedTextBrush.html +176 -0
  43. data/doc/rdoc/classes/Wee/Brush/GenericTagBrush.html +283 -0
  44. data/doc/rdoc/classes/Wee/Brush/GenericTextBrush.html +176 -0
  45. data/doc/rdoc/classes/Wee/Brush/ImageButtonTag.html +195 -0
  46. data/doc/rdoc/classes/Wee/Brush/InputCallbackMixin.html +149 -0
  47. data/doc/rdoc/classes/Wee/Brush/InputTag.html +172 -0
  48. data/doc/rdoc/classes/Wee/Brush/Page.html +193 -0
  49. data/doc/rdoc/classes/Wee/Brush/SelectListTag.html +267 -0
  50. data/doc/rdoc/classes/Wee/Brush/SelectOptionTag.html +177 -0
  51. data/doc/rdoc/classes/Wee/Brush/SubmitButtonTag.html +154 -0
  52. data/doc/rdoc/classes/Wee/Brush/TableDataTag.html +173 -0
  53. data/doc/rdoc/classes/Wee/Brush/TableHeaderTag.html +146 -0
  54. data/doc/rdoc/classes/Wee/Brush/TableRowTag.html +277 -0
  55. data/doc/rdoc/classes/Wee/Brush/TableTag.html +146 -0
  56. data/doc/rdoc/classes/Wee/Brush/TextAreaTag.html +229 -0
  57. data/doc/rdoc/classes/Wee/Brush/TextInputTag.html +154 -0
  58. data/doc/rdoc/classes/Wee/Callback.html +231 -0
  59. data/doc/rdoc/classes/Wee/CallbackRegistry.html +308 -0
  60. data/doc/rdoc/classes/Wee/CallbackStream.html +227 -0
  61. data/doc/rdoc/classes/Wee/Canvas.html +235 -0
  62. data/doc/rdoc/classes/Wee/Component.html +933 -0
  63. data/doc/rdoc/classes/Wee/Context.html +111 -0
  64. data/doc/rdoc/classes/Wee/Decoration.html +338 -0
  65. data/doc/rdoc/classes/Wee/Delegate.html +247 -0
  66. data/doc/rdoc/classes/Wee/ErrorPage.html +175 -0
  67. data/doc/rdoc/classes/Wee/ErrorResponse.html +180 -0
  68. data/doc/rdoc/classes/Wee/GenericResponse.html +162 -0
  69. data/doc/rdoc/classes/Wee/HtmlCanvas.html +751 -0
  70. data/doc/rdoc/classes/Wee/HtmlWriter.html +351 -0
  71. data/doc/rdoc/classes/Wee/LiteralMethodCallback.html +180 -0
  72. data/doc/rdoc/classes/Wee/MethodCallback.html +193 -0
  73. data/doc/rdoc/classes/Wee/Page.html +111 -0
  74. data/doc/rdoc/classes/Wee/Presenter.html +521 -0
  75. data/doc/rdoc/classes/Wee/RedirectResponse.html +150 -0
  76. data/doc/rdoc/classes/Wee/RefreshResponse.html +157 -0
  77. data/doc/rdoc/classes/Wee/RenderingContext.html +111 -0
  78. data/doc/rdoc/classes/Wee/Request.html +268 -0
  79. data/doc/rdoc/classes/Wee/RequestHandler.html +336 -0
  80. data/doc/rdoc/classes/Wee/Response.html +260 -0
  81. data/doc/rdoc/classes/Wee/Session.html +469 -0
  82. data/doc/rdoc/classes/Wee/SimpleIdGenerator.html +198 -0
  83. data/doc/rdoc/classes/Wee/Snapshot.html +211 -0
  84. data/doc/rdoc/classes/Wee/StateHolder.html +149 -0
  85. data/doc/rdoc/classes/Wee/StateRegistry.html +434 -0
  86. data/doc/rdoc/classes/Wee/StateRegistry/Snapshot.html +320 -0
  87. data/doc/rdoc/classes/Wee/StateRegistry/WithObject.html +153 -0
  88. data/doc/rdoc/classes/Wee/Utils.html +111 -0
  89. data/doc/rdoc/classes/Wee/Utils/LRUCache.html +148 -0
  90. data/doc/rdoc/classes/Wee/ValueHolder.html +220 -0
  91. data/doc/rdoc/classes/Wee/WEBrickAdaptor.html +330 -0
  92. data/doc/rdoc/created.rid +1 -0
  93. data/doc/rdoc/files/INSTALL.html +118 -0
  94. data/doc/rdoc/files/README.html +466 -0
  95. data/doc/rdoc/files/lib/cache/cache_rb.html +101 -0
  96. data/doc/rdoc/files/lib/wee/adaptors/webrick_rb.html +108 -0
  97. data/doc/rdoc/files/lib/wee/application_rb.html +112 -0
  98. data/doc/rdoc/files/lib/wee/callback_rb.html +107 -0
  99. data/doc/rdoc/files/lib/wee/component_ext_rb.html +101 -0
  100. data/doc/rdoc/files/lib/wee/component_rb.html +109 -0
  101. data/doc/rdoc/files/lib/wee/context_rb.html +101 -0
  102. data/doc/rdoc/files/lib/wee/core/callback_rb.html +115 -0
  103. data/doc/rdoc/files/lib/wee/core/component_rb.html +108 -0
  104. data/doc/rdoc/files/lib/wee/core/decoration_rb.html +133 -0
  105. data/doc/rdoc/files/lib/wee/core/presenter_rb.html +112 -0
  106. data/doc/rdoc/files/lib/wee/core/snapshot_rb.html +113 -0
  107. data/doc/rdoc/files/lib/wee/core/valueholder_rb.html +110 -0
  108. data/doc/rdoc/files/lib/wee/core_rb.html +131 -0
  109. data/doc/rdoc/files/lib/wee/decoration_rb.html +101 -0
  110. data/doc/rdoc/files/lib/wee/holder_rb.html +101 -0
  111. data/doc/rdoc/files/lib/wee/html_canvas_rb.html +108 -0
  112. data/doc/rdoc/files/lib/wee/html_writer_rb.html +108 -0
  113. data/doc/rdoc/files/lib/wee/idgen_rb.html +101 -0
  114. data/doc/rdoc/files/lib/wee/page_rb.html +101 -0
  115. data/doc/rdoc/files/lib/wee/presenter_rb.html +112 -0
  116. data/doc/rdoc/files/lib/wee/renderer/html/brushes_rb.html +101 -0
  117. data/doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html +101 -0
  118. data/doc/rdoc/files/lib/wee/renderer/html/writer_rb.html +108 -0
  119. data/doc/rdoc/files/lib/wee/rendering/html/brushes_rb.html +101 -0
  120. data/doc/rdoc/files/lib/wee/rendering/html/canvas_rb.html +101 -0
  121. data/doc/rdoc/files/lib/wee/rendering/html/writer_rb.html +108 -0
  122. data/doc/rdoc/files/lib/wee/request_rb.html +113 -0
  123. data/doc/rdoc/files/lib/wee/requesthandler_rb.html +101 -0
  124. data/doc/rdoc/files/lib/wee/response_rb.html +108 -0
  125. data/doc/rdoc/files/lib/wee/session_rb.html +109 -0
  126. data/doc/rdoc/files/lib/wee/snapshot_ext_rb.html +101 -0
  127. data/doc/rdoc/files/lib/wee/snapshot_rb.html +107 -0
  128. data/doc/rdoc/files/lib/wee/state_registry_rb.html +110 -0
  129. data/doc/rdoc/files/lib/wee/stuff_rb.html +144 -0
  130. data/doc/rdoc/files/lib/wee/utils/cache_rb.html +108 -0
  131. data/doc/rdoc/files/lib/wee/webrick_rb.html +108 -0
  132. data/doc/rdoc/files/lib/wee_rb.html +132 -0
  133. data/doc/rdoc/fr_class_index.html +93 -0
  134. data/doc/rdoc/fr_file_index.html +51 -0
  135. data/doc/rdoc/fr_method_index.html +242 -0
  136. data/doc/rdoc/index.html +24 -0
  137. data/doc/rdoc/rdoc-style.css +208 -0
  138. data/examples/ObjectSpaceBrowser.rb +199 -0
  139. data/examples/calendar.rb +366 -0
  140. data/examples/cc.rb +94 -0
  141. data/examples/draw.rb +91 -0
  142. data/examples/example.rb +223 -0
  143. data/examples/test.rb +66 -0
  144. data/examples/window.rb +53 -0
  145. data/lib/cache/cache.rb +9 -0
  146. data/lib/wee.rb +18 -8
  147. data/lib/wee/adaptors/webrick.rb +73 -0
  148. data/lib/wee/application.rb +69 -71
  149. data/lib/wee/context.rb +2 -12
  150. data/lib/wee/core.rb +15 -0
  151. data/lib/wee/core/callback.rb +108 -0
  152. data/lib/wee/core/component.rb +314 -0
  153. data/lib/wee/core/decoration.rb +129 -0
  154. data/lib/wee/core/presenter.rb +132 -0
  155. data/lib/wee/core/snapshot.rb +21 -0
  156. data/lib/wee/core/valueholder.rb +19 -0
  157. data/lib/wee/idgen.rb +13 -0
  158. data/lib/wee/page.rb +1 -1
  159. data/lib/wee/renderer/html/brushes.rb +435 -0
  160. data/lib/wee/renderer/html/canvas.rb +148 -0
  161. data/lib/wee/{html_writer.rb → renderer/html/writer.rb} +31 -16
  162. data/lib/wee/request.rb +57 -0
  163. data/lib/wee/requesthandler.rb +77 -0
  164. data/lib/wee/response.rb +77 -0
  165. data/lib/wee/session.rb +70 -64
  166. data/lib/wee/{snapshot.rb → snapshot_ext.rb} +4 -4
  167. data/test/components/calltest.rb +16 -0
  168. data/test/components/counter.rb +17 -0
  169. data/test/components/messagebox.rb +15 -0
  170. data/test/components/page.rb +14 -0
  171. data/test/components/page_decoration.rb +7 -0
  172. data/test/stress.rb +64 -0
  173. data/test/test_component.rb +106 -0
  174. data/test/test_html_canvas.rb +25 -0
  175. data/test/test_html_writer.rb +27 -0
  176. data/test/test_request.rb +13 -0
  177. data/test/utils/cross.rb +65 -0
  178. data/test/utils/generic_plotter.rb +28 -0
  179. data/test/utils/gnuplot.rb +31 -0
  180. data/test/utils/measure_memory.rb +9 -0
  181. data/test/utils/memory_plotter.rb +10 -0
  182. data/test/utils/object_plotter.rb +10 -0
  183. data/test/utils/webrick_background.rb +31 -0
  184. data/wee.gemspec +22 -0
  185. metadata +222 -18
  186. data/lib/wee/component.rb +0 -126
  187. data/lib/wee/delegate_decoration.rb +0 -22
  188. data/lib/wee/handler_registry.rb +0 -89
  189. data/lib/wee/holder.rb +0 -14
  190. data/lib/wee/html_canvas.rb +0 -379
  191. data/lib/wee/state_registry.rb +0 -173
  192. data/lib/wee/stuff.rb +0 -29
  193. data/lib/wee/webrick.rb +0 -15
@@ -0,0 +1,199 @@
1
+ $LOAD_PATH.unshift << "../lib"
2
+ require 'wee'
3
+ require 'wee/webrick'
4
+ require 'wee/utils/cache'
5
+ require 'cgi'
6
+
7
+ require 'enumerator'
8
+
9
+ module ObjectSpaceBrowser
10
+
11
+ class Klasses < Wee::Component
12
+
13
+ def klasses
14
+ ObjectSpace.to_enum(:each_object, Class).sort_by{|k| k.name}
15
+ end
16
+
17
+ def choose(klass)
18
+ call(Klass.new(klass))
19
+ end
20
+
21
+ def render
22
+ r.h1 "Classes"
23
+
24
+ r.ul {
25
+ klasses.each do |klass|
26
+ r.li { r.anchor.action(:choose, klass).with(klass.name) }
27
+ end
28
+ }
29
+ end
30
+ end
31
+
32
+ class Klass < Wee::Component
33
+
34
+ def initialize(klass)
35
+ super()
36
+ @klass = klass
37
+ set_instances
38
+ end
39
+
40
+ def choose(instance)
41
+ call Instance.new(instance)
42
+ end
43
+
44
+ ##
45
+ # Fetches all instances of the klass sorted by object_id
46
+
47
+ def set_instances
48
+ @instances =
49
+ case @klass
50
+ when Symbol
51
+ Symbol.all_symbols.sort_by do |s| s.to_s end
52
+ else
53
+ ObjectSpace.to_enum(:each_object, @klass).sort_by{|i| i.object_id}
54
+ end
55
+ end
56
+
57
+ def render
58
+ instances = @instances
59
+ r.h1 "Class #{@klass.name}"
60
+ r.h2 "#{@instances.length} Instances"
61
+
62
+ return if @instances.length.zero?
63
+
64
+ r.ul {
65
+ @instances.each do |instance|
66
+ r.li { r.anchor.action(:choose, instance).with("0x%x" % instance.object_id) }
67
+ end
68
+ }
69
+ end
70
+
71
+ end
72
+
73
+ class Instance < Wee::Component
74
+
75
+ def initialize(instance)
76
+ super()
77
+ @instance = instance
78
+ end
79
+
80
+ def choose(instance)
81
+ call Instance.new(instance)
82
+ end
83
+
84
+ def back
85
+ answer
86
+ end
87
+
88
+ def render
89
+ r.anchor.action(:back).with("back")
90
+
91
+ r.break
92
+ r.h1 "Instance 0x%x of #{@instance.class.name}" % @instance.object_id
93
+
94
+ case @instance
95
+ when Array
96
+ r.bold("array elements: ")
97
+ r.break
98
+ r.ul do
99
+ @instance.each do |obj|
100
+ r.li { render_obj(obj, r) }
101
+ end
102
+ end
103
+ when Hash
104
+ r.bold("hash elements: ")
105
+ r.break
106
+ r.table.border(1).with do
107
+ r.table_row do
108
+ r.table_data do r.bold("Key") end
109
+ r.table_data do r.bold("Value") end
110
+ end
111
+
112
+ @instance.each_pair do |k, v|
113
+ r.table_row do
114
+ r.table_data { render_obj(k, r) }
115
+ r.table_data { render_obj(v, r) }
116
+ end
117
+ end
118
+ end
119
+
120
+ when String, Float, Fixnum, Bignum, Numeric, Integer, Symbol
121
+ r.encode_text(@instance.inspect)
122
+ end
123
+
124
+ return if @instance.instance_variables.empty?
125
+ r.break
126
+
127
+ render_instance_variables(r)
128
+ end
129
+
130
+ def render_instance_variables(r)
131
+ r.table.border(1).with do
132
+ r.table_row do
133
+ r.table_data do r.bold("Instance Variable") end
134
+ r.table_data do r.bold("Object") end
135
+ end
136
+ @instance.instance_variables.each do |var| render_ivar_row(var, r) end
137
+ end
138
+ end
139
+
140
+ def render_ivar_row(var, r)
141
+ r.table_row do
142
+ r.table_data(var)
143
+ r.table_data do
144
+ v = @instance.instance_variable_get(var)
145
+ render_obj(v, r)
146
+ end
147
+ end
148
+ end
149
+
150
+ def render_obj(obj, r)
151
+ r.anchor.action(:choose, obj).with do
152
+ r.bold(obj.class.name)
153
+ r.space
154
+ r.text("(#{ obj.object_id })")
155
+ r.space
156
+ r.space
157
+
158
+ case obj
159
+ when String, Float, Integer, Symbol
160
+ r.encode_text(obj.inspect)
161
+ else
162
+ r.encode_text(obj.inspect[0, 40] + "...")
163
+ end
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+ end # module ObjectSpaceBrowser
170
+
171
+ if $0 == __FILE__ then
172
+
173
+ OBJ = {
174
+ "hello" => { [1,2,3] => [5,6,7], "test" => :super },
175
+ "other" => %w(a b c d e f)
176
+ }
177
+
178
+ class MySession < Wee::Session
179
+ def initialize
180
+ super do
181
+ self.root_component = ObjectSpaceBrowser::Instance.new(OBJ)
182
+ self.page_store = Wee::Utils::LRUCache.new(10) # backtrack up to 10 pages
183
+ end
184
+ end
185
+ end
186
+
187
+ class MyApplication < Wee::Application
188
+ def shutdown
189
+ end
190
+ end
191
+
192
+ Wee::Application.new {|app|
193
+ app.name = 'ObjectBrowser'
194
+ app.path = '/ob'
195
+ app.session_class = MySession
196
+ app.session_store = Wee::Utils::LRUCache.new(10)
197
+ app.dumpfile = ''
198
+ }.start
199
+ end
@@ -0,0 +1,366 @@
1
+ # Copyright by Kevin Howe (kh@newclear.ca)
2
+
3
+ $LOAD_PATH.unshift << "../lib"
4
+ require 'wee'
5
+ require 'wee/adaptors/webrick'
6
+ require 'wee/utils/cache'
7
+ require 'date'
8
+
9
+ class Date
10
+ # Fetch the number of days in the given month
11
+ #
12
+ def days_in
13
+ ((Date.new(self.year, self.month, 1) >> 1)-1).day
14
+ end
15
+ # Calendar represenation of a month. Consists of a
16
+ # list of weeks, each week a list of 7 days, each day a Date object.
17
+ # Padded with days showing for previous and next month.
18
+ #
19
+ def calendar
20
+ # months
21
+ curr_month = Date.new(self.year, self.month, 1)
22
+ prev_month = (curr_month << 1)
23
+ next_month = (curr_month >> 1)
24
+
25
+ # previous month days
26
+ prev_days = Array.new
27
+ prev_in_curr = curr_month.wday
28
+ ((curr_month-1)-(prev_in_curr-1)).upto(curr_month-1) { |d| prev_days << d }
29
+
30
+ # current month days
31
+ curr_days = Array.new
32
+ curr_month.upto(next_month-1) { |d| curr_days << d }
33
+
34
+ # next month days
35
+ next_days = Array.new
36
+ days = prev_days+curr_days
37
+ weeks = (days.size.to_f/7).ceil
38
+ cdays_size = weeks*7
39
+ next_in_curr = (cdays_size-days.size)
40
+ next_month.upto(next_month+(next_in_curr-1)) { |d| next_days << d }
41
+ days += next_days
42
+
43
+ # split into weeks
44
+ table = Array.new
45
+ days.each do |day|
46
+ table << Array.new if table.size == 0 or table.last.size == 7
47
+ table.last << day
48
+ end
49
+
50
+ table
51
+ end
52
+ end
53
+
54
+ # Generates a browsable calendar.
55
+ # Each day is linked, clicking will set the date to that particular day.
56
+ #
57
+ class MiniCalendar < Wee::Component
58
+
59
+ # Browse mode: no answer will be given
60
+ attr_accessor :browse
61
+
62
+ # Holds the current chosen date
63
+ attr_accessor :date
64
+
65
+ # Initialize the MiniCalendar
66
+ #
67
+ def initialize(date=Date.today)
68
+ super()
69
+ @month = Date.new(date.year, date.month, 1)
70
+ @day = date
71
+ @browse = false
72
+ end
73
+
74
+ # Backtrack state
75
+ #
76
+ def backtrack_state(snap)
77
+ super
78
+ snap.add(self)
79
+ end
80
+
81
+ # Set to browse-only (no answer will be given)
82
+ #
83
+ def browse(value=true)
84
+ @browse = (value && true)
85
+ self
86
+ end
87
+
88
+ # True if in browser-only mode
89
+ #
90
+ def browse?
91
+ @browse
92
+ end
93
+
94
+ # True if the given date is the currently selected month
95
+ #
96
+ def current_month?(date)
97
+ Date.new(date.year, date.month, 1) == @month
98
+ end
99
+
100
+ # True if the given date is the currently selected day
101
+ #
102
+ def selected_day?(date)
103
+ date == @day
104
+ end
105
+
106
+ # Date object representing the previous month
107
+ #
108
+ def prev_month
109
+ @month << 1
110
+ end
111
+
112
+ # Date object representing the next month
113
+ #
114
+ def next_month
115
+ @month >> 1
116
+ end
117
+
118
+ # Previous month's abbreviation
119
+ #
120
+ def prev_month_abbr
121
+ Date::ABBR_MONTHNAMES[prev_month.month]
122
+ end
123
+
124
+ # Next month's abbreviation
125
+ #
126
+ def next_month_abbr
127
+ Date::ABBR_MONTHNAMES[next_month.month]
128
+ end
129
+
130
+ # String to be displayed as the month heading
131
+ #
132
+ def month_heading
133
+ Date::MONTHNAMES[@month.month].to_s+' '+@month.year.to_s
134
+ end
135
+
136
+ # String to be displayed indicating the current date
137
+ #
138
+ def today_string
139
+ date = Date.today
140
+ mon_abbr = Date::ABBR_MONTHNAMES[date.month]
141
+ day_abbr = Date::ABBR_DAYNAMES[date.wday]
142
+ sprintf('Today is %s, %s %s %s', day_abbr, mon_abbr, date.day, date.year)
143
+ end
144
+
145
+ # Render a given day
146
+ #
147
+ def render_day(date)
148
+ if current_month?(date)
149
+ selected_day?(date) ? render_selected_day(date) : render_month_day(date)
150
+ else
151
+ render_other_day(date)
152
+ end
153
+ end
154
+
155
+ # Render a day of the currently selected month
156
+ #
157
+ def render_month_day(date)
158
+ r.table_data { r.anchor.callback { save(date) }.with(date.day) }
159
+ end
160
+
161
+ # Render the currently selected day
162
+ #
163
+ def render_selected_day(date)
164
+ r.table_data.style('border: 1px solid black').with do
165
+ r.anchor.style('font-weight: bold').callback { save(date) }.with(date.day)
166
+ end
167
+ end
168
+
169
+ # Render days of the previous or next month
170
+ #
171
+ def render_other_day(date)
172
+ r.table_data do
173
+ r.anchor.style('color: silver').callback { save(date) }.with(date.day)
174
+ end
175
+ end
176
+
177
+ # CSS styles
178
+ #
179
+ def render_styles
180
+ # ...
181
+ end
182
+
183
+ # Render Calender header
184
+ #
185
+ def render_header
186
+ r.table_row do
187
+ r.table_header.colspan(4).with { r.encoded_text(month_heading) }
188
+ r.table_header { r.anchor.callback { go_prev }.with(prev_month_abbr) }
189
+ r.table_header { r.anchor.callback { go_next }.with(next_month_abbr) }
190
+ r.table_header { browse? ? r.space : r.anchor.callback { back }.style('color: black').with('X') }
191
+ end
192
+ end
193
+
194
+ # Render Calendar footer
195
+ #
196
+ def render_footer
197
+ r.table_row { r.table_header.colspan(7).with { r.encoded_text(today_string) } }
198
+ end
199
+
200
+ # Render Calendar
201
+ #
202
+ def render
203
+ r.html do
204
+ r.head { r.title('Calendar'); render_styles }
205
+ r.body do
206
+ r.text(sprintf('<!--Month: %s, Day: %s-->', @month, @day))
207
+ r.table { r.table_row { r.table_header {
208
+ r.table do
209
+ render_header
210
+ r.table_row { Date::ABBR_DAYNAMES.each { |day| r.table_header(day) } }
211
+ @month.calendar.each do |week|
212
+ r.table_row do
213
+ week.each { |day| render_day(day) }
214
+ end
215
+ end
216
+ render_footer
217
+ end
218
+ }}}
219
+ end
220
+ end
221
+ end
222
+
223
+ # Return without changes
224
+ #
225
+ def back
226
+ answer nil unless browse?
227
+ end
228
+
229
+ # Select the previous month
230
+ #
231
+ def go_prev
232
+ @month = prev_month
233
+ end
234
+
235
+ # Select the next month
236
+ #
237
+ def go_next
238
+ @month = next_month
239
+ end
240
+
241
+ # Save the given day
242
+ #
243
+ def save(day)
244
+ @day = day
245
+ @month = Date.new(day.year, day.month, 1)
246
+ answer(day) unless browse?
247
+ end
248
+ end
249
+
250
+ if __FILE__ == $0
251
+
252
+ # Custom CSS styles
253
+ #
254
+ module StyleMixin
255
+ def render_styles
256
+ r.style("
257
+ a {
258
+ text-decoration: none;
259
+ }
260
+ body {
261
+ font-size : 11px;
262
+ font-family : Arial, Helvetica, sans-serif;
263
+ text-align: center;
264
+ }
265
+ td {
266
+ font-family: Arial, Helvetica, sans-serif;
267
+ font-size: 11px;
268
+ border: 1px solid;
269
+ background-color: #FFFFFF;
270
+ vertical-align: top;
271
+ text-align: center;
272
+ }
273
+ th {
274
+ font-family: Arial, Helvetica, sans-serif;
275
+ font-size: 11px;
276
+ font-style: normal;
277
+ font-weight: bold;
278
+ background-color: #BBCCFF;
279
+ border: 1px solid;
280
+ vertical-align: top;
281
+ text-align: center;
282
+ }
283
+ ")
284
+ end
285
+ end
286
+
287
+ # Calendar with custom CSS styles
288
+ #
289
+ class CustomCalendar < MiniCalendar
290
+ include StyleMixin
291
+ end
292
+
293
+ # Calendar demo
294
+ #
295
+ class CustomCalendarDemo < Wee::Component
296
+ include StyleMixin
297
+
298
+ # Holds the current chosen date
299
+ attr_accessor :date
300
+
301
+ # Initialize with a Date object (defaults to today)
302
+ #
303
+ def initialize(date=Date.today)
304
+ super()
305
+ @date = date
306
+ end
307
+
308
+ # Backtrack state
309
+ #
310
+ def backtrack_state(snap)
311
+ super
312
+ snap.add(self)
313
+ end
314
+
315
+ # Render calendar icon
316
+ #
317
+ def render_icon
318
+ icon = 'http://www.softcomplex.com/products/tigra_calendar/img/cal.gif'
319
+ r.img.src(icon).width(16).height(16).border(0).alt('Calendar')
320
+ end
321
+
322
+ # Render Calendar demo
323
+ #
324
+ def render
325
+ r.html do
326
+ r.head { r.title('Calendar Demo'); render_styles }
327
+ r.body do
328
+ r.break
329
+ r.table { r.table_row { r.table_header {
330
+ r.table do
331
+ r.table_row { r.table_header('Calendar Demo') }
332
+ r.table_row { r.table_data {
333
+ r.text_input.value(@date).attr(:date)
334
+ r.space
335
+ r.anchor.callback { calendar }.with { render_icon }
336
+ }}
337
+ end
338
+ }}}
339
+ end
340
+ end
341
+ end
342
+
343
+ # Call the calendar component
344
+ #
345
+ def calendar()
346
+ if date = call( CustomCalendar.new(@date) )
347
+ @date = date
348
+ end
349
+ end
350
+ end
351
+
352
+ class MySession < Wee::Session
353
+ def initialize
354
+ super do
355
+ self.root_component = CustomCalendarDemo.new
356
+ self.page_store = Wee::Utils::LRUCache.new(10) # backtrack up to 10 pages
357
+ end
358
+ end
359
+ end
360
+
361
+ app = Wee::Application.new {|app|
362
+ app.default_request_handler { MySession.new }
363
+ app.id_generator = Wee::SimpleIdGenerator.new(rand(1_000_000))
364
+ }
365
+ Wee::WEBrickAdaptor.register('/app' => app).start
366
+ end