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,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"