ruby_mvc 0.0.1 → 0.0.2

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 (68) hide show
  1. data/README.md +14 -0
  2. data/lib/ruby_mvc.rb +3 -1
  3. data/lib/ruby_mvc/application.rb +52 -2
  4. data/lib/ruby_mvc/controllers.rb +28 -0
  5. data/lib/ruby_mvc/controllers/action.rb +93 -0
  6. data/lib/ruby_mvc/controllers/action_group.rb +70 -0
  7. data/lib/ruby_mvc/controllers/app_controller.rb +4 -2
  8. data/lib/ruby_mvc/controllers/rails_controller.rb +2 -0
  9. data/lib/ruby_mvc/models.rb +2 -0
  10. data/lib/ruby_mvc/models/ar_table_model.rb +133 -0
  11. data/lib/ruby_mvc/models/array_table_model.rb +81 -13
  12. data/lib/ruby_mvc/models/keyed_array_table_model.rb +1 -1
  13. data/lib/ruby_mvc/models/model.rb +129 -0
  14. data/lib/ruby_mvc/models/table_model.rb +107 -10
  15. data/lib/ruby_mvc/models/view_model_template.rb +140 -0
  16. data/lib/ruby_mvc/renderers.rb +1 -0
  17. data/lib/ruby_mvc/renderers/html4_table_model_renderer.rb +7 -6
  18. data/lib/ruby_mvc/renderers/hyperlink_cell_renderer.rb +47 -0
  19. data/lib/ruby_mvc/toolkit.rb +5 -1
  20. data/lib/ruby_mvc/toolkit/browser_history.rb +115 -0
  21. data/lib/ruby_mvc/toolkit/dialog.rb +12 -1
  22. data/lib/ruby_mvc/toolkit/frame.rb +3 -1
  23. data/lib/ruby_mvc/toolkit/grid_view.rb +46 -0
  24. data/lib/ruby_mvc/toolkit/messagebox.rb +32 -0
  25. data/lib/ruby_mvc/toolkit/peers/wxruby.rb +5 -0
  26. data/lib/ruby_mvc/toolkit/peers/wxruby/app.rb +23 -2
  27. data/lib/ruby_mvc/toolkit/peers/wxruby/common.rb +11 -1
  28. data/lib/ruby_mvc/toolkit/peers/wxruby/dialog.rb +82 -0
  29. data/lib/ruby_mvc/toolkit/peers/wxruby/form_builder.rb +108 -0
  30. data/lib/ruby_mvc/toolkit/peers/wxruby/frame.rb +85 -1
  31. data/lib/ruby_mvc/toolkit/peers/wxruby/grid_model.rb +79 -0
  32. data/lib/ruby_mvc/toolkit/peers/wxruby/grid_view.rb +117 -0
  33. data/lib/ruby_mvc/toolkit/peers/wxruby/messagebox.rb +58 -0
  34. data/lib/ruby_mvc/toolkit/peers/wxruby/web_view.rb +40 -10
  35. data/lib/ruby_mvc/toolkit/property_change_notifier.rb +46 -0
  36. data/lib/ruby_mvc/toolkit/signal_handler.rb +149 -0
  37. data/lib/ruby_mvc/toolkit/web_view.rb +1 -1
  38. data/lib/ruby_mvc/toolkit/widget.rb +13 -6
  39. data/lib/ruby_mvc/views.rb +8 -59
  40. data/lib/ruby_mvc/views/{ar_type_list.rb → ar_form_view.rb} +10 -13
  41. data/lib/ruby_mvc/views/ar_support.rb +29 -0
  42. data/lib/ruby_mvc/views/ar_type_editor.rb +17 -28
  43. data/lib/ruby_mvc/views/ar_web_model_view.rb +59 -0
  44. data/lib/ruby_mvc/views/ar_web_type_list.rb +44 -0
  45. data/lib/ruby_mvc/views/browser_view.rb +185 -0
  46. data/lib/ruby_mvc/views/form_view.rb +111 -0
  47. data/lib/ruby_mvc/views/grid_table_view.rb +96 -0
  48. data/lib/ruby_mvc/views/table_view.rb +0 -39
  49. data/lib/ruby_mvc/views/view.rb +121 -0
  50. data/lib/ruby_mvc/views/web_content_table_view.rb +40 -0
  51. data/lib/ruby_mvc/views/{web_view.rb → web_content_view.rb} +17 -28
  52. data/lib/ruby_mvc/views/web_model_view.rb +67 -0
  53. data/ruby_mvc.gemspec +1 -1
  54. data/sample/browser_view.rb +57 -0
  55. data/sample/form.rb +59 -0
  56. data/sample/form2.rb +63 -0
  57. data/sample/grid_table_view.rb +68 -0
  58. data/sample/grid_view.rb +44 -0
  59. data/sample/grid_view2.rb +57 -0
  60. data/sample/test.html +1 -0
  61. data/sample/test2.html +33 -0
  62. data/sample/web_view.rb +4 -0
  63. data/test/unit/models/test_array_table_model.rb +19 -3
  64. data/test/unit/models/test_keyed_array_table_model.rb +3 -2
  65. data/test/unit/models/test_model.rb +88 -0
  66. metadata +39 -20
  67. data/lib/ruby_mvc/toolkit/notification.rb +0 -202
  68. data/lib/ruby_mvc/views/ar_model_editor.rb +0 -84
@@ -0,0 +1,108 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: form_builder.rb
21
+ # Created: Fri 30 Dec 2011 17:20:42 CET
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+ module Toolkit
28
+ module WxRuby
29
+
30
+ # This module is a helper class used to build the
31
+ # concrete representations of the FormView controls
32
+
33
+ class FormBuilder
34
+ def self.build(parent, form)
35
+ builder = self.new
36
+ builder.build(parent, form)
37
+ builder
38
+ end
39
+
40
+ def initialize
41
+ @fields = {}
42
+ @panel = Wx::BoxSizer.new(Wx::VERTICAL)
43
+ @sizer = Wx::FlexGridSizer.new(0, 2, 5, 5)
44
+ @panel.add(@sizer, 0, Wx::ALIGN_CENTER_VERTICAL|Wx::ALL, 5)
45
+ end
46
+
47
+ def widget
48
+ @panel
49
+ end
50
+
51
+ def build(parent, form)
52
+ @form = form
53
+ form.layout do |key, label, val, editor, disabled|
54
+ puts "key: #{key}; disabled: #{disabled}"
55
+ case(editor)
56
+ when :textarea
57
+ w = build_textfield(parent, label, val, true)
58
+ else
59
+ w = build_textfield(parent, label, val)
60
+ end
61
+ @fields[key] = w
62
+ w.disable if disabled
63
+ end
64
+ end
65
+
66
+ def submit
67
+ save_form
68
+ end
69
+
70
+ private
71
+ def save_form
72
+ vals = {}
73
+ @fields.each do |k, v|
74
+ if v && v.is_modified
75
+ vals[k] = v.get_value
76
+ end
77
+ end
78
+ @form.submit(vals)
79
+ end
80
+
81
+ # def load_form(model)
82
+ # @fields.keys.each do |k|
83
+ # @fields[k].set_value(model[k].to_s)
84
+ # end
85
+ # end
86
+
87
+ def build_textfield(parent, label, val = "", multiline = false)
88
+ if multiline
89
+ flags = Wx::TE_MULTILINE
90
+ size = [ 150, -1 ]
91
+ else
92
+ flags = 0
93
+ size = [ 150, -1 ]
94
+ end
95
+ st = Wx::StaticText.new(parent, :label => label)
96
+ tf = Wx::TextCtrl.new(parent, :value => val.to_s, :size => size, :style => flags)
97
+ tf.evt_set_focus { |e| tf.set_selection(0, -1) }
98
+ tf.evt_kill_focus { |e| tf.set_selection(0, 0) }
99
+ # @sizer.add(st, 0, Wx::ALIGN_LEFT|Wx::ALL, 5)
100
+ # @sizer.add(tf, 1, Wx::ALIGN_CENTER|Wx::ALL, 5)
101
+ @sizer.add(st)
102
+ @sizer.add(tf)
103
+ tf
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -27,6 +27,7 @@ module RubyMVC
27
27
  module Toolkit
28
28
  module WxRuby
29
29
  class Frame < Wx::Frame
30
+ include Toolkit::SignalHandler
30
31
  include Common
31
32
  Toolkit::Frame.peer_class = self
32
33
 
@@ -34,7 +35,19 @@ module RubyMVC
34
35
  opts = {}
35
36
  opts[:title] = options[:title]
36
37
  opts[:size] = [ options[:width], options[:height] ]
37
- super(options[:parent], opts)
38
+ if parent = options[:parent]
39
+ parent = parent.peer
40
+ end
41
+ super(parent, opts)
42
+ if icon = options[:icon]
43
+ self.set_icon WxRuby.load_icon(icon)
44
+ end
45
+ @action_index = {}
46
+
47
+ evt_close do |e|
48
+ e.skip
49
+ signal_emit("window-closed", self)
50
+ end
38
51
  end
39
52
 
40
53
  # This method is used to add a child to the existing
@@ -42,6 +55,77 @@ module RubyMVC
42
55
 
43
56
  def add(child, options = {})
44
57
  child.peer.reparent(self)
58
+
59
+ if child.is_a?(RubyMVC::Views::View) && (a = child.actions)
60
+ child.frame = self
61
+ merge_actions(a)
62
+ end
63
+ end
64
+
65
+ def merge_actions(actions)
66
+ # puts "#merge_actions #{actions.inspect}"
67
+ tb = toolbar
68
+ actions.each do |a|
69
+ i = @action_index.size
70
+ # puts "Action: #{a.label}"
71
+ case a[:icon]
72
+ when :stock_new
73
+ artid = Wx::ART_NEW
74
+ when :stock_edit
75
+ artid = Wx::ART_NORMAL_FILE
76
+ when :stock_delete
77
+ artid = Wx::ART_DELETE
78
+ when :stock_home
79
+ artid = Wx::ART_GO_HOME
80
+ when :stock_back
81
+ artid = Wx::ART_GO_BACK
82
+ when :stock_forward
83
+ artid = Wx::ART_GO_FORWARD
84
+ when :stock_reload
85
+ artid = Wx::ART_REDO
86
+ end
87
+ if artid
88
+ icon = Wx::ArtProvider.get_bitmap(artid, Wx::ART_TOOLBAR, [ 16, 16 ])
89
+ else
90
+ icon = Wx::NULL_BITMAP
91
+ end
92
+
93
+ tb.add_tool(i, a.label, icon)
94
+ tb.enable_tool(i, a.sensitive)
95
+ a.signal_connect("property-changed") do |a, key, old, val|
96
+ # puts "property changed: #{key} => #{val}"
97
+ tb.enable_tool(i, val)
98
+ end
99
+ evt_tool(i) do |event|
100
+ # puts "Action[#{i}] triggered: #{a.key}"
101
+ a.call
102
+ end
103
+ @action_index[a.key] = i
104
+ end
105
+ @toolbar.realize
106
+
107
+ # puts "action_index: #{@action_index.inspect}"
108
+ end
109
+
110
+ def unmerge_actions(actions)
111
+ # puts "unmerge actions: #{actions.inspect}"
112
+ tb = toolbar
113
+ actions.each do |a|
114
+ idx = @action_index.delete(a.key)
115
+ # puts "unmerge action[#{idx}] => #{a.inspect}"
116
+ tb.delete_tool(idx) if idx
117
+ end
118
+ end
119
+
120
+ protected
121
+ def toolbar
122
+ if !@toolbar
123
+ @toolbar = create_tool_bar(
124
+ Wx::TB_HORIZONTAL |
125
+ Wx::TB_FLAT |
126
+ Wx::TB_TEXT)
127
+ end
128
+ @toolbar
45
129
  end
46
130
  end
47
131
  end
@@ -0,0 +1,79 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: grid_model.rb
21
+ # Created: Sat 31 Dec 2011 18:29:03 CET
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+ module Toolkit
28
+ module WxRuby
29
+
30
+ # This class provides an adapter between a
31
+ # RubyMVC::Models::TableModel instance and the
32
+ # Wx::GridTableBase API so that we can drive Wx::Grid
33
+ # instances using our model definitions.
34
+
35
+ class GridModel < Wx::GridTableBase
36
+ def initialize(model)
37
+ super()
38
+ @model = model
39
+ @labels = model.labels
40
+ @cols = {}
41
+ @labels.each_with_index do |l, i|
42
+ @cols[i] = l[:key]
43
+ end
44
+ end
45
+
46
+ def get_number_cols
47
+ @model.labels.size
48
+ end
49
+
50
+ def get_number_rows
51
+ @model.size
52
+ end
53
+
54
+ def get_value(row, col)
55
+ @model.value_for(row, get_key(col)).to_s
56
+ end
57
+
58
+ def is_empty_cell(row, col)
59
+ get_value(row, col).nil?
60
+ end
61
+
62
+ def get_attr(row, col, kind)
63
+ end
64
+
65
+ def get_row_label_value(row)
66
+ (row + 1).to_s
67
+ end
68
+
69
+ def get_col_label_value(col)
70
+ @labels[col][:label]
71
+ end
72
+
73
+ def get_key(col)
74
+ @cols[col]
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,117 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: dialog.rb
21
+ # Created: Sun 11 Dec 2011 14:37:40 CST
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+ module Toolkit
28
+ module WxRuby
29
+ class GridView < Wx::Grid
30
+ include SignalHandler
31
+ include Common
32
+ Toolkit::GridView.peer_class = self
33
+
34
+ def initialize(options = {})
35
+ puts "options: #{options.inspect}"
36
+ super(WxRuby.parent(options), options[:id] || -1)
37
+ if false == options[:show_row_labels]
38
+ set_row_label_size(0)
39
+ end
40
+ @selected_rows = []
41
+
42
+ evt_grid_cmd_cell_left_dclick(self.get_id()) do |e|
43
+ if @gm
44
+ col = @gm.get_key(e.get_col)
45
+ else
46
+ col = e.get_col
47
+ end
48
+ signal_emit("row-activated", self, @model, e.get_row, col)
49
+ end
50
+
51
+ evt_grid_range_select do |e|
52
+ puts "Event alt: #{e.alt_down}; ctrl: #{e.control_down}; brc: #{e.get_bottom_right_coords}; bottom: #{e.get_bottom_row}; left: #{e.get_left_col}; right: #{e.get_right_col}; tlc: #{e.get_top_left_coords}; top: #{e.get_top_row}; meta: #{e.meta_down}; selecting: #{e.selecting}; shift: #{e.shift_down}" if !e.selecting
53
+ next if !e.selecting
54
+
55
+ # FIXME: this should be a bit more clever in the
56
+ # future, but right now, we're only dealing with
57
+ # row selection
58
+ # puts "Event alt: #{e.alt_down}; ctrl: #{e.control_down}; brc: #{e.get_bottom_right_coords}; bottom: #{e.get_bottom_row}; left: #{e.get_left_col}; right: #{e.get_right_col}; tlc: #{e.get_top_left_coords}; top: #{e.get_top_row}; meta: #{e.meta_down}; selecting: #{e.selecting}; shift: #{e.shift_down}"
59
+ top = e.get_top_row
60
+ bottom = e.get_bottom_row
61
+ sel = []
62
+ top.upto(bottom) do |i|
63
+ sel << i
64
+ end
65
+ @selected_rows = sel
66
+ signal_emit("row-selection-changed", self, @model, sel)
67
+ end
68
+ end
69
+
70
+ def model=(model)
71
+ @model = model
72
+ @gm = GridModel.new(model)
73
+ set_table(@gm, Wx::Grid::GridSelectRows)
74
+
75
+ # FIXME: this is a bit cheezy and there should be a
76
+ # better way to communicate between the grid table
77
+ # and the view than this... Apparently, the wxRuby
78
+ # implementation doesn't expose the message
79
+ # dispatching required between GridTableBase and the
80
+ # Grid displaying it. Kinda defeats the point...
81
+
82
+ @model.signal_connect("rows-inserted") do |s, i, r|
83
+ puts "refresh rows-inserted"
84
+ @gm = GridModel.new(model)
85
+ set_table(@gm, Wx::Grid::GridSelectRows, false)
86
+ end
87
+ @model.signal_connect("rows-removed") do |s, i, r|
88
+ puts "refresh rows-removed"
89
+ @gm = GridModel.new(model)
90
+ set_table(@gm, Wx::Grid::GridSelectRows, false)
91
+ end
92
+ @model.signal_connect("row-changed") do |s, i, r|
93
+ puts "refresh row-changed"
94
+ @gm = GridModel.new(model)
95
+ set_table(@gm, Wx::Grid::GridSelectRows, false)
96
+ end
97
+ end
98
+
99
+ def set_table(table, flags, clear_selection = true)
100
+ super(table, flags)
101
+ @selected_rows.clear if clear_selection
102
+ auto_size_columns(false)
103
+ signal_emit("row-selection-changed", self, @model, @selected_rows)
104
+ end
105
+
106
+ def editable=(val)
107
+ enable_editing(val)
108
+ end
109
+
110
+ def selected_rows
111
+ # FIXME: I shouldn't have to maintain this list...
112
+ @selected_rows
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,58 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011-2012 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: messagebox.rb
21
+ # Created: Mon 9 Jan 2012 11:34:52 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+ module Toolkit
28
+ module WxRuby
29
+ class MessageBox < Wx::MessageDialog
30
+ include Common
31
+ Toolkit::MessageBox.peer_class = self
32
+
33
+ def initialize(message, options)
34
+ opts = {}
35
+ title = options[:title] || "Message"
36
+ if parent = options[:parent]
37
+ parent = parent.peer
38
+ end
39
+ case(options[:class])
40
+ when :error
41
+ flags = Wx::OK | Wx::ICON_ERROR
42
+ when :info
43
+ flags = Wx::OK | Wx::ICON_INFORMATION
44
+ when :question
45
+ flags = Wx::YES_NO | Wx::ICON_QUESTION
46
+ else
47
+ flags = Wx::OK | Wx::CANCEL
48
+ end
49
+ super(parent, message.to_s, title, flags)
50
+ end
51
+
52
+ def show
53
+ show_modal
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end