String
is NSMutableString
String
is NSMutableString
String
is NSMutableString
String
is NSMutableString
>> require 'osx/cocoa' => true
>> require 'osx/cocoa' => true >> 'hello'.class => String
>> require 'osx/cocoa' => true >> 'hello'.class => String >> hello = OSX::NSString.stringWithString('hello') => #<NSCFString "hello">
>> require 'osx/cocoa' => true >> 'hello'.class => String >> hello = OSX::NSString.stringWithString('hello') => #<NSCFString "hello"> >> hello.objc_methods.select { |m| m =~ /caseString$/ } => ["lowercaseString", "uppercaseString"]
>> 'hello'.class => NSMutableString
>> 'hello'.class => NSMutableString >> 'hello'.methods(true, true).select { |m| m =~ /caseString$/ } => [:lowercaseString, :uppercaseString]
[sound play];
[sound play];
sound.play
[sound play];
sound.play
sound.play
NSSound* sound; sound = [sound initWithContentsOfFile: @"my.mp3" byReference: NO ];
NSSound* sound; sound = [sound initWithContentsOfFile: @"my.mp3" byReference: NO ];
sound = NSSound.initWithContentsOfFile_byReference( 'my.mp3', false )
NSSound* sound; sound = [sound initWithContentsOfFile: @"my.mp3" byReference: NO ];
sound = NSSound.initWithContentsOfFile_byReference( 'my.mp3', false )
sound = NSSound.initWithContentsOfFile( 'my.mp3', byReference: false )
#import <Cocoa/Cocoa.h> NSApplication *app = [NSApplication sharedApplication] NSWindow *window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 200, 200) styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing: NSBackingStoreBuffered defer: NO ) [window setTitle: @"Hello World"] NSButton* button = [[NSButton alloc] initWithFrame: NSZeroRect] [[window contentView] addSubview: button] [button setBezelStyle: NSRoundedBezelStyle] [button setTitle: @"Say Hello"] [button sizeToFit] [button setFrameOrigin: NSMakePoint( ([[[window contentView] frameSize] width] / 2.0) - ([[button frameSize] width] / 2.0), ([[[window contentView] frameSize] height] / 2.0) - ([[button frameSize] height] / 2.0) ) @interface HelloWorldController : NSObject { } - (IBAction)sayHello:(id)sender; @end #import "HelloWorldController.h" @implementation HelloWorldController - (IBAction)sayHello:(id)sender{ NSLog(@"Hello World!"); } @end HelloWorldController* controller = [[HelloWorldController alloc] init] [button setTarget: controller] [button setAction: @selector(sayHello:)] [window display] [window orderFrontRegardless] [app run]
require 'osx/cocoa'; include OSX app = NSApplication.sharedApplication window = NSWindow.alloc.initWithContentRect_styleMask_backing_defer( [0, 0, 200, 60], NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask, NSBackingStoreBuffered, false ) window.title = 'Hello World' button = NSButton.alloc.initWithFrame(NSZeroRect) window.contentView.addSubview(button) button.bezelStyle = NSRoundedBezelStyle button.title = 'Say Hello' button.sizeToFit button.frameOrigin = NSMakePoint( (window.contentView.frameSize.width / 2.0) - (button.frameSize.width / 2.0), (window.contentView.frameSize.height / 2.0) - (button.frameSize.height / 2.0) ) button_controller = Object.new def button_controller.sayHello(sender) NSLog('Hello World!') end button.target = button_controller button.action = 'sayHello:' window.display window.orderFrontRegardless app.run
framework 'Cocoa' app = NSApplication.sharedApplication window = NSWindow.alloc.initWithContentRect( [0, 0, 200, 60], styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask, backing:NSBackingStoreBuffered, defer:false ) window.title = 'Hello World' button = NSButton.alloc.initWithFrame(NSZeroRect) window.contentView.addSubview(button) button.bezelStyle = NSRoundedBezelStyle button.title = 'Say Hello' button.sizeToFit button.frameOrigin = NSMakePoint( (window.contentView.frameSize.width / 2.0) - (button.frameSize.width / 2.0), (window.contentView.frameSize.height / 2.0) - (button.frameSize.height / 2.0) ) button_controller = Object.new def button_controller.sayHello(sender) NSLog('Hello World!') end button.target = button_controller button.action = 'sayHello:' window.display window.orderFrontRegardless app.run
require 'hotcocoa'; include HotCocoa application do window = window(:title => 'Hello World', :frame => [0, 0, 200, 60]) button = button(:title => 'Say Hello', :layout => { :align => :centre }) button.on_action { NSLog('Hello World!') } window << button end
require 'hotcocoa'; include HotCocoa application do window = window( :title => 'Hello World', :frame => [0, 0, 200, 60] ) button = button( :title => 'Say Hello', :layout => { :align => :centre } ) button.on_action { NSLog('Hello World!') } window << button end
+-helloworld/
+-config/
| +-build.yml
+-lib/
| +-application.rb
| +-menu.rb
+-Rakefile
+-resources/
+-smiley.icns
+-helloworld/
+-config/
| +-build.yml <-----
+-lib/
| +-application.rb
| +-menu.rb
+-Rakefile
+-resources/
+-smiley.icns
name: HelloWorld load: lib/application.rb secure: true version: "1.0" icon: resources/smiley.icns sources: - lib/**/*.rb
+-helloworld/
+-config/
| +-build.yml
+-lib/
| +-application.rb <-----
| +-menu.rb
+-Rakefile
+-resources/
+-smiley.icns
require 'hotcocoa'; include HotCocoa application do window = window( :title => 'Hello World', :frame => [0, 0, 200, 60] ) button = button( :title => 'Say Hello', :layout => { :align => :centre } ) button.on_action { NSLog('Hello World!') } window << button end
+-helloworld/
+-config/
| +-build.yml
+-lib/
| +-application.rb
| +-menu.rb <-----
+-Rakefile
+-resources/
+-smiley.icns
module HotCocoa def application_menu menu do |main| main.submenu :apple do |apple| apple.item(:quit, { :title => "Quit #{NSApp.name}", :key => "q" }) end end end end
+-helloworld/
+-config/
| +-build.yml
+-lib/
| +-application.rb
| +-menu.rb
+-Rakefile <-----
+-resources/
+-smiley.icns
require 'hotcocoa/application_builder' require 'hotcocoa/standard_rake_tasks' task :default => [:run]
macrake clean # Delete app bundle macrake build # Build app bundle macrake run # Build & run app bundle macrake deploy # Build app bundle and embed MacRuby.framework
+-helloworld/
+-config/
| +-build.yml
+-lib/
| +-application.rb
| +-menu.rb
+-Rakefile
+-resources/
+-smiley.icns <-----
# DO THE DEMO $ macrake deploy $ macrake run
+-helloworld
+-HelloWorld.app/
+-Contents
+-Frameworks
| +-MacRuby.framework # Embedded
+-Info.plist # Metadata
+-MacOS
| +-HelloWorld # Binary
+-PkgInfo # Metadata
+-Resources
+-HelloWorld.icns # Icons
+-rb_main.rb # MacRuby app loader
+-vfs.db # Virtual FS database
require 'appscript' module CalculatorDriver include Appscript def activate_calculator_app app_path = File.expand_path(...) app(app_path).activate end def calculator_process system_events = app('System Events') system_events.processes['Calculator'] end def setup_calculator_driver activate_calculator_app window = calculator_process.windows['Calculator'] @buttons = window.buttons @text_fields = window.text_fields end #...
def input_with_buttons(buttons_text) buttons_text.each_byte do |byte| click_button(byte.chr) end end def click_button(character) buttons = %w(C 0 1 2 3 4 5 6 7 8 9 . + - * / = √) if buttons.include?(character) @buttons[character].click else raise "Button does not exist for: #{character}" end end #...
require 'test/unit/assertions' #... include Test::Unit::Assertions def displays_number(expected_result) result = @text_fields[1].value.get assert_equal expected_result, result end
require 'test/unit' require 'calculator_driver' class AdditionTest < Test::Unit::TestCase include CalculatorDriver def setup setup_calculator_driver click_button('C') end def test_adding_two_single_digit_numbers input_with_buttons('1') click_button('+') input_with_buttons('2') click_button('=') displays_number('3') end #...
# DO THE DEMO $ macrake build $ rake test:acceptance
require 'hotcocoa' include HotCocoa class Calculator def self.on self.new.show end attr_accessor :accumulator, :value, :operand_pressed, :button_view def initialize @accumulator = [] end def show application :name => "Calculator" do |app| main_window << value main_window << button_view main_window.will_close { exit } end end private def main_window(&block) @main_window ||= window(:frame => [100, 800, 220, 280], :title => "Calculator", :view => :nolayout, :style => [:titled, :closable, :miniaturizable], &block) end def value @value ||= text_field(:frame => [10, 230, 200, 40], :text => "0", :font => font(:name => "Tahoma", :size => 22), :text_align => :right) end def button_view @button_view || create_button_view end def create_button_view @button_view = view(:frame => [10, 10, 200, 240]) add_buttons @button_view end def add_buttons calc_button("CL", 0, 4) { clear } calc_button("SQR", 1, 4) { sqrt } calc_button("/", 2, 4) { operand :/ } calc_button("*", 3, 4) { operand :* } calc_button("7", 0, 3) { press 7 } calc_button("8", 1, 3) { press 8 } calc_button("9", 2, 3) { press 9 } calc_button("-", 3, 3) { operand :- } calc_button("4", 0, 2) { press 4 } calc_button("5", 1, 2) { press 5 } calc_button("6", 2, 2) { press 6 } calc_button("+", 3, 2) { operand :+ } calc_button("1", 0, 1) { press 1 } calc_button("2", 1, 1) { press 2 } calc_button("3", 2, 1) { press 3 } calc_button("=", 3, 1, 0, 1) { evaluate } calc_button("0", 0, 0, 1, 0) { press 0 } calc_button(".", 2, 0) { press '.' } end def calc_button(name, x, y, w=0, h=0, &block) button_view << button(:title => name, :bezel => :regular_square, :frame => [x*50, y*43-h*43, 47+w*50, 40+h*43]).on_action(&block) end def evaluate accumulator << float_value result = eval(accumulator.join(" ")) value.text = (result.to_i == result ? result.to_i : result.to_s) accumulator.clear end def press(key) if operand_pressed value.text = key.to_s else value.text = (value.to_s == "0" ? key.to_s : (value.to_s + key.to_s)) end @operand_pressed = false end def operand(key) accumulator << float_value accumulator << key @operand_pressed = true end def float_value (value.to_s[0,1] == "." ? "0#{value.to_s}" : value.to_s).to_f end def sqrt value.text = Math.sqrt(float_value).to_s end def clear value.text = "0" end end Calculator.on
class Display def initialize clear end def clear @value = '0' end def set(value) @value = value.to_s end def push(character) if @value == '0' @value = character else @value += character end end #...
class DisplayTest < Test::Unit::TestCase def test_initial_value assert_equal '0', @display.to_s assert_in_delta 0.0, @display.to_f, 1e-8 end def test_clear_value @display.push('1') @display.clear assert_equal '0', @display.to_s assert_in_delta 0.0, @display.to_f, 1e-8 end def test_entering_single_digit_number @display.push('1') assert_equal '1', @display.to_s assert_in_delta 1.0, @display.to_f, 1e-8 end #...
class Accumulator def initialize clear end def push(value) @values << value end def evaluate result = eval(@values.join(' ')).to_f clear result end def clear @values = [] end #...
class View attr_reader :buttons def initialize(controller) main_window = window( :frame => [100, 800, 220, 280], :title => "Calculator", :view => :nolayout, :style => [:titled, :closable, :miniaturizable] ) @value = text_field( :frame => [10, 230, 200, 40], :text => controller.display.to_s, :font => font(:name => "Tahoma", :size => 22), :text_align => :right ) main_window << @value #...
#... @buttons = {} @buttons['C'] = calc_button("C", 0, 4) @buttons['√'] = calc_button("√", 1, 4) @buttons['/'] = calc_button("/", 2, 4) #... @buttons['='] = calc_button("=", 3, 1, 0, 1) @buttons['0'] = calc_button("0", 0, 0, 1, 0) @buttons['.'] = calc_button(".", 2, 0) buttons_view = view(:frame => [10, 10, 200, 240]) @buttons.values.each do |b| buttons_view << b end main_window << buttons_view main_window.will_close { exit } end
class AccumulatorTest < Test::Unit::TestCase def test_initial_evaluate result = @accumulator.evaluate assert_in_delta 0.0, result, 1e-8 end def test_evaluate_after_no_operations @accumulator.push(123.0) result = @accumulator.evaluate assert_in_delta 123.0, result, 1e-8 end def test_evaluate_addition_operation @accumulator.push(123.0) @accumulator.push('+') @accumulator.push(456.0) result = @accumulator.evaluate assert_in_delta 579.0, result, 1e-8 end #...
class Calculator def initialize @model = Model.new end def show application :name => "Calculator" do |app| @view = View.new(self) %w(0 1 2 3 4 5 6 7 8 9 .).each do |digit| @view.buttons[digit].on_action { press(digit) } end %w(+ - * /).each do |operation| @view.buttons[operation].on_action { operand(operation) } end @view.buttons['C'].on_action { clear } @view.buttons['√'].on_action { sqrt } @view.buttons['='].on_action { evaluate } end end #...
def evaluate @model.evaluate @view.update_value(@model.current_value) end def press(key) @model.press(key) @view.update_value(@model.current_value) end def operand(key) @model.operand(key) end def sqrt @model.sqrt @view.update_value(@model.current_value) end def clear @model.clear @view.update_value(@model.current_value) end
# DO THE DEMO $ TESTOPTS="-v" rake test:units