ironnails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/Rakefile +21 -0
  2. data/VERSION +1 -0
  3. data/init.rb +1 -0
  4. data/ironnails.gemspec +96 -0
  5. data/lib/iron_nails.rb +1 -0
  6. data/lib/ironnails/bin/IronNails.Library.dll +0 -0
  7. data/lib/ironnails/bin/IronRuby.Libraries.Yaml.dll +0 -0
  8. data/lib/ironnails/bin/IronRuby.Libraries.dll +0 -0
  9. data/lib/ironnails/bin/IronRuby.dll +0 -0
  10. data/lib/ironnails/bin/Microsoft.Dynamic.dll +0 -0
  11. data/lib/ironnails/bin/Microsoft.Scripting.Core.dll +0 -0
  12. data/lib/ironnails/bin/Microsoft.Scripting.ExtensionAttribute.dll +0 -0
  13. data/lib/ironnails/bin/Microsoft.Scripting.dll +0 -0
  14. data/lib/ironnails/config/configuration.rb +141 -0
  15. data/lib/ironnails/config/initializer.rb +144 -0
  16. data/lib/ironnails/controller/base.rb +135 -0
  17. data/lib/ironnails/controller/view_operations.rb +101 -0
  18. data/lib/ironnails/controller.rb +2 -0
  19. data/lib/ironnails/core_ext/array.rb +15 -0
  20. data/lib/ironnails/core_ext/class/attribute_accessors.rb +57 -0
  21. data/lib/ironnails/core_ext/class.rb +8 -0
  22. data/lib/ironnails/core_ext/fixnum.rb +22 -0
  23. data/lib/ironnails/core_ext/hash.rb +32 -0
  24. data/lib/ironnails/core_ext/kernel.rb +26 -0
  25. data/lib/ironnails/core_ext/string.rb +58 -0
  26. data/lib/ironnails/core_ext/symbol.rb +78 -0
  27. data/lib/ironnails/core_ext/system/net/web_request.rb +110 -0
  28. data/lib/ironnails/core_ext/system/security/secure_string.rb +18 -0
  29. data/lib/ironnails/core_ext/system/windows/markup/xaml_reader.rb +6 -0
  30. data/lib/ironnails/core_ext/system/windows/ui_element.rb +17 -0
  31. data/lib/ironnails/core_ext/time.rb +28 -0
  32. data/lib/ironnails/core_ext.rb +12 -0
  33. data/lib/ironnails/errors.rb +19 -0
  34. data/lib/ironnails/iron_xml.rb +83 -0
  35. data/lib/ironnails/logger.rb +4 -0
  36. data/lib/ironnails/logging/buffered_logger.rb +137 -0
  37. data/lib/ironnails/logging/class_logger.rb +29 -0
  38. data/lib/ironnails/models/base.rb +16 -0
  39. data/lib/ironnails/models/bindable_collection.rb +15 -0
  40. data/lib/ironnails/models/model_mixin.rb +69 -0
  41. data/lib/ironnails/models.rb +3 -0
  42. data/lib/ironnails/nails_engine.rb +398 -0
  43. data/lib/ironnails/observable.rb +117 -0
  44. data/lib/ironnails/security/secure_string.rb +61 -0
  45. data/lib/ironnails/version.rb +11 -0
  46. data/lib/ironnails/view/collections.rb +117 -0
  47. data/lib/ironnails/view/commands/add_sub_view_command.rb +33 -0
  48. data/lib/ironnails/view/commands/behavior_command.rb +29 -0
  49. data/lib/ironnails/view/commands/command.rb +208 -0
  50. data/lib/ironnails/view/commands/event_command.rb +32 -0
  51. data/lib/ironnails/view/commands/timed_command.rb +40 -0
  52. data/lib/ironnails/view/commands.rb +5 -0
  53. data/lib/ironnails/view/view.rb +190 -0
  54. data/lib/ironnails/view/view_model.rb +45 -0
  55. data/lib/ironnails/view/xaml_proxy.rb +226 -0
  56. data/lib/ironnails/view.rb +5 -0
  57. data/lib/ironnails/wpf.rb +113 -0
  58. data/lib/ironnails/wpf_application.rb +30 -0
  59. data/lib/ironnails.rb +68 -0
  60. metadata +133 -0
@@ -0,0 +1,137 @@
1
+ # Inspired by the Buffered Logger from Ezra (Merb)
2
+ # Taken from active_support
3
+ module IronNails
4
+
5
+ module Logging
6
+
7
+
8
+ class BufferedLogger
9
+ module Severity
10
+ DEBUG = 0
11
+ INFO = 1
12
+ WARN = 2
13
+ ERROR = 3
14
+ FATAL = 4
15
+ UNKNOWN = 5
16
+ end
17
+ include Severity
18
+
19
+ MAX_BUFFER_SIZE = 1000
20
+
21
+ # Set to false to disable the silencer
22
+ cattr_accessor :silencer
23
+ self.silencer = true
24
+
25
+ # Silences the logger for the duration of the block.
26
+ def silence(temporary_level = ERROR)
27
+ if silencer
28
+ begin
29
+ old_logger_level, self.level = level, temporary_level
30
+ yield self
31
+ ensure
32
+ self.level = old_logger_level
33
+ end
34
+ else
35
+ yield self
36
+ end
37
+ end
38
+
39
+ attr_accessor :level
40
+ attr_reader :auto_flushing
41
+ attr_reader :buffer
42
+
43
+ def initialize(log, level = DEBUG)
44
+ @level = level
45
+ @buffer = []
46
+ @auto_flushing = 1
47
+ @no_block = false
48
+
49
+ if log.respond_to?(:write)
50
+ @log = log
51
+ elsif File.exist?(log)
52
+ @log = File.open(log, (File::WRONLY | File::APPEND))
53
+ @log.sync = true
54
+ else
55
+ FileUtils.mkdir_p(File.dirname(log))
56
+ @log = File.open(log, (File::WRONLY | File::APPEND | File::CREAT))
57
+ @log.sync = true
58
+ @log.write("# Logfile created on %s" % [Time.now.to_s])
59
+ end
60
+ end
61
+
62
+ def set_non_blocking_io
63
+ if !RUBY_PLATFORM.match(/java|mswin/) && !(@log == STDOUT) && @log.respond_to?(:write_nonblock)
64
+ @no_block = true
65
+ end
66
+ end
67
+
68
+ def add(severity, message = nil, progname = nil, &block)
69
+ from_framework = progname == IRONNAILS_FRAMEWORKNAME
70
+ fw_logging = defined?(IronNails::Logging::FRAMEWORK_LOGGING) && IronNails::Logging::FRAMEWORK_LOGGING
71
+ return if @level > severity || (from_framework && !fw_logging )
72
+ message = (message || (block && block.call) || progname).to_s
73
+ puts message if defined?(IronNails::Logging::CONSOLE_LOGGING) && IronNails::Logging::CONSOLE_LOGGING
74
+ # If a newline is necessary then create a new message ending with a newline.
75
+ # Ensures that the original message is not mutated.
76
+ message = "IRONNAILS: #{Severity.constants[severity]}: #{message}" if from_framework
77
+ message = "[#{Time.now.strftime("%d/%m/%Y %H:%M:%S.#{Time.now.usec}")}] #{message}\n" unless message[-1] == ?\n
78
+ buffer << message
79
+ auto_flush
80
+ message
81
+ end
82
+
83
+ for severity in Severity.constants
84
+ class_eval <<-EOT, __FILE__, __LINE__
85
+ def #{severity.downcase}(message = nil, progname = nil, &block)
86
+ add(#{severity}, message, progname, &block)
87
+ end
88
+
89
+ def #{severity.downcase}?
90
+ #{severity} >= @level
91
+ end
92
+ EOT
93
+ end
94
+
95
+ # Set the auto-flush period. Set to true to flush after every log message,
96
+ # to an integer to flush every N messages, or to false, nil, or zero to
97
+ # never auto-flush. If you turn auto-flushing off, be sure to regularly
98
+ # flush the log yourself -- it will eat up memory until you do.
99
+ def auto_flushing=(period)
100
+ @auto_flushing =
101
+ case period
102
+ when true;
103
+ 1
104
+ when false, nil, 0;
105
+ MAX_BUFFER_SIZE
106
+ when Integer;
107
+ period
108
+ else
109
+ raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
110
+ end
111
+ end
112
+
113
+ def flush
114
+ unless buffer.empty?
115
+ if @no_block
116
+ @log.write_nonblock(buffer.slice!(0..-1).join)
117
+ else
118
+ @log.write(buffer.slice!(0..-1).join)
119
+ end
120
+ end
121
+ end
122
+
123
+ def close
124
+ flush
125
+ @log.close if @log.respond_to?(:close)
126
+ @log = nil
127
+ end
128
+
129
+ protected
130
+ def auto_flush
131
+ flush if buffer.size >= @auto_flushing
132
+ end
133
+ end
134
+
135
+ end
136
+
137
+ end
@@ -0,0 +1,29 @@
1
+ module IronNails
2
+
3
+ module Logging
4
+
5
+ module ClassLogger
6
+
7
+ # provides access for the logger we are using
8
+ # you can override this logger as long as it responds to
9
+ # the methods: debug, info, warn, error, fatal
10
+ def logger
11
+ IRONNAILS_DEFAULT_LOGGER
12
+ end
13
+
14
+ # Ensures that a message is logged when the execution of
15
+ # the specified block throws an error. It will then re-raise the error.
16
+ def log_on_error
17
+ begin
18
+ yield if block_given?
19
+ rescue Exception => e
20
+ logger.error "IronNails Error: #{e}"
21
+ raise e
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ module IronNails
2
+
3
+ module Models
4
+
5
+
6
+
7
+
8
+ class Base
9
+
10
+ include IronNails::Models::ModelMixin
11
+
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ module IronNails
2
+
3
+ module Models
4
+
5
+ class BindableCollection < System::Collections::ObjectModel::ObservableCollection.of(System::Object)
6
+
7
+ def initialize(*list)
8
+ list.map { |item| self.add item }
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,69 @@
1
+ module IronNails
2
+
3
+ module Models
4
+
5
+ module ModelMixin
6
+
7
+ include IronNails::Logging::ClassLogger
8
+
9
+ end
10
+
11
+ module Databinding
12
+
13
+ module ClassMethods
14
+
15
+ # defines a write-only attribute on an object
16
+ # this would map to a property setter in different languages
17
+ def attr_writer(*names)
18
+ names.each do |nm|
19
+ mn = nm
20
+ self.send :define_method, "#{nm}=".to_sym do |arg|
21
+ __vr__ = instance_variable_get :"@#{mn}"
22
+ return __vr__ if __vr__ == arg
23
+ instance_variable_set :"@#{mn}", arg
24
+ raise_property_changed mn
25
+ end
26
+ end
27
+ end
28
+
29
+ # defines a read/write attribute on an object.
30
+ # this would map to a property with a getter and a setter in different langauages
31
+ def attr_accessor(*names)
32
+ attr_reader *names
33
+ attr_writer *names
34
+ end
35
+
36
+
37
+ end
38
+
39
+ # extend the class with the class methods defined in this module
40
+ def self.included(base)
41
+ base.send :include, System::ComponentModel::INotifyPropertyChanged unless base.ancestors.include? System::ComponentModel::INotifyPropertyChanged
42
+ base.extend ClassMethods
43
+ end
44
+
45
+ def add_PropertyChanged(handler=nil)
46
+ @__handlers__ ||= []
47
+ @__handlers__ << handler
48
+ end
49
+
50
+ def remove_PropertyChanged(handler=nil)
51
+ @__handlers__ ||= []
52
+ @__handlers__.delete handler
53
+ end
54
+
55
+ private
56
+ def raise_property_changed(name)
57
+ return unless @__handlers__
58
+ @__handlers__.each do |ev|
59
+ ev.invoke self, System::ComponentModel::PropertyChangedEventArgs.new(name) if ev.respond_to? :invoke
60
+ ev.call self, System::ComponentModel::PropertyChangedEventArgs.new(name) if ev.respond_to? :call
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,3 @@
1
+ require File.dirname(__FILE__) + '/models/model_mixin'
2
+ require File.dirname(__FILE__) + '/models/bindable_collection'
3
+ require File.dirname(__FILE__) + '/models/base'
@@ -0,0 +1,398 @@
1
+ require File.dirname(__FILE__) + "/view/collections"
2
+ require File.dirname(__FILE__) + "/view/view_model"
3
+ require File.dirname(__FILE__) + "/view/xaml_proxy"
4
+ require File.dirname(__FILE__) + "/observable"
5
+
6
+ module IronNails
7
+
8
+ module Core
9
+
10
+ module ViewOperations
11
+
12
+ def init_view_operations
13
+ end
14
+
15
+ def build_view(options)
16
+ logger.debug "View to load: #{options[:name]}", IRONNAILS_FRAMEWORKNAME
17
+ vw = IronNails::View::View.new(options)
18
+ #vw.add_observer(:loaded) { |sender| set_data_context_for(sender) }
19
+ vw
20
+ end
21
+
22
+ def register_child_view(options)
23
+ vw = registry.view_for options[:controller]
24
+ vw.add_child(options)
25
+ end
26
+
27
+ def register_view_for(controller)
28
+ vw = build_view(:name => controller.view_name.to_sym, :controller => controller.controller_name)
29
+ vw.add_observer(:configuring) { |sender| configure_view(sender) }
30
+ registry.register_view_for controller, vw
31
+ end
32
+
33
+ def on_view(controller, name = nil, &b)
34
+ find_view(controller, name).on_proxy(&b) #unless vw.nil?
35
+ end
36
+
37
+ def from_view(controller, name, target, method)
38
+ find_view(controller, name).get_property(target, method)
39
+ end
40
+
41
+ def to_update_ui_after(controller, options, &b)
42
+ # if options.is_a? Hash
43
+ # klass = options[:class]||BindableCollection
44
+ # request = options[:request]
45
+ # else
46
+ # klass = BindableCollection
47
+ # request = options
48
+ # end
49
+ # cb = System::Threading::WaitCallback.new do
50
+ # begin
51
+ # registry.view_for(controller).dispatcher.begin_invoke(DispatcherPriority.normal, Action.of(klass).new(&b), request.call)
52
+ # rescue WebException => e
53
+ # MessageBox.Show("There was a problem logging in to Twitter. #{e.message}");
54
+ # rescue RequestLimitException => e
55
+ # MessageBox.Show(e.message)
56
+ # rescue SecurityException => e
57
+ # MessageBox.Show("Incorrect username or password. Please try again");
58
+ # end
59
+ # end
60
+ # System::Threading::ThreadPool.queue_user_work_item cb
61
+ cb = nil
62
+ cb = options[:callback] unless options[:callback].nil?
63
+ options[:callback] = lambda do |vw|
64
+ b.call
65
+ refresh_view(vw)
66
+ end
67
+ find_view(controller, name).to_update_ui_after(options, &b)
68
+ end
69
+
70
+ def on_ui_thread(controller, options=nil, &b)
71
+ if options.is_a? Hash
72
+ data = options[:data]
73
+ klass = options[:class] || data.class
74
+ else
75
+ unless options.nil?
76
+ klass = options.class
77
+ data = options
78
+ end
79
+ end
80
+ b.call
81
+ #registry.view_for(controller).dispatcher.begin_invoke(DispatcherPriority.normal, options.nil? ? Action.new(&b) : Action.of(klass).new(&b), data)
82
+ end
83
+
84
+ alias_method :on_ui_thread_with, :on_ui_thread
85
+
86
+ def play_storyboard(controller, name, storyboard)
87
+ logger.debug "finding controller #{controller.controller_name} and view #{name} to play #{storyboard}"
88
+ vw = find_view(controller, name)
89
+ find_view(controller, name).play_storyboard(storyboard)
90
+ end
91
+
92
+ def stop_storyboard(controller, view_name, storyboard)
93
+ find_view(controller, name).stop_storyboard(storyboard)
94
+ end
95
+
96
+ def find_view(controller, name)
97
+ registry.view_for(controller).find(name)
98
+ end
99
+ end
100
+
101
+ module ViewModelObjectOperations
102
+
103
+ # gets or sets the models that wil be used in the view to bind to
104
+ attr_accessor :model_queue
105
+
106
+ def init_object_operations
107
+ @model_queue = ModelCollection.new
108
+ end
109
+
110
+ # flags the view model as in need of wiring up and
111
+ # sets the model collection
112
+ def model_queue=(value)
113
+ unless model_queue == value
114
+ @configured = false
115
+ @model_queue = value
116
+ end
117
+ end
118
+
119
+ # adds a new model to the queue for synchronisation to the view
120
+ def add_model_to_queue_on(model)
121
+ if model.respond_to?(:has_model?)
122
+ model.each do |m|
123
+ enqueue_model(m)
124
+ end
125
+ elsif model.is_a?(Hash)
126
+ enqueue_model(model)
127
+ end
128
+ end
129
+
130
+ alias_method :add_models_to_queue_on, :add_model_to_queue_on
131
+
132
+ private
133
+
134
+ def enqueue_model(model)
135
+ key = model.keys[0]
136
+ unless model_queue.has_model?(model) && model_queue[key] == model[key]
137
+ model_queue.add_model model
138
+ @configured = false
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ module ViewModelCommandOperations
145
+
146
+ # gets or sets the command_queue to respond to user actions in the view.
147
+ attr_accessor :command_queue
148
+
149
+ def init_command_operations
150
+ @command_queue = CommandCollection.new
151
+ end
152
+
153
+ # flags the view model as in need of wiring up and
154
+ # sets the command collection
155
+ def command_queue=(value)
156
+ unless command_queue == value
157
+ @configured = false
158
+ @command_queue = value
159
+ end
160
+ end
161
+
162
+ # adds a command or a command collection to the queue
163
+ def add_command_to_queue(cmd)
164
+
165
+ if cmd.respond_to?(:has_command?)
166
+ cmd.each do |c|
167
+ enqueue_command(c)
168
+ end
169
+ elsif cmd.respond_to?(:execute) && cmd.respond_to?(:refresh_view) # define some sort of contract
170
+ enqueue_command(cmd)
171
+ end
172
+ end
173
+
174
+ alias_method :add_commands_to_queue, :add_command_to_queue
175
+
176
+ private
177
+
178
+ def enqueue_command(cmd)
179
+ if !command_queue.has_command?(cmd) || cmd.changed?
180
+ cmd.add_observer(:refreshing_view) do |sender|
181
+ refresh_view(registry.view_for(sender.controller))
182
+ end
183
+ command_queue << cmd
184
+ @configured = false
185
+ end
186
+ end
187
+
188
+ end
189
+
190
+ module ViewModelOperations
191
+
192
+ # gets the view model instance to manipulate with this builder
193
+ attr_accessor :view_models
194
+
195
+ include ViewModelObjectOperations
196
+ include ViewModelCommandOperations
197
+
198
+ def init_viewmodel_operations
199
+ init_object_operations
200
+ init_command_operations
201
+ @view_models = {}
202
+ end
203
+
204
+ def register_viewmodel_for(controller)
205
+ vm_class_name = controller.view_model_name.camelize
206
+ Object.const_set vm_class_name, Class.new unless Object.const_defined? vm_class_name
207
+
208
+ # TODO: There is an issue with namespacing and CLR classes, they aren't registered as constants with
209
+ # IronRuby. This makes it hard to namespace viewmodels. If the namespace is included everything
210
+ # should work as normally. Will revisit this later to properly fix it.
211
+ vm_name = controller.view_model_name
212
+ klass = Object.const_get vm_class_name
213
+ klass.send :include, IronNails::Models::Databinding
214
+ klass.send :include, IronNails::View::ViewModelMixin
215
+ key = vm_name.to_sym
216
+ view_models[key] = klass.new if view_models[key].nil?
217
+ registry.register_viewmodel_for controller, view_models[key]
218
+ view_models[key]
219
+ end
220
+
221
+ end
222
+
223
+ class ComponentRegistryItem
224
+
225
+ attr_accessor :viewmodel
226
+
227
+ attr_accessor :view
228
+
229
+ def initialize(options={})
230
+ @view = options[:view]
231
+ @viewmodel = options[:viewmodel]
232
+ end
233
+
234
+ end
235
+
236
+ class ComponentRegistry
237
+
238
+ attr_accessor :components
239
+
240
+ def initialize
241
+ @components = {}
242
+ end
243
+
244
+ def register(controller)
245
+ components[controller.controller_name] = ComponentRegistryItem.new
246
+ end
247
+
248
+ def register_view_for(controller, view)
249
+ find_controller(controller).view = view
250
+ end
251
+
252
+ def register_viewmodel_for(controller, model)
253
+ find_controller(controller).viewmodel = model
254
+ end
255
+
256
+ def find_controller(controller)
257
+ con_name = controller.respond_to?(:controller_name) ? controller.controller_name : controller.to_sym
258
+ components[con_name]
259
+ end
260
+
261
+ def viewmodel_for(controller)
262
+ find_controller(controller).viewmodel
263
+ end
264
+
265
+ def view_for(controller)
266
+ find_controller(controller).view
267
+ end
268
+ end
269
+
270
+ # This could be viewed as the life support for the Nails framework
271
+ # It serves as the glue between the different components.
272
+ # One of its main functions is to manage communication between the controller,
273
+ # view model and view.
274
+ class NailsEngine
275
+
276
+ include IronNails::Logging::ClassLogger
277
+ include ControllerObservable
278
+ include ViewOperations
279
+ include ViewModelOperations
280
+
281
+ # Stores the registered components and does lookup on them
282
+ attr_accessor :registry
283
+
284
+ def set_viewmodel_for(controller, key, value)
285
+ model = registry.viewmodel_for controller
286
+ model.set_model key, value
287
+ end
288
+
289
+ # configures the properties for the view model
290
+ def configure_models(model)
291
+ model_queue.each do |o|
292
+ o.each do |k, v|
293
+ model.add_model k, v
294
+ end unless o.nil?
295
+ end
296
+ end
297
+
298
+ # processes the command queue.
299
+ def configure_events(model, view)
300
+ command_queue.each do |cmd|
301
+ case
302
+ when cmd.is_a?(EventCommand)
303
+ view.add_command(cmd)
304
+ when cmd.is_a?(TimedCommand)
305
+ view.add_timer(cmd)
306
+ view.proxy.start_timer(cmd)
307
+ when cmd.is_a?(BehaviorCommand)
308
+ model.add_command cmd
309
+ end unless cmd.attached?
310
+ end
311
+ end
312
+
313
+ # configures the view
314
+ def configure_view(view)
315
+ model = registry.viewmodel_for view.controller
316
+ configure_models(model)
317
+ configure_events(model, view)
318
+ view.data_context = model unless view.has_datacontext? && !view.sets_datacontext?
319
+ @configured = true
320
+ end
321
+
322
+ # refreshes the data for the view.
323
+ def refresh_view(view)
324
+ notify_observers :refreshing_view, view.controller, self, view
325
+ view.configure
326
+ view.proxy.refresh
327
+ @configured = true
328
+ end
329
+
330
+ # synchronises the data in the viewmodel with the controller
331
+ def synchronise_with_controller
332
+ notify_observers :reading_input, self, view
333
+ end
334
+
335
+ def add_command_to_view(commands)
336
+ add_commands_to_queue commands
337
+ end
338
+
339
+ def synchronise_to_controller(controller)
340
+ objects = controller.instance_variable_get "@objects"
341
+ #model = registry.viewmodel_for controller #.objects.collect { |kvp| kvp.key.to_s.underscore.to_sym }
342
+ vw = registry.view_for controller
343
+ model = vw.proxy.data_context
344
+ objects.each do |k, v|
345
+ if model.respond_to?(k.to_sym)
346
+ val = model.send k.to_sym
347
+ objects[k] = val
348
+ controller.instance_variable_set "@#{k}", val
349
+ end
350
+ end
351
+ view_properties = controller.instance_variable_get "@view_properties"
352
+ view_properties.each do |k, v|
353
+ val = from_view controller, (v[:view]||controller.view_name), v[:element], v[:property]
354
+ instance_variable_set "@#{k}", val
355
+ end
356
+ end
357
+
358
+ # returns whether this view needs configuration or not
359
+ def configured?
360
+ !!@configured
361
+ end
362
+
363
+ def initialize
364
+ @configured, @registry = false, ComponentRegistry.new
365
+ init_viewmodel_operations
366
+ init_view_operations
367
+ end
368
+
369
+ def register_controller(controller)
370
+ logger.debug "registering controller #{controller.controller_name}", IRONNAILS_FRAMEWORKNAME
371
+ registry.register(controller)
372
+ register_viewmodel_for controller
373
+ register_view_for controller
374
+ controller.nails_engine = self
375
+ logger.debug "controller #{controller.controller_name} registered", IRONNAILS_FRAMEWORKNAME
376
+ end
377
+
378
+ def show_initial_window(controller)
379
+ logger.debug "setting up controller", IRONNAILS_FRAMEWORKNAME
380
+ #controller.setup_for_showing_view
381
+ registry.view_for(controller).load
382
+ controller.default_action if controller.respond_to? :default_action
383
+ controller.setup_for_showing_view
384
+ yield registry.view_for(controller).instance if block_given?
385
+ end
386
+
387
+ def initialize_with(command_definitions, models)
388
+ add_commands_to_queue command_definitions
389
+ add_models_to_queue_on models
390
+ logger.debug "Added commands to queue on view manager.", IRONNAILS_FRAMEWORKNAME
391
+ logger.debug "Added models to queue on view manager.", IRONNAILS_FRAMEWORKNAME
392
+ end
393
+
394
+ end
395
+
396
+ end
397
+
398
+ end