ruby_mvc 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ruby_mvc/ar_support.rb +84 -0
- data/lib/ruby_mvc/controllers.rb +1 -0
- data/lib/ruby_mvc/{views/ar_support.rb → controllers/action_provider.rb} +21 -7
- data/lib/ruby_mvc/controllers/app_controller.rb +10 -1
- data/lib/ruby_mvc/controllers/rails_controller.rb +1 -3
- data/lib/ruby_mvc/models/ar_row_model.rb +62 -0
- data/lib/ruby_mvc/models/ar_table_model.rb +4 -4
- data/lib/ruby_mvc/models/model.rb +8 -0
- data/lib/ruby_mvc/models/view_model_template.rb +35 -1
- data/lib/ruby_mvc/renderers/hyperlink_cell_renderer.rb +5 -3
- data/lib/ruby_mvc/toolkit/dialog.rb +8 -0
- data/lib/ruby_mvc/toolkit/peers/wxruby/dialog.rb +16 -1
- data/lib/ruby_mvc/toolkit/peers/wxruby/form_builder.rb +1 -1
- data/lib/ruby_mvc/toolkit/peers/wxruby/grid_view.rb +11 -5
- data/lib/ruby_mvc/toolkit/peers/wxruby/web_view.rb +1 -0
- data/lib/ruby_mvc/toolkit/signal_handler.rb +11 -1
- data/lib/ruby_mvc/toolkit/widget.rb +1 -1
- data/lib/ruby_mvc/views/ar_type_editor.rb +2 -1
- data/lib/ruby_mvc/views/ar_web_model_view.rb +137 -3
- data/lib/ruby_mvc/views/ar_web_type_list.rb +8 -1
- data/lib/ruby_mvc/views/browser_view.rb +4 -4
- data/lib/ruby_mvc/views/grid_table_view.rb +4 -4
- data/lib/ruby_mvc/views/view.rb +7 -10
- data/lib/ruby_mvc/views/web_content_table_view.rb +6 -1
- data/lib/ruby_mvc/views/web_model_view.rb +3 -1
- data/ruby_mvc.gemspec +1 -1
- metadata +54 -52
@@ -0,0 +1,84 @@
|
|
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: ar_support.rb
|
21
|
+
# Created: Mon 12 Dec 2011 06:49:00 CST
|
22
|
+
#
|
23
|
+
#####################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'active_record'
|
27
|
+
|
28
|
+
require 'ruby_mvc/models/ar_row_model'
|
29
|
+
require 'ruby_mvc/models/ar_table_model'
|
30
|
+
require 'ruby_mvc/views/ar_form_view'
|
31
|
+
require 'ruby_mvc/views/ar_type_editor'
|
32
|
+
require 'ruby_mvc/views/ar_web_type_list'
|
33
|
+
require 'ruby_mvc/views/ar_web_model_view'
|
34
|
+
|
35
|
+
module RubyMVC
|
36
|
+
|
37
|
+
class ActiveRecordModelRegistry < Hash
|
38
|
+
def model(etk, options = {})
|
39
|
+
key = etk
|
40
|
+
key = etk.to_s.to_sym if !etk.is_a? Symbol
|
41
|
+
if has_key? key
|
42
|
+
self[key]
|
43
|
+
else
|
44
|
+
self[key] = Models::ActiveRecordTableModel.new(etk, options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.model(*args, &block)
|
50
|
+
@ar_models ||= ActiveRecordModelRegistry.new
|
51
|
+
@ar_models.model(etk, options)
|
52
|
+
end
|
53
|
+
|
54
|
+
class ActiveRecordTemplateRegistry < Hash
|
55
|
+
def template(etk, title = nil, options = {}, &block)
|
56
|
+
if title.is_a? Hash
|
57
|
+
options = title
|
58
|
+
title = options[:title]
|
59
|
+
end
|
60
|
+
key = etk
|
61
|
+
key = etk.to_s.to_sym if !etk.is_a? Symbol
|
62
|
+
if block
|
63
|
+
obj = Models::ViewModelTemplate.new(options, &block)
|
64
|
+
obj.title = title || etk.to_s
|
65
|
+
self[key] = obj
|
66
|
+
else
|
67
|
+
self[key]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.template(*args, &block)
|
73
|
+
@ar_templates ||= ActiveRecordTemplateRegistry.new
|
74
|
+
@ar_templates.template(*args, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def template(*args, &block)
|
78
|
+
RubyMVC.template(*args, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def model(*args, &block)
|
82
|
+
RubyMVC.model(*args, &block)
|
83
|
+
end
|
84
|
+
end
|
data/lib/ruby_mvc/controllers.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#--
|
2
2
|
######################################################################
|
3
3
|
#
|
4
|
-
# Copyright 2011 Andrew S. Townley
|
4
|
+
# Copyright 2011-2012 Andrew S. Townley
|
5
5
|
#
|
6
6
|
# Permission to use, copy, modify, and disribute this software for
|
7
7
|
# any purpose with or without fee is hereby granted, provided that
|
@@ -17,13 +17,27 @@
|
|
17
17
|
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
18
18
|
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
19
19
|
#
|
20
|
-
# File:
|
21
|
-
# Created:
|
20
|
+
# File: action_provider.rb
|
21
|
+
# Created: Sat 14 Jan 2012 13:16:53 GMT
|
22
22
|
#
|
23
23
|
#####################################################################
|
24
24
|
#++
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
module RubyMVC
|
27
|
+
|
28
|
+
# This module is used to provide actions to toolkit widget
|
29
|
+
# implementations for appropriate rendering based on the
|
30
|
+
# widget type.
|
31
|
+
|
32
|
+
module ActionProvider
|
33
|
+
attr_reader :actions
|
34
|
+
|
35
|
+
def action(key, options = {}, &block)
|
36
|
+
@actions ||= ActionGroup.new
|
37
|
+
a = Action.new(key, options, &block)
|
38
|
+
@actions << a
|
39
|
+
a
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -42,7 +42,16 @@ module RubyMVC
|
|
42
42
|
def link_activated(sender, link)
|
43
43
|
puts "#link_activated(#{sender}, #{link})"
|
44
44
|
uri = URI.parse(link)
|
45
|
-
|
45
|
+
|
46
|
+
if uri.query
|
47
|
+
params = CGI.parse(uri.query)
|
48
|
+
params.each do |k, v|
|
49
|
+
if v && v.size == 1
|
50
|
+
params[k] = v.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
46
55
|
m = RubyMVC.method_name(uri.path).to_sym
|
47
56
|
if self.respond_to? m
|
48
57
|
self.send(m, sender, link, params)
|
@@ -0,0 +1,62 @@
|
|
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: ar_row_model.rb
|
21
|
+
# Created: Thu 12 Jan 2012 16:47:20 GMT
|
22
|
+
#
|
23
|
+
#####################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
module RubyMVC
|
27
|
+
module Models
|
28
|
+
|
29
|
+
# This class provides a Model adapter implementation for
|
30
|
+
# ActiveRecordBase class instances.
|
31
|
+
|
32
|
+
class ActiveRecordRowModel < Model
|
33
|
+
def initialize(row, options = {})
|
34
|
+
options[:data] = row
|
35
|
+
super(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def entity_type
|
39
|
+
@data.class
|
40
|
+
end
|
41
|
+
|
42
|
+
def keys
|
43
|
+
@data.attributes.keys.collect { |k| k.to_sym }
|
44
|
+
end
|
45
|
+
|
46
|
+
# This method provides information about inter-model links
|
47
|
+
# to provide built-in support for master-detail types of
|
48
|
+
# relationships between models.
|
49
|
+
|
50
|
+
def link_labels
|
51
|
+
# FIXME: should probably implement this intelligently to
|
52
|
+
# do some introspection magic
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
|
56
|
+
def size
|
57
|
+
@data.attributes.keys.size
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -33,7 +33,7 @@ module Models
|
|
33
33
|
# the rows matching a particular query.
|
34
34
|
|
35
35
|
class ActiveRecordTableModel < TableModel
|
36
|
-
attr_reader :keys
|
36
|
+
attr_reader :keys, :entity_type
|
37
37
|
|
38
38
|
def initialize(entity_type, options = {})
|
39
39
|
super()
|
@@ -118,18 +118,18 @@ module Models
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def size
|
121
|
-
puts "idx.size: #{@row_idx.size}"
|
121
|
+
# puts "idx.size: #{@row_idx.size}"
|
122
122
|
[_rows.count, @row_idx.size].max
|
123
123
|
end
|
124
124
|
|
125
125
|
protected
|
126
126
|
def _rows
|
127
|
-
if @filter
|
127
|
+
if @filter && !@rows
|
128
128
|
x = @entity_type.where(@filter)
|
129
129
|
else
|
130
130
|
x = @rows || @entity_type.find(:all)
|
131
131
|
end
|
132
|
-
puts "working with #{x.count} rows"
|
132
|
+
# puts "working with #{x.count} rows"
|
133
133
|
x
|
134
134
|
end
|
135
135
|
end
|
@@ -79,6 +79,14 @@ module Models
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
# This method provides information about inter-model links
|
83
|
+
# to provide built-in support for master-detail types of
|
84
|
+
# relationships between models.
|
85
|
+
|
86
|
+
def link_labels
|
87
|
+
{}
|
88
|
+
end
|
89
|
+
|
82
90
|
# This method is used to check whether a property key is
|
83
91
|
# editable or not
|
84
92
|
|
@@ -43,6 +43,8 @@ module Models
|
|
43
43
|
# may be accessed.
|
44
44
|
|
45
45
|
class ViewModelTemplate
|
46
|
+
include ActionProvider
|
47
|
+
|
46
48
|
attr_accessor :title
|
47
49
|
|
48
50
|
# When the ViewModelTemplate is initialized, it requires a set
|
@@ -52,8 +54,10 @@ module Models
|
|
52
54
|
def initialize(options = {}, &block)
|
53
55
|
@options = options
|
54
56
|
@labels = []
|
57
|
+
@link_labels = []
|
55
58
|
@options[:editable] ||= {}
|
56
59
|
@options[:properties] ||= []
|
60
|
+
@options[:links] ||= []
|
57
61
|
self.instance_eval(&block) if block
|
58
62
|
end
|
59
63
|
|
@@ -68,6 +72,10 @@ module Models
|
|
68
72
|
@labels
|
69
73
|
end
|
70
74
|
|
75
|
+
def link_labels
|
76
|
+
@link_labels
|
77
|
+
end
|
78
|
+
|
71
79
|
# Implement the Model#is_editable? method in terms of the
|
72
80
|
# template definition. If the template doesn't further
|
73
81
|
# restrict the behavior, the model's definition is used
|
@@ -94,7 +102,7 @@ module Models
|
|
94
102
|
# through the view.
|
95
103
|
|
96
104
|
def property(key, options = {})
|
97
|
-
puts "options: #{options.inspect}"
|
105
|
+
# puts "options: #{options.inspect}"
|
98
106
|
key = key.to_sym
|
99
107
|
|
100
108
|
if false == options[:show]
|
@@ -117,6 +125,32 @@ module Models
|
|
117
125
|
end
|
118
126
|
end
|
119
127
|
|
128
|
+
# This method is used to declare a linked property for the
|
129
|
+
# model and make it available to the view
|
130
|
+
|
131
|
+
def link(key, options = {})
|
132
|
+
key = key.to_sym
|
133
|
+
|
134
|
+
if false == options[:show]
|
135
|
+
show = false
|
136
|
+
else
|
137
|
+
show = true
|
138
|
+
end
|
139
|
+
|
140
|
+
editable(key, false) if false == options[:editable]
|
141
|
+
|
142
|
+
if show && !@options[:links].include?(key)
|
143
|
+
@options[:links] << key
|
144
|
+
l = options[:alias] || key.to_s.capitalize
|
145
|
+
@link_labels << options.merge({ :key => key, :label => l })
|
146
|
+
elsif !show
|
147
|
+
@options[:links].delete(key)
|
148
|
+
@link_labels.delete_if do |k|
|
149
|
+
k[:key] == key
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
120
154
|
# This method is used to apply the template to a specific,
|
121
155
|
# concrete model instance, creating a clone of the
|
122
156
|
# template in the process so that multiple different
|
@@ -33,11 +33,13 @@ module RubyMVC
|
|
33
33
|
|
34
34
|
def render(widget, row, col)
|
35
35
|
lk = col[:hl_label_key] || col[:key]
|
36
|
+
# puts "LK: #{lk.inspect}; row: #{row.inspect}"
|
36
37
|
text = row[lk]
|
37
|
-
|
38
|
+
href = col[:href]
|
39
|
+
val = row[col[:href_key] || col[:key]]
|
38
40
|
tagz {
|
39
|
-
td_ {
|
40
|
-
a_ text, :href => "#{
|
41
|
+
td_(:valign => "top") {
|
42
|
+
a_ text, :href => "#{href}#{val}"
|
41
43
|
}
|
42
44
|
}
|
43
45
|
end
|
@@ -27,6 +27,14 @@ module RubyMVC
|
|
27
27
|
module Toolkit
|
28
28
|
|
29
29
|
class Dialog < Widget
|
30
|
+
# this signal is triggered after the dialog has been
|
31
|
+
# processed modally and will return one of a range of
|
32
|
+
# response codes, depending on the type of the dialog.
|
33
|
+
#
|
34
|
+
# The standard response codes are :accept or :cancel
|
35
|
+
|
36
|
+
signal "response"
|
37
|
+
|
30
38
|
def add(w)
|
31
39
|
# FIXME: this is a cheezy way to do this...
|
32
40
|
if w.is_a? RubyMVC::Views::FormView
|
@@ -27,6 +27,7 @@ module RubyMVC
|
|
27
27
|
module Toolkit
|
28
28
|
module WxRuby
|
29
29
|
class Dialog < Wx::Dialog
|
30
|
+
include SignalHandler
|
30
31
|
include Common
|
31
32
|
Toolkit::Dialog.peer_class = self
|
32
33
|
|
@@ -64,12 +65,26 @@ module RubyMVC
|
|
64
65
|
self.sizer.fit(self)
|
65
66
|
end
|
66
67
|
|
68
|
+
def add_view(view)
|
69
|
+
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
70
|
+
view.peer.reparent(self)
|
71
|
+
sizer.add(view.peer, 1, Wx::EXPAND|Wx::ALL, 5)
|
72
|
+
sizer.add(@buttons, 0, Wx::ALIGN_RIGHT|Wx::ALL, 5)
|
73
|
+
self.sizer = sizer
|
74
|
+
layout
|
75
|
+
end
|
76
|
+
|
67
77
|
def show
|
68
78
|
self.centre
|
69
79
|
if @modal
|
70
|
-
|
80
|
+
case self.show_modal()
|
81
|
+
when Wx::ID_OK, Wx::ID_YES
|
71
82
|
@wxform.submit if @wxform
|
83
|
+
resp = :accept
|
84
|
+
else
|
85
|
+
resp = :cancel
|
72
86
|
end
|
87
|
+
signal_emit("response", self, resp)
|
73
88
|
else
|
74
89
|
sel.show()
|
75
90
|
end
|
@@ -51,7 +51,7 @@ module RubyMVC
|
|
51
51
|
def build(parent, form)
|
52
52
|
@form = form
|
53
53
|
form.layout do |key, label, val, editor, disabled|
|
54
|
-
puts "key: #{key}; disabled: #{disabled}"
|
54
|
+
# puts "key: #{key}; disabled: #{disabled}"
|
55
55
|
case(editor)
|
56
56
|
when :textarea
|
57
57
|
w = build_textfield(parent, label, val, true)
|
@@ -32,7 +32,7 @@ module RubyMVC
|
|
32
32
|
Toolkit::GridView.peer_class = self
|
33
33
|
|
34
34
|
def initialize(options = {})
|
35
|
-
puts "options: #{options.inspect}"
|
35
|
+
# puts "options: #{options.inspect}"
|
36
36
|
super(WxRuby.parent(options), options[:id] || -1)
|
37
37
|
if false == options[:show_row_labels]
|
38
38
|
set_row_label_size(0)
|
@@ -58,7 +58,13 @@ module RubyMVC
|
|
58
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
59
|
top = e.get_top_row
|
60
60
|
bottom = e.get_bottom_row
|
61
|
-
|
61
|
+
if e.meta_down || e.shift_down
|
62
|
+
# extending the selection
|
63
|
+
sel = @selected_rows.clone
|
64
|
+
else
|
65
|
+
# reset the selection
|
66
|
+
sel = []
|
67
|
+
end
|
62
68
|
top.upto(bottom) do |i|
|
63
69
|
sel << i
|
64
70
|
end
|
@@ -80,18 +86,18 @@ module RubyMVC
|
|
80
86
|
# Grid displaying it. Kinda defeats the point...
|
81
87
|
|
82
88
|
@model.signal_connect("rows-inserted") do |s, i, r|
|
83
|
-
puts "refresh rows-inserted"
|
89
|
+
# puts "refresh rows-inserted"
|
84
90
|
@gm = GridModel.new(model)
|
85
91
|
set_table(@gm, Wx::Grid::GridSelectRows, false)
|
86
92
|
end
|
87
93
|
@model.signal_connect("rows-removed") do |s, i, r|
|
88
|
-
puts "refresh rows-removed"
|
94
|
+
# puts "refresh rows-removed"
|
89
95
|
@gm = GridModel.new(model)
|
90
96
|
selected_rows.delete(i)
|
91
97
|
set_table(@gm, Wx::Grid::GridSelectRows, false)
|
92
98
|
end
|
93
99
|
@model.signal_connect("row-changed") do |s, i, r|
|
94
|
-
puts "refresh row-changed"
|
100
|
+
# puts "refresh row-changed"
|
95
101
|
@gm = GridModel.new(model)
|
96
102
|
set_table(@gm, Wx::Grid::GridSelectRows, false)
|
97
103
|
end
|
@@ -137,11 +137,21 @@ module Toolkit
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def signal_emit(signal, *args)
|
140
|
+
# FIXME: there's a few things wrong with this now that
|
141
|
+
# we've changed to support multiple signal handlers.
|
142
|
+
# Registration/deregistration should be cleaner, but
|
143
|
+
# then we'd be using an observer pattern vs the signal
|
144
|
+
# handler. Anyway, with multiple registered handlers,
|
145
|
+
# if the signal is vetoable, then it should throw a veto
|
146
|
+
# exception or something.
|
147
|
+
|
140
148
|
self.class.valid_signal! signal if self.class.respond_to? :signals
|
141
149
|
signals = (@signals ||= {})
|
150
|
+
rval = nil
|
142
151
|
(signals[signal] ||= []).each do |proc|
|
143
|
-
proc.call(*args) if !proc.nil?
|
152
|
+
(rval = proc.call(*args)) if !proc.nil?
|
144
153
|
end
|
154
|
+
rval
|
145
155
|
end
|
146
156
|
end
|
147
157
|
|
@@ -103,7 +103,7 @@ module RubyMVC
|
|
103
103
|
|
104
104
|
def connect_peer_signals
|
105
105
|
self.class.signals.each do |s, opts|
|
106
|
-
puts "connecting signal '#{peer}##{s}' to #{self}"
|
106
|
+
# puts "connecting signal '#{peer}##{s}' to #{self}"
|
107
107
|
peer.signal_connect(s) do |*args|
|
108
108
|
args[0] = self
|
109
109
|
signal_emit(s, *args)
|
@@ -35,7 +35,8 @@ module Views
|
|
35
35
|
super((@template ? @template.apply(@model) : @model), options)
|
36
36
|
signal_connect("row-edit") do |s, m, i, r|
|
37
37
|
app.dialog(:title => options[:editor_title], :parent => parent) do |dlg|
|
38
|
-
|
38
|
+
fm = (@template ? @template.apply(r) : Models::ActiveRecordRowModel.new(r))
|
39
|
+
form = FormView.new(fm, &block)
|
39
40
|
form.signal_connect("form-submit") do |form, d|
|
40
41
|
begin
|
41
42
|
r.save!
|
@@ -27,9 +27,24 @@ module RubyMVC
|
|
27
27
|
module Views
|
28
28
|
|
29
29
|
class ActiveRecordWebModelView < WebModelView
|
30
|
+
signal "add-child"
|
31
|
+
signal "add-child-link"
|
30
32
|
signal "row-edit"
|
31
33
|
signal "row-delete", :vetoable => true
|
32
34
|
|
35
|
+
# This signal is triggered when the view needs to render
|
36
|
+
# an action link for one of the linked models. Currently
|
37
|
+
# supported command keys are:
|
38
|
+
#
|
39
|
+
# - :link_edit - return a hash with the href to edit the
|
40
|
+
# link entries
|
41
|
+
#
|
42
|
+
# In each case, the arguments sent are the view, the
|
43
|
+
# command key, the model and the label entry being
|
44
|
+
# rendered.
|
45
|
+
|
46
|
+
signal "action-link"
|
47
|
+
|
33
48
|
def initialize(row, options = {})
|
34
49
|
super
|
35
50
|
|
@@ -40,18 +55,137 @@ module Views
|
|
40
55
|
# action(:delete, :label => "Delete", :icon => :stock_delete) do
|
41
56
|
# signal_emit("row-delete", self, row)
|
42
57
|
# end
|
58
|
+
|
59
|
+
begin
|
60
|
+
if @model.children
|
61
|
+
action(:add_child, :label => "Add Child", :icon => :stock_new) do
|
62
|
+
signal_emit("add-child", self, row)
|
63
|
+
end
|
64
|
+
|
65
|
+
action(:add_child_link, :label => "Add Child Link", :icon => :stock_new) do
|
66
|
+
signal_emit("add-child-link", self, row)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue NoMethodError
|
70
|
+
# we ignore this on purpose
|
71
|
+
end
|
43
72
|
end
|
44
73
|
|
45
74
|
def render
|
46
|
-
|
75
|
+
# FIXME: this isn't the way to properly test for
|
76
|
+
# ancestry, but we need it right now. Needs to have a
|
77
|
+
# review/revisit of the way things are nested. It's
|
78
|
+
# evolving a little organically at the moment
|
79
|
+
# (2012-01-12: ast)
|
80
|
+
|
47
81
|
tagz {
|
48
|
-
|
49
|
-
|
82
|
+
render_parent
|
83
|
+
super
|
84
|
+
render_links
|
50
85
|
}
|
51
86
|
end
|
52
87
|
|
53
88
|
protected
|
89
|
+
def render_parent
|
90
|
+
# FIXME: this is really screwed up and shouldn't really
|
91
|
+
# work this way
|
92
|
+
# puts "#render_ancestry"
|
93
|
+
begin
|
94
|
+
@model.reload
|
95
|
+
kidz = @model.subtree[1..-1]
|
96
|
+
# puts "Ancestors: " << kidz.inspect
|
97
|
+
tagz {
|
98
|
+
if cmd = signal_emit("action-link", self, :parent_edit, @model, {})
|
99
|
+
cmd2 = signal_emit("action-link", self, :unparent, @model, {})
|
100
|
+
h3_("Parent ") {
|
101
|
+
font_(:size => "2") {
|
102
|
+
a_ cmd.delete(:text), cmd
|
103
|
+
tagz.push " "
|
104
|
+
a_ cmd2.delete(:text), cmd2 if cmd2
|
105
|
+
}
|
106
|
+
}
|
107
|
+
end
|
108
|
+
if parent = @model.parent
|
109
|
+
# puts "parent: #{parent.inspect}"
|
110
|
+
et = parent.class
|
111
|
+
pm = Models::ActiveRecordTableModel.new(et, :rows => [ parent ])
|
112
|
+
if tmpl = RubyMVC.template(et)
|
113
|
+
pm = tmpl.apply(pm)
|
114
|
+
end
|
115
|
+
tagz.push WebContentTableView.new(pm).render
|
116
|
+
end
|
117
|
+
}
|
118
|
+
rescue NoMethodError => e
|
119
|
+
puts "warning: #{e}"
|
120
|
+
# puts e.backtrace
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
54
124
|
def render_links
|
125
|
+
# puts "#render_links"
|
126
|
+
|
127
|
+
tagz {
|
128
|
+
# render children first
|
129
|
+
render_children
|
130
|
+
|
131
|
+
return if @model.link_labels.size == 0
|
132
|
+
|
133
|
+
# render other links
|
134
|
+
@model.link_labels.each do |l|
|
135
|
+
links = @model.send(l[:key], true)
|
136
|
+
edits = []
|
137
|
+
cmds = [ :linked_edit ]
|
138
|
+
if l.has_key? :link_entity
|
139
|
+
cmds.insert(0, :add_link)
|
140
|
+
cmds.insert(0, :add_linked)
|
141
|
+
cmds << :link_edit
|
142
|
+
end
|
143
|
+
|
144
|
+
cmds.each do |cmd|
|
145
|
+
edits << signal_emit("action-link", self, cmd, @model, l)
|
146
|
+
end
|
147
|
+
let = l[:entity_type]
|
148
|
+
h3_("#{let} links (#{links.size})") {
|
149
|
+
if edits.size > 0
|
150
|
+
font_(:size => "2") {
|
151
|
+
edits.each do |cmd|
|
152
|
+
tagz.push " "
|
153
|
+
a_ cmd.delete(:text), cmd
|
154
|
+
end
|
155
|
+
}
|
156
|
+
end
|
157
|
+
}
|
158
|
+
if links.size > 0
|
159
|
+
lm = Models::ActiveRecordTableModel.new(let, :rows => links)
|
160
|
+
if tmpl = RubyMVC.template(let)
|
161
|
+
lm = tmpl.apply(lm)
|
162
|
+
end
|
163
|
+
tagz.push WebContentTableView.new(lm).render
|
164
|
+
end
|
165
|
+
end
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def render_children
|
170
|
+
begin
|
171
|
+
# puts "MODEL HAS CHILDREN? #{@model.has_children?}: #{@model.inspect}"
|
172
|
+
if @model.has_children?
|
173
|
+
kidz = @model.children
|
174
|
+
# puts "Children: " << kidz.inspect
|
175
|
+
et = kidz.first.class
|
176
|
+
km = Models::ActiveRecordTableModel.new(et, :rows => kidz)
|
177
|
+
if tmpl = RubyMVC.template(et)
|
178
|
+
km = tmpl.apply(km)
|
179
|
+
end
|
180
|
+
tagz {
|
181
|
+
h3_("Child #{et.to_s.pluralize}")
|
182
|
+
tagz.push WebContentTableView.new(km).render
|
183
|
+
}
|
184
|
+
end
|
185
|
+
rescue NoMethodError => e
|
186
|
+
puts "warning: #{e}"
|
187
|
+
# puts e.backtrace
|
188
|
+
end
|
55
189
|
end
|
56
190
|
end
|
57
191
|
|
@@ -27,6 +27,8 @@ module RubyMVC
|
|
27
27
|
module Views
|
28
28
|
|
29
29
|
class ActiveRecordWebTypeList < WebContentTableView
|
30
|
+
signal "add-row"
|
31
|
+
|
30
32
|
def initialize(entity_type, options = {}, &block)
|
31
33
|
@model = Models::ActiveRecordTableModel.new(entity_type, options)
|
32
34
|
if options.is_a? Hash
|
@@ -36,7 +38,12 @@ module Views
|
|
36
38
|
options = {}
|
37
39
|
end
|
38
40
|
super((@template ? @template.apply(@model) : @model), options)
|
39
|
-
|
41
|
+
|
42
|
+
action(:add, :label => "Add #{entity_type}", :icon => :stock_new) do
|
43
|
+
signal_emit("add-row", self, entity_type)
|
44
|
+
end
|
45
|
+
|
46
|
+
action(:edit, :label => "Edit", :icon => :stock_edit, &block)
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
@@ -85,7 +85,7 @@ module Views
|
|
85
85
|
widget.signal_connect("navigation-requested") do |s, h, t|
|
86
86
|
puts "BrowserView#navigation-requested: #{h}"
|
87
87
|
if (c = self.controller)
|
88
|
-
puts "forwarding to controller: #{c}"
|
88
|
+
# puts "forwarding to controller: #{c}"
|
89
89
|
c.link_activated(s, h)
|
90
90
|
end
|
91
91
|
end
|
@@ -115,7 +115,7 @@ module Views
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def reload
|
118
|
-
if location && v = location[:view]
|
118
|
+
if location && (v = location[:view])
|
119
119
|
load(v, location[:uri])
|
120
120
|
else
|
121
121
|
super
|
@@ -144,10 +144,10 @@ module Views
|
|
144
144
|
# place)
|
145
145
|
|
146
146
|
if (vc = view.controller) && vc != self.controller
|
147
|
-
puts "assigned new controller from WebContentView: #{vc}"
|
147
|
+
# puts "assigned new controller from WebContentView: #{vc}"
|
148
148
|
self.controller = vc
|
149
149
|
else
|
150
|
-
puts "no controller defined for #{view}"
|
150
|
+
# puts "no controller defined for #{view}"
|
151
151
|
end
|
152
152
|
|
153
153
|
# add any content actions
|
@@ -59,7 +59,7 @@ module Views
|
|
59
59
|
:enable => :select_multi,
|
60
60
|
:icon => :stock_delete
|
61
61
|
) do
|
62
|
-
puts "rows: #{widget.selected_rows.inspect}"
|
62
|
+
# puts "rows: #{widget.selected_rows.inspect}"
|
63
63
|
widget.selected_rows.reverse_each do |i|
|
64
64
|
model.remove_row(i)
|
65
65
|
end
|
@@ -76,7 +76,7 @@ module Views
|
|
76
76
|
end
|
77
77
|
|
78
78
|
widget.signal_connect("row-selection-changed") do |s, m, rows|
|
79
|
-
puts "selection changed: #{rows.inspect}"
|
79
|
+
# puts "selection changed: #{rows.inspect}"
|
80
80
|
@actions.each do |a|
|
81
81
|
a.selection(s, m, rows)
|
82
82
|
end
|
@@ -87,8 +87,8 @@ module Views
|
|
87
87
|
signal_emit("row-edit", self, model, r, row)
|
88
88
|
end
|
89
89
|
|
90
|
-
puts "self.class.signals: #{self.class.signals.keys.inspect}"
|
91
|
-
puts "widget.class.signals: #{widget.class.signals.keys.inspect}"
|
90
|
+
# puts "self.class.signals: #{self.class.signals.keys.inspect}"
|
91
|
+
# puts "widget.class.signals: #{widget.class.signals.keys.inspect}"
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
data/lib/ruby_mvc/views/view.rb
CHANGED
@@ -25,23 +25,20 @@
|
|
25
25
|
|
26
26
|
module RubyMVC
|
27
27
|
module Views
|
28
|
-
|
28
|
+
|
29
29
|
class View < RubyMVC::Toolkit::AbstractWidget
|
30
|
-
|
30
|
+
include ActionProvider
|
31
31
|
attr_accessor :controller
|
32
32
|
|
33
33
|
def initialize(options = {})
|
34
|
-
@actions = ActionGroup.new
|
35
34
|
@options = options
|
36
35
|
self.controller = options[:controller]
|
37
36
|
(options[:actions] || []).each { |a| @actions << a }
|
38
37
|
end
|
39
38
|
|
40
39
|
protected
|
41
|
-
def
|
42
|
-
|
43
|
-
@actions << a
|
44
|
-
a
|
40
|
+
def options
|
41
|
+
@options
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
@@ -73,7 +70,7 @@ module RubyMVC
|
|
73
70
|
# widgets.
|
74
71
|
|
75
72
|
def widget(*args, &block)
|
76
|
-
puts "Set widget for #{self}: #{args.inspect}"
|
73
|
+
# puts "Set widget for #{self}: #{args.inspect}"
|
77
74
|
@widget_def = { :args => args, :block => block }
|
78
75
|
end
|
79
76
|
end
|
@@ -96,11 +93,11 @@ module RubyMVC
|
|
96
93
|
# appropriately manage signal registration
|
97
94
|
|
98
95
|
def signal_connect(signal, &b)
|
99
|
-
puts "Widget class: #{@widget.class}"
|
96
|
+
# puts "Widget class: #{@widget.class}"
|
100
97
|
if @widget.class.valid_signal? signal
|
101
98
|
@widget.signal_connect(signal, &b)
|
102
99
|
else
|
103
|
-
puts "super"
|
100
|
+
# puts "super"
|
104
101
|
super
|
105
102
|
end
|
106
103
|
end
|
@@ -31,8 +31,13 @@ module Views
|
|
31
31
|
|
32
32
|
class WebContentTableView < WebContentView
|
33
33
|
def render
|
34
|
+
html = ""
|
35
|
+
if t = @options[:title]
|
36
|
+
html << "<h2>" << t << "</h2>"
|
37
|
+
end
|
38
|
+
|
34
39
|
r = @options[:renderer] || Renderers::Html4TableModelRenderer
|
35
|
-
r.render(@model, @options)
|
40
|
+
html << r.render(@model, @options)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
@@ -30,6 +30,7 @@ module Views
|
|
30
30
|
include Tagz
|
31
31
|
|
32
32
|
def initialize(row, options = {})
|
33
|
+
@model_type = row.class
|
33
34
|
if options.is_a? Hash
|
34
35
|
@template = options[:template]
|
35
36
|
else
|
@@ -46,7 +47,8 @@ module Views
|
|
46
47
|
protected
|
47
48
|
def render_properties
|
48
49
|
tagz {
|
49
|
-
|
50
|
+
h2_(@model_type)
|
51
|
+
table_(:border => 1, :cellspacing => 0) {
|
50
52
|
@model.labels.each do |l|
|
51
53
|
k = l[:key]
|
52
54
|
tr_ {
|
data/ruby_mvc.gemspec
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ruby_mvc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrew S. Townley
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-14 00:00:00 Z
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description: A simple, cross-platform MVC framework for Ruby
|
@@ -22,75 +22,77 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
- lib/ruby_mvc/
|
26
|
-
- lib/ruby_mvc/
|
27
|
-
- lib/ruby_mvc/
|
28
|
-
- lib/ruby_mvc/
|
29
|
-
- lib/ruby_mvc/
|
30
|
-
- lib/ruby_mvc/
|
31
|
-
- lib/ruby_mvc/
|
32
|
-
- lib/ruby_mvc/
|
33
|
-
- lib/ruby_mvc/
|
34
|
-
- lib/ruby_mvc/
|
35
|
-
- lib/ruby_mvc/
|
36
|
-
- lib/ruby_mvc/
|
25
|
+
- lib/ruby_mvc/views/ar_type_editor.rb
|
26
|
+
- lib/ruby_mvc/views/ar_web_type_list.rb
|
27
|
+
- lib/ruby_mvc/views/web_content_table_view.rb
|
28
|
+
- lib/ruby_mvc/views/ar_web_model_view.rb
|
29
|
+
- lib/ruby_mvc/views/web_content_view.rb
|
30
|
+
- lib/ruby_mvc/views/table_view.rb
|
31
|
+
- lib/ruby_mvc/views/form_view.rb
|
32
|
+
- lib/ruby_mvc/views/view.rb
|
33
|
+
- lib/ruby_mvc/views/browser_view.rb
|
34
|
+
- lib/ruby_mvc/views/web_model_view.rb
|
35
|
+
- lib/ruby_mvc/views/grid_table_view.rb
|
36
|
+
- lib/ruby_mvc/views/ar_form_view.rb
|
37
|
+
- lib/ruby_mvc/wx.rb
|
38
|
+
- lib/ruby_mvc/toolkit.rb
|
37
39
|
- lib/ruby_mvc/models.rb
|
38
|
-
- lib/ruby_mvc/module.rb
|
39
|
-
- lib/ruby_mvc/renderers/html4_table_model_renderer.rb
|
40
|
-
- lib/ruby_mvc/renderers/hyperlink_cell_renderer.rb
|
41
|
-
- lib/ruby_mvc/renderers.rb
|
42
|
-
- lib/ruby_mvc/toolkit/app.rb
|
43
|
-
- lib/ruby_mvc/toolkit/browser_history.rb
|
44
|
-
- lib/ruby_mvc/toolkit/dialog.rb
|
45
|
-
- lib/ruby_mvc/toolkit/frame.rb
|
46
|
-
- lib/ruby_mvc/toolkit/grid_view.rb
|
47
|
-
- lib/ruby_mvc/toolkit/messagebox.rb
|
48
|
-
- lib/ruby_mvc/toolkit/peers/wxruby/app.rb
|
49
|
-
- lib/ruby_mvc/toolkit/peers/wxruby/box_layout.rb
|
50
40
|
- lib/ruby_mvc/toolkit/peers/wxruby/common.rb
|
41
|
+
- lib/ruby_mvc/toolkit/peers/wxruby/box_layout.rb
|
42
|
+
- lib/ruby_mvc/toolkit/peers/wxruby/grid_view.rb
|
51
43
|
- lib/ruby_mvc/toolkit/peers/wxruby/dialog.rb
|
44
|
+
- lib/ruby_mvc/toolkit/peers/wxruby/app.rb
|
52
45
|
- lib/ruby_mvc/toolkit/peers/wxruby/form_builder.rb
|
53
46
|
- lib/ruby_mvc/toolkit/peers/wxruby/frame.rb
|
54
|
-
- lib/ruby_mvc/toolkit/peers/wxruby/grid_model.rb
|
55
|
-
- lib/ruby_mvc/toolkit/peers/wxruby/grid_view.rb
|
56
|
-
- lib/ruby_mvc/toolkit/peers/wxruby/messagebox.rb
|
57
47
|
- lib/ruby_mvc/toolkit/peers/wxruby/web_view.rb
|
48
|
+
- lib/ruby_mvc/toolkit/peers/wxruby/messagebox.rb
|
49
|
+
- lib/ruby_mvc/toolkit/peers/wxruby/grid_model.rb
|
58
50
|
- lib/ruby_mvc/toolkit/peers/wxruby.rb
|
59
|
-
- lib/ruby_mvc/toolkit/
|
51
|
+
- lib/ruby_mvc/toolkit/grid_view.rb
|
52
|
+
- lib/ruby_mvc/toolkit/dialog.rb
|
53
|
+
- lib/ruby_mvc/toolkit/app.rb
|
60
54
|
- lib/ruby_mvc/toolkit/signal_handler.rb
|
55
|
+
- lib/ruby_mvc/toolkit/frame.rb
|
56
|
+
- lib/ruby_mvc/toolkit/browser_history.rb
|
61
57
|
- lib/ruby_mvc/toolkit/web_view.rb
|
58
|
+
- lib/ruby_mvc/toolkit/messagebox.rb
|
62
59
|
- lib/ruby_mvc/toolkit/widget.rb
|
63
|
-
- lib/ruby_mvc/toolkit.rb
|
64
|
-
- lib/ruby_mvc/
|
65
|
-
- lib/ruby_mvc/
|
66
|
-
- lib/ruby_mvc/
|
67
|
-
- lib/ruby_mvc/
|
68
|
-
- lib/ruby_mvc/
|
69
|
-
- lib/ruby_mvc/
|
70
|
-
- lib/ruby_mvc/
|
71
|
-
- lib/ruby_mvc/
|
72
|
-
- lib/ruby_mvc/
|
73
|
-
- lib/ruby_mvc/
|
74
|
-
- lib/ruby_mvc/
|
75
|
-
- lib/ruby_mvc/
|
76
|
-
- lib/ruby_mvc/
|
60
|
+
- lib/ruby_mvc/toolkit/property_change_notifier.rb
|
61
|
+
- lib/ruby_mvc/controllers/app_controller.rb
|
62
|
+
- lib/ruby_mvc/controllers/action_provider.rb
|
63
|
+
- lib/ruby_mvc/controllers/action_group.rb
|
64
|
+
- lib/ruby_mvc/controllers/action.rb
|
65
|
+
- lib/ruby_mvc/controllers/rails_controller.rb
|
66
|
+
- lib/ruby_mvc/models/view_model_template.rb
|
67
|
+
- lib/ruby_mvc/models/table_model.rb
|
68
|
+
- lib/ruby_mvc/models/keyed_array_table_model.rb
|
69
|
+
- lib/ruby_mvc/models/model.rb
|
70
|
+
- lib/ruby_mvc/models/ar_row_model.rb
|
71
|
+
- lib/ruby_mvc/models/ar_table_model.rb
|
72
|
+
- lib/ruby_mvc/models/array_table_model.rb
|
73
|
+
- lib/ruby_mvc/module.rb
|
74
|
+
- lib/ruby_mvc/ar_support.rb
|
75
|
+
- lib/ruby_mvc/controllers.rb
|
76
|
+
- lib/ruby_mvc/renderers/html4_table_model_renderer.rb
|
77
|
+
- lib/ruby_mvc/renderers/hyperlink_cell_renderer.rb
|
78
|
+
- lib/ruby_mvc/application.rb
|
77
79
|
- lib/ruby_mvc/views.rb
|
78
|
-
- lib/ruby_mvc/
|
80
|
+
- lib/ruby_mvc/renderers.rb
|
79
81
|
- lib/ruby_mvc.rb
|
80
|
-
- sample/browser_view.rb
|
81
|
-
- sample/form.rb
|
82
82
|
- sample/form2.rb
|
83
|
-
- sample/
|
84
|
-
- sample/grid_table_view.rb
|
83
|
+
- sample/test2.html
|
85
84
|
- sample/grid_view.rb
|
86
85
|
- sample/grid_view2.rb
|
86
|
+
- sample/form.rb
|
87
|
+
- sample/frame.rb
|
88
|
+
- sample/web_view.rb
|
87
89
|
- sample/mvc.rb
|
90
|
+
- sample/browser_view.rb
|
88
91
|
- sample/test.html
|
89
|
-
- sample/
|
90
|
-
-
|
92
|
+
- sample/grid_table_view.rb
|
93
|
+
- test/unit/models/test_model.rb
|
91
94
|
- test/unit/models/test_array_table_model.rb
|
92
95
|
- test/unit/models/test_keyed_array_table_model.rb
|
93
|
-
- test/unit/models/test_model.rb
|
94
96
|
- test/unit/test_array_table_model.rb
|
95
97
|
- LICENSE
|
96
98
|
- README.md
|