ANN: Second drop of RubyCLR bridge


#1

This is a much more complete drop of the bridge:
http://www.iunknown.com/articles/2006/02/20/second-drop-of-rubyclr

To show off its features, I’ve built a non-trivial all-Ruby Windows
Forms
2.0 RSS Reader application that’s in the distribution. It’s been tested
with
the RTM bits of .NET FX 2.0, and Ruby 1.8.2.

Comments & questions more than welcome!

Cheers,
-John
http://www.iunknown.com


#2

On 2/20/06, John L. removed_email_address@domain.invalid wrote:

-John
http://www.iunknown.com

Any idea if this will, or will be capable of working with mono?


#3

Any idea if this will, or will be capable of working with mono?

I haven’t had any cycles to look at mono’s implementation of the
DynamicMethod API. If they have feature parity there, then it shouldn’t
be
too hard. That said, that’s a secondary goal at the moment, I really
want to
get it to work first on .NET 2.0, and then do a port to mono.
Side-by-side
dev would eat up more cycles than I have at the moment.

That said, anyone out there want to work in parallel on a mono port?

-John
http://www.iunknown.com


#4

Oh man, if this means we can finally write true-blue Windows GUI apps
in Ruby, I’m in heaven. I haven’t used .NET yet, so I’m a little in the
dark about the whole deal, but just seeing the example on your page
gets me excited.

Keep it up, I’m definitely keeping an eye on this project.

-Matt T.


#5

Yes - that’s the primary goal of this project - client side GUI apps
(especially leveraging the new WinFX libraries) and console mode
utilities.

I think that Rails has the server side app story covered, but there
isn’t a
compelling story for Ruby and rich client apps on Windows yet. I’m
hoping
that this will be that story.

Cheers,
-John
http://www.iunknown.com


#6

On 2/20/06, John L. removed_email_address@domain.invalid wrote:

Any idea if this will, or will be capable of working with mono?

I haven’t had any cycles to look at mono’s implementation of the
DynamicMethod API. If they have feature parity there, then it shouldn’t be
too hard. That said, that’s a secondary goal at the moment, I really want
to
get it to work first on .NET 2.0, and then do a port to mono. Side-by-side
dev would eat up more cycles than I have at the moment.

I don’t know how far along mono’s .NET 2.0 implementation has gotten,
but it
would definitely be interesting to see in the long run.

That said, anyone out there want to work in parallel on a mono port?

I’d love to, I’ve just got about nine other projects I need to get done
first, so I can’t volunteer just yet :slight_smile:

-John


#7

This is a great step forward. I’ve done a lot of Windows Forms work and
…NET has a really good UI layer for working with. What’s more, it has
fantastic documentation. I tried to learn Tcl/Tk but the challenge of
translating from Perl and learning a new tool kit at the same time was
too much. This is just what I wanted to write Ruby GUI apps.

Anyways, I banged together a little ‘Google Calculator’ program that
uses Google’s calcuator service for evaluating expressions. Sounds
trivial until you need to divide miles by fortnights or similar (try
it!).

Heres the code - just copy it into the same directory with the
rubyclr.rb file and the RbDynamicMethod.dll:

RSS Reader sample application

©Copyright 2006 John L.

BUG: crashes on dave winer’s feed http://www.scripting.com/rss.xml -

bug in rss feed reader

require ‘rubyclr’

RubyClr::reference ‘System’
RubyClr::reference ‘System.Drawing’
RubyClr::reference ‘System.Windows.Forms’

include System::Drawing
include System::Drawing::Drawing2D
include System::Windows::Forms

require ‘open-uri’
require ‘cgi’

class GoogleCalc

def self.calc(expr)
open((“http://www.google.com/search?q=#{CGI.escape(expr.strip)}”))
do |f|
if f.status.include? “200”
begin
matches = MATCH_EXP.match(f.read)
return result_format(matches[2])
rescue NoMethodError
return “==> Expression not understood.”
rescue Exception
return “==> Expression not understood. (#{$!.class.inspect},
#{$!.inspect})”
end
else
return “==> Response error: #{f.status.inspect}”
end
end
end

private

MATCH_EXP = Regexp.new("

 (.?) =
(.
?)")

def self.result_format(s)
s.gsub("
“,”,").gsub(“×”,“x”).gsub("","^").gsub("", “”)
end

end

class MainForm
attr_accessor :form

def initialize
form = Form.new
form.FormBorderStyle = FormBorderStyle::Sizable
form.SizeGripStyle = SizeGripStyle::Show
form.StartPosition = FormStartPosition::CenterScreen
form.Text = “Google Calculator”
form.Size = Size.new(220, 200)

expressionGroupBox = GroupBox.new
expressionGroupBox.Dock = DockStyle::Top
expressionGroupBox.Width = 215
expressionGroupBox.Height = 50
expressionGroupBox.Text = "Expression"

expressionTextBox = TextBox.new
expressionTextBox.Location = Point.new(5, 20)
expressionTextBox.Size = Size.new(125, 21)
expressionTextBox.Anchor = AnchorStyles::Left | AnchorStyles::Top |

AnchorStyles::Right

calcButton = Button.new
calcButton.Size = Size.new(75, 23)
calcButton.Location = Point.new(135, 19)
calcButton.Text = "Calculate"
calcButton.Anchor = AnchorStyles::Right | AnchorStyles::Top
calcButton.Enabled = false

expressionGroupBox.Controls.Add(expressionTextBox)
expressionGroupBox.Controls.Add(calcButton)

resultGroupBox = GroupBox.new
resultGroupBox.Dock = DockStyle::Fill
resultGroupBox.Text = "Results"
resultGroupBox.Size = Size.new(100, 100)

resultTextBox = TextBox.new
resultTextBox.Location = Point.new(5, 20)
resultTextBox.Size = Size.new(90, 75)
resultTextBox.Anchor = AnchorStyles::Right | AnchorStyles::Top |

AnchorStyles::Left | AnchorStyles::Bottom
resultTextBox.Multiline = true
resultTextBox.ReadOnly = true
# resultTextBox.BorderStyle = BorderStyle::None
#resultTextBox.ForeColor = Color.Black
#resultTextBox.BackColor = Color.White

expressionTextBox.TextChanged do |sender, args|
  calcButton.Enabled = (expressionTextBox.Text.strip != "")
end

calcButton.Click do |sender, args|
  begin
    calcButton.Text = "Working ..."
    calcButton.Enabled = false
    resultTextBox.Text = GoogleCalc.calc(expressionTextBox.Text)
  rescue Exception
    resultTextBox.Text = "==> Error occurrred: $!.message"
  ensure
    calcButton.Text = "Calculate"
    calcButton.Enabled = true
  end
end

resultGroupBox.Controls.Add(resultTextBox)

form.Controls.Add(resultGroupBox)
form.Controls.Add(expressionGroupBox)
form.PerformLayout
@form = form

end
end

Application.EnableVisualStyles
Application.SetCompatibleTextRenderingDefault false
Application.Run(MainForm.new.form)


#8

Here’s some more fun - an alternate way to initialize properties. Now if
only I could get rid of the argument to the block:

begin code

Form.class_eval do
def initialize(*args, &blk)
super
unless blk.nil?
blk.call(self)
end
end
end

class MainForm
attr_accessor :form

def initialize
@form = Form.new do |f|
f.FormBorderStyle = FormBorderStyle::Sizable
f.SizeGripStyle = SizeGripStyle::Show
f.StartPosition = FormStartPosition::CenterScreen
f.Text = “Initialize From Block!”
f.Size = Size.new(220, 200)
end
end
end

Application.Run(MainForm.new.form)


#9

when i run it,it show follow errors:
dynamic constant assignment
MATCH_EXP=Regexp.new("

<imgsrc=/images/calc_img.gif> (.?) = (.?)")

#10

Watch out for the wrapping from the email. Just delete the carriage
return
from the string.

-John