ironnails 0.0.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 (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,57 @@
1
+ # Taken from the Rails codebase. I can't require any gem atm when I can I will use their implementation.
2
+ #
3
+ # Extends the class object with class and instance accessors for class attributes,
4
+ # just like the native attr* accessors for instance attributes.
5
+ #
6
+ # class Person
7
+ # cattr_accessor :hair_colors
8
+ # end
9
+ #
10
+ # Person.hair_colors = [:brown, :black, :blonde, :red]
11
+ class Class
12
+
13
+ def cattr_reader(*syms)
14
+ syms.flatten.each do |sym|
15
+ next if sym.is_a?(Hash)
16
+ class_eval(<<-EOS, __FILE__, __LINE__)
17
+ unless defined? @@#{sym}
18
+ @@#{sym} = nil
19
+ end
20
+
21
+ def self.#{sym}
22
+ @@#{sym}
23
+ end
24
+
25
+ def #{sym}
26
+ @@#{sym}
27
+ end
28
+ EOS
29
+ end
30
+ end
31
+
32
+ def cattr_writer(*syms)
33
+ options = syms.extract_options!
34
+ syms.flatten.each do |sym|
35
+ class_eval(<<-EOS, __FILE__, __LINE__)
36
+ unless defined? @@#{sym}
37
+ @@#{sym} = nil
38
+ end
39
+
40
+ def self.#{sym}=(obj)
41
+ @@#{sym} = obj
42
+ end
43
+
44
+ #{"
45
+ def #{sym}=(obj)
46
+ @@#{sym} = obj
47
+ end
48
+ " unless options[:instance_writer] == false }
49
+ EOS
50
+ end
51
+ end
52
+
53
+ def cattr_accessor(*syms)
54
+ cattr_reader(*syms)
55
+ cattr_writer(*syms)
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/class/attribute_accessors'
2
+
3
+ class Class
4
+
5
+ def demodulize
6
+ self.to_s.gsub(/^.*::/, '')
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ class Fixnum
2
+
3
+ def to_timespan(as=:seconds)
4
+ case as
5
+ when :hours || :hour
6
+ TimeSpan.new(self, 0, 0)
7
+ when :minutes || :minute
8
+ TimeSpan.new(0, self, 0)
9
+ else
10
+ TimeSpan.new(0, 0, self)
11
+ end
12
+ end
13
+
14
+ def minutes
15
+ self * 60
16
+ end
17
+
18
+ def seconds
19
+ self
20
+ end
21
+
22
+ end
@@ -0,0 +1,32 @@
1
+ class Hash
2
+
3
+ #returns a string of post parameters for http posts, url-encoded
4
+ def to_post_parameters
5
+ params = ""
6
+
7
+ self.each do |k, v|
8
+ params += "&" unless params.empty?
9
+ params += "#{k}=#{HttpUtility.url_encode(v.to_s.to_clr_string)}"
10
+ end
11
+
12
+ params
13
+ end
14
+
15
+ def to_s
16
+ res = self.collect do |k, v|
17
+ val = case
18
+ when v.is_a?(String)
19
+ "\"#{v}\""
20
+ when v.is_a?(Symbol)
21
+ ":#{v}"
22
+ else
23
+ "#{v}"
24
+ end
25
+ "#{k.is_a?(Symbol) ? ":#{k}" : "#{k}" } => #{val}"
26
+ end
27
+ "{ #{res.join(', ')} }"
28
+ end
29
+
30
+ alias_method :to_str, :to_s
31
+ alias_method :inspect, :to_s
32
+ end
@@ -0,0 +1,26 @@
1
+ module Kernel
2
+
3
+ # Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
4
+ #
5
+ # silence_warnings do
6
+ # value = noisy_call # no warning voiced
7
+ # end
8
+ #
9
+ # noisy_call # warning voiced
10
+ def silence_warnings
11
+ old_verbose, $VERBOSE = $VERBOSE, nil
12
+ yield
13
+ ensure
14
+ $VERBOSE = old_verbose
15
+ end
16
+
17
+ def using(o=nil)
18
+ begin
19
+ yield if block_given?
20
+ ensure
21
+ o.dispose
22
+ end
23
+ end
24
+
25
+
26
+ end
@@ -0,0 +1,58 @@
1
+ class String
2
+
3
+ # ensures that our url starts with at least http
4
+ def ensure_http
5
+ return "http://#{self}" unless /^(ht|f)tp:\/\/.*/i.match(self)
6
+ self
7
+ end
8
+
9
+ # returns whether this string is a well formed url
10
+ def is_url?
11
+ !!(Uri.is_well_formed_uri_string(self.to_clr_string, UriKind.Absolute) && /^(ht|f)tp/i.match(Uri.new(self).scheme))
12
+ end
13
+
14
+ def strip_html
15
+ self.gsub(/<(.|\n)*?>/, '')
16
+ end
17
+
18
+ def camelize(first_letter_in_uppercase = true)
19
+ if first_letter_in_uppercase
20
+ self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
21
+ else
22
+ self[0...1].downcase + camelize(self)[1..-1]
23
+ end
24
+ end
25
+
26
+ def underscore
27
+ self.gsub(/::/, '/').
28
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
29
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
30
+ tr("-", "_").
31
+ downcase
32
+ end
33
+
34
+ def to_clr_char
35
+ self.to_clr_string.to_char_array[0]
36
+ end
37
+
38
+ def to_secure_string
39
+ IronNails::Security::SecureString.secure_string self
40
+ end
41
+
42
+ def decrypt
43
+ IronNails::Security::SecureString.decrypt_string self
44
+ end
45
+
46
+ def classify
47
+ Kernel.const_get(self.camelize)
48
+ end
49
+
50
+ def truncate(max=140)
51
+ if self.size > max
52
+ s = self[0...max-5]
53
+ return s.split(' ')[0...s.split(' ').size - 1].join(' ')
54
+ end
55
+ self
56
+ end
57
+
58
+ end
@@ -0,0 +1,78 @@
1
+ class Symbol
2
+
3
+ def to_brush
4
+ case self
5
+ when :black
6
+ Brushes.black
7
+ when :white
8
+ Brushes.white
9
+ when :green
10
+ Brushes.green
11
+ when :alice_blue
12
+ Brushes.alice_blue
13
+ when :red
14
+ Brushes.red
15
+ end
16
+ end
17
+
18
+ def to_orientation
19
+ case self
20
+ when :horizontal
21
+ Orientation.horizontal
22
+ when :vertical
23
+ Orientation.vertical
24
+ end
25
+ end
26
+
27
+ def to_visibility
28
+ case self
29
+ when :visible
30
+ Visibility.visible
31
+ when :hidden
32
+ Visibility.hidden
33
+ when :collapsed
34
+ Visibility.collapsed
35
+ end
36
+ end
37
+
38
+ def to_vertical_alignment
39
+ case self
40
+ when :center
41
+ VerticalAlignment.center
42
+ when :top
43
+ VerticalAlignment.top
44
+ when :bottom
45
+ VerticalAlignment.bottom
46
+ when :stretch
47
+ VerticalAlignment.strecht
48
+ end
49
+ end
50
+
51
+ def to_horizontal_alignment
52
+ case self
53
+ when :center
54
+ HorizontalAlignment.center
55
+ when :left
56
+ HorizontalAlignment.left
57
+ when :right
58
+ HorizontalAlignment.right
59
+ when :stretch
60
+ HorizontalAlignment.stretch
61
+ end
62
+ end
63
+
64
+ def to_binding_mode
65
+ case self
66
+ when :default
67
+ BindingMode.default
68
+ when :one_time
69
+ BindingMode.one_time
70
+ when :one_way
71
+ BindingMode.one_way
72
+ when :one_way_to_source
73
+ BindingMode.one_way_to_source
74
+ when :two_way
75
+ BindingMode.two_way
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,110 @@
1
+ class System::Net::WebRequest
2
+
3
+ include IronNails::Logging::ClassLogger
4
+
5
+ def prepare_for_post(parameters = {})
6
+
7
+ params = parameters.to_post_parameters
8
+
9
+ self.clr_member(:Method=).call "POST"
10
+ self.content_type = "application/x-www-form-urlencoded"
11
+ self.content_length = params.length
12
+
13
+ using (stream = StreamWriter.new(self.get_request_stream, System::Text::Encoding.ASCII)) do
14
+ stream.write params
15
+ end
16
+
17
+ params
18
+ end
19
+
20
+ def prepare_for_async_post(parameters = {}, &callback)
21
+ self.clr_member(:Method=).call "POST"
22
+ self.content_type = "application/x-www-form-urlencoded"
23
+ self.content_length = parameters.to_post_parameters.length
24
+
25
+ self.begin_get_request_stream(AsyncCallback.new {|ar| callback.call(ar) }, nil)
26
+ end
27
+
28
+ def perform_post( params, parse_response=nil)
29
+ logger.debug("IronNails: WebRequest: Performing POST to #{request_uri.to_string}")
30
+ self.prepare_for_post(params)
31
+ begin
32
+ res = self.get_response # we get a real HttpWebResponse back instead of the WebResponse for the C# and VB.NET users. yay for duck typing
33
+ unless parse_response.nil?
34
+ using(rdr = StreamReader.new(res.get_response_stream)) do
35
+ return parse_response.call(rdr)
36
+ end
37
+ else
38
+ return res.status_code == HttpStatusCode.OK
39
+ end
40
+ rescue WebException => e
41
+ handle_exception e
42
+ end
43
+ false
44
+ end
45
+
46
+ def perform_async_post( params, parse_response=nil, &callback)
47
+ logger.debug("IronNails: WebRequest: Performing asynchronous POST to #{request_uri.to_string}")
48
+ self.prepare_for_async_post params do |async_result|
49
+ using(post_stream = self.end_get_request_stream(async_result)) do
50
+ pars = parameters.to_post_parameters
51
+ post_stream.write pars.convert_to_bytes, 0, pars.size
52
+ end
53
+
54
+ self.begin_get_response(AsyncCallback.new { |response|
55
+ res = self.end_get_response response
56
+ using(rdr = StreamReader.new(res.get_response_stream)) do
57
+ parse_response.call(rdr)
58
+ end unless parse_response.nil?
59
+ callback.call res.status_code == HttpStatusCode.OK if block_given?
60
+ }, nil);
61
+ end
62
+ end
63
+
64
+
65
+ def perform_get( parse_response=nil)
66
+ logger.debug("IronNails: WebRequest: Performing GET to #{request_uri.to_string}")
67
+ begin
68
+ response = self.get_response
69
+ using(rdr = StreamReader.new(response.get_response_stream)) do
70
+ parse_response.call(rdr)
71
+ end unless parse_response.nil?
72
+ rescue WebException => e
73
+ handle_exception e
74
+ end
75
+ end
76
+
77
+ def perform_async_get( parse_response=nil, &callback)
78
+ logger.debug("IronNails: WebRequest: Performing asynchronous GET to #{request_uri.to_string}")
79
+ self.begin_get_response AsyncCallback.new{ |response|
80
+ begin
81
+ res = self.end_get_response(response)
82
+ using(rdr = StreamReader.new(res.get_response_stream)) do
83
+ obj = parse_response.call(rdr)
84
+ callback.call(obj) if block_given?
85
+ end if parse_response
86
+ rescue WebException => e
87
+ handle_exception e
88
+ end
89
+ }, nil
90
+ end
91
+
92
+ def handle_exception(e)
93
+ logger.error("ERROR: IronNails: WebRequest (#{request_uri.to_string}):\nThere was an error while executing the web request: #{e.message}")
94
+ status = e.status;
95
+ if status == WebExceptionStatus.protocol_error
96
+ httpResponse = e.response
97
+
98
+ case httpResponse.status_code
99
+ when HttpStatusCode.NotModified: # 304 Not modified = no new tweets so ignore error.
100
+ break;
101
+ when HttpStatusCode.Unauthorized: # unauthorized
102
+ raise SecurityException.new("Not Authorized.");
103
+ else
104
+ raise
105
+ end
106
+ else
107
+ raise
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,18 @@
1
+ module System
2
+
3
+ module Security
4
+
5
+ class SecureString
6
+
7
+ def to_insecure_string
8
+ IronNails::Security::SecureString.unsecure_string self
9
+ end
10
+
11
+ def encrypt
12
+ IronNails::Security::SecureString.encrypt_string self
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,6 @@
1
+ class System::Windows::Markup::XamlReader
2
+
3
+ def self.load_from_path(path)
4
+ self.load XmlReader.create(path)
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ module System
2
+
3
+ module Windows
4
+
5
+ class UIElement
6
+
7
+ @@empty_delegate = System::Action.new { }
8
+ @@empty_priorty = System::Windows::Threading::DispatcherPriority.render
9
+
10
+ def refresh
11
+ self.dispatcher.invoke @@empty_priorty, @@empty_delegate
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,28 @@
1
+ require 'time'
2
+ class Time
3
+
4
+ def humanize
5
+ humanized_time = ""
6
+ delta = Time.now - self
7
+ case
8
+ when delta <= 1
9
+ humanized_time = "just now"
10
+ when delta < 60
11
+ humanized_time = "#{delta.floor} seconds ago"
12
+ when delta < 120
13
+ humanized_time = "about a minute ago"
14
+ when delta < (45 * 60)
15
+ humanized_time = "#{(delta / 60).round} minutes ago"
16
+ when delta < (90 * 60)
17
+ humanized_time = "about an hour ago"
18
+ when delta < (86400)
19
+ humanized_time = "about #{(delta / 3600 ).round } hours ago"
20
+ when delta < (48 * 3600)
21
+ humanized_time = "1 day ago"
22
+ else
23
+ humanized_time = "#{(delta / 86400).round} days ago"
24
+ end
25
+
26
+ humanized_time
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'ironnails/core_ext/array'
2
+ require 'ironnails/core_ext/class'
3
+ require 'ironnails/core_ext/fixnum'
4
+ require 'ironnails/core_ext/hash'
5
+ require 'ironnails/core_ext/kernel'
6
+ require 'ironnails/core_ext/string'
7
+ require 'ironnails/core_ext/symbol'
8
+ require 'ironnails/core_ext/time'
9
+ require 'ironnails/core_ext/system/net/web_request'
10
+ require 'ironnails/core_ext/system/windows/markup/xaml_reader'
11
+ require 'ironnails/core_ext/system/windows/ui_element'
12
+ require 'ironnails/core_ext/system/security/secure_string'
@@ -0,0 +1,19 @@
1
+ module IronNails
2
+
3
+ module Errors
4
+
5
+ class IronNailsError < StandardError
6
+
7
+
8
+ end
9
+
10
+ class ContractError < IronNails::Errors::IronNailsError
11
+
12
+ def initialize(method)
13
+ super "#{method} needs to be overridden in an implementing class"
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,83 @@
1
+ module IronNails
2
+
3
+ module Core
4
+
5
+ class IronXml
6
+
7
+ attr_reader :xml_node, :parent
8
+
9
+ def initialize(xml_doc, parent=nil)
10
+ @xml_node = xml_doc
11
+ @parent = parent
12
+ end
13
+
14
+ # selects multiple child nodes from the tree
15
+ def elements(name, &b)
16
+ if has_element? name
17
+ ele = @xml_node.select_nodes xp_pref(name)
18
+ ele.each do |el|
19
+ raise "Expected a block for multiple elements" unless block_given?
20
+ b.call IronXml.new(el, self) unless el.nil?
21
+ end
22
+ else
23
+ []
24
+ end
25
+ end
26
+
27
+ # selects a single child node from the tree
28
+ def element(name)
29
+ if has_element? name
30
+ ele = @xml_node.select_single_node xp_pref(name)
31
+ xml = IronXml.new(ele, self)
32
+ yield xml if block_given?
33
+ xml
34
+ end
35
+ end
36
+
37
+ # indicates whether the element is present in the selected nodes.
38
+ def has_element?(name)
39
+ !@xml_node.nil? && @xml_node.select_nodes("#{name}").count > 0
40
+ end
41
+
42
+ # the XPath prefix (rooted or not?)
43
+ def xp_pref(name)
44
+ @parent.nil? ? "//#{name}" : name
45
+ end
46
+
47
+ # the value of the selected node
48
+ def value
49
+ @xml_node.inner_text
50
+ end
51
+
52
+ # parses an xml document. +content+ can be either
53
+ # a string containing xml, a path to an xml document
54
+ # or a System::IO::Reader. You tell IronXml which type of
55
+ # content you have by passing in a +content_type+.
56
+ # +content_type+ is a symbol that defaults to :string
57
+ # it expects a block to traverse the xml provided.
58
+ def self.parse(content, content_type = :string, &b)
59
+ xdoc = XmlDocument.new
60
+
61
+ if content_type == :string
62
+ xdoc.load_xml(content)
63
+ else
64
+ xdoc.load(content)
65
+ end
66
+ b.call(IronXml.new(xdoc))
67
+ end
68
+
69
+ def method_missing(sym, *args, &b)
70
+ # this is what gives us the syntactic sugar over the
71
+ # Xlinq like syntax
72
+ if block_given?
73
+ self.elements(sym.to_s, &b)
74
+ else
75
+ self.element(sym.to_s).value
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,4 @@
1
+ require 'ironnails/core_ext/array'
2
+ require 'ironnails/core_ext/class'
3
+ require "ironnails/logging/buffered_logger"
4
+ require "ironnails/logging/class_logger"