RubyCocoa Sheets - help anyone?

Hey Guys

Just wondered if somone could help me with using modal sheets in
RubyCocoa - I think I am nearly there but its one method paramater that
is sucuppering me… In the apple tutorial here is the code:

  • (void)showCustomSheet: (NSWindow *)window

// User has asked to see the custom display. Display it.
{
if (!myCustomSheet)
//Check the myCustomSheet instance variable to make sure the custom
sheet does not already exist.
[NSBundle loadNibNamed: @“MyCustomSheet” owner: self];

[NSApp beginSheet: myCustomSheet
        modalForWindow: window
        modalDelegate: self
        didEndSelector:

@selector(didEndSheet:returnCode:contextInfo:)
contextInfo: nil];

// Sheet is up here.
// Return processing to the event loop

}

So I have translated this into

def showConnectionSheet(window)
NSBundle.loadNibNamed_owner(‘Connection’, self)
NSApp.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(@connection,
self.window, nil, nil, nil)
end

But its the didEndSelector paramater that I do not know what to put in?
Can anyone help me?

Cheers

Tim

try NSSelectorFromString

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSelectorFromString

Jacob B. wrote:

try NSSelectorFromString

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSelectorFromString

Hey Jacob

Excuse my ignorence but I am not sure how that would help me? I dont
actually understand what the
@selector(didEndSheet:returnCode:contextInfo:) code is actually doing -
could you perhaps explain? If I can understand what it does i should be
able to translate it hopefully.

Cheers

Tim

On 5/5/07, Tim P. [email protected] wrote:

could you perhaps explain? If I can understand what it does i should be
able to translate it hopefully.

@selector is a way of reifying a method name. it’s a bit like using
:a_method_name in ruby or method(:method_name). Basically the sheet
wants the name of a method to run when the sheet is done interacting
with the user.

On May 6, 2007, at 12:41 AM, Tim P. wrote:

actually understand what the

Posted via http://www.ruby-forum.com/.

For Cocoa info you might try the CocoaDev list.
http://lists.apple.com
RubyCocoa is Ruby, but the references on Cocoa are all in Objective-C
and yes they can be a bit vague. It’s a huge framework.

Ok cool, that makes sense, so I would need to define a sheet method that
runs just before the sheet is going to close? Its a callback for the
sheet effectivly then.

I have tried instansiating both NSSelector and NSSelectorFromString, but
no luck. I have tried instansiating them in a number of ways:

NSSelectorFromString.alloc.init(‘connectionSheetDidEnd’)
NSSelector(‘connectionSheetDidEnd’).alloc.init

and so on…

It complains it does not like the NSSelectorFromString and thinks it is
an uninitilized constant?

Cheers

Tim

IIRC NSSelectorFromString is a good old fashioned C function, not a
class. checks to be sure
Yep:

So if its a C function, what does that mean for me using RubyCocoa? its
in the foundation framework so i would have thought I could use it with
the ruby bridge?

Thanks

Tim

On 5/5/07, Tim P. [email protected] wrote:

and so on…

It complains it does not like the NSSelectorFromString and thinks it is
an uninitilized constant?

IIRC NSSelectorFromString is a good old fashioned C function, not a
class. checks to be sure
Yep:
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSelectorFromString

Tim P. [email protected] writes:

IIRC NSSelectorFromString is a good old fashioned C function, not a
class. checks to be sure
Yep:

So if its a C function, what does that mean for me using RubyCocoa? its
in the foundation framework so i would have thought I could use it with
the ruby bridge?

Okay, two things of note here:

First, it’s quite possible that you could pass a plain string, and
RubyCocoa
will call NSSelectorFromString() for you. I’m not a RubyCocoa pro by any
stretch, but that’s how my CamelBones Perl/Cocoa bridge works; selectors
are
just plain old strings in Perl.

Second, you’ll need to pass the full name of the selector, not just
the
part before the first argument - i.e.
“didEndSheet:returnCode:contextInfo:”.

sherm–

On May 6, 2007, at 3:20 AM, Tim P. wrote:

Thanks

Tim


Posted via http://www.ruby-forum.com/.

That’s not necessarily a problem.
Remember that Cocoa’s main language is Objective-C which is a strict
super-set of C. Valid C is valid Objective-C.
RubyCocoa is a bridge to Cocoa.
I haven’t used it myself. Cocoa is so big already with lots of vague
docs. It’s going to be tough but fun going with RubyCocoa perhaps.
You might want to get the Hillegass book on Cocoa first if you
haven’t got it already. If you know what’s going on in Cocoa with Obj-
C, then Ruby Cocoa will be a lot easier.

Tim P. [email protected] writes:

Second, you’ll need to pass the full name of the selector, not just
the
part before the first argument - i.e.
“didEndSheet:returnCode:contextInfo:”.

So what your saying in effect is that although im writing in Ruby,
because its a bridge I have to pass the whole ObjC method signiture?

Yes, because the code that will be calling your callback is Objective-C.
All it knows is to send the message
‘didEndSheet:returnCode:contextInfo:’.
It doesn’t know if the receiver will handle the message by calling a
method in Objective-C, Ruby, or some other language.

To put it another way, the selector is the name of the message, and will
be the same regardless of what language you’re writing in, or how that
language maps messages to the methods that handle them.

Most of the time, you won’t need to worry about the distinction between
selector and method names - the bridge will handle translating ordinary
Ruby method calls to Objective-C messages. But you will need to keep it
in mind when you’re passing selectors as arguments.

so if my method was:

def connectionSheetDidEnd(returnCode, contextInfo)

Don’t name your method like that. When you send Cocoa messages, you
replace
the :s with _s (all except the last one). When you want Cocoa to call
your
Ruby methods, the bridge does the same translation in reverse. So if the
selector you give to Cocoa is ‘didEndSheet:returnCode:contextInfo:’,
then
the Ruby method should be named like this:

def didEndSheet_returnCode_contextInfo(sheet, code, context)
    ...
end

So, when the bridge receives the message, it will replace the :s with
_s,
and strip off the last _, to determine what Ruby method will handle the
message.

I would then have to pass in
‘connectionSheetDidEnd:returnCode:contextInfo’?

Don’t forget that last colon. In Ruby (and Perl, and Python) the
trailing
underscore is optional for the method name, but the trailing colon is
still
part of the selector.

sherm–

Hey Sherm

Thats really great thank you! Much much clearer now :slight_smile:

In ligt of your suggestions I have reworked it so my couple of methods
are

def showConnectionSheet
NSBundle.loadNibNamed_owner(‘Connection’, self)
NSApp.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(@connection,
self.window, self, ‘didEndSheet:returnCode:contextInfo:’, nil)
end

def didEndSheet_returnCode_contextInfo(sheet, code, context)
return
end

But then I get an assertion error:

*** Assertion failure in -[NSApplication
_commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:didEndSelector:contextInfo:],
AppKit.subproj/NSApplication.m:3057

In the initial Apple example code there method is marked as (void) and
not an (IBAction), can this method not be called directly? Also, I have
establised an IB outlet which im guessing the nib is loaded into? Are
there any tutorials at all out there on using sheets?!

Cheers again for your ongoing help

Tim

Second, you’ll need to pass the full name of the selector, not just
the
part before the first argument - i.e.
“didEndSheet:returnCode:contextInfo:”.

So what your saying in effect is that although im writing in Ruby,
because its a bridge I have to pass the whole ObjC method signiture?

so if my method was:

def connectionSheetDidEnd(returnCode, contextInfo)

code here…

end

I would then have to pass in
‘connectionSheetDidEnd:returnCode:contextInfo’? Is that how it works or
am I such a newbie at this i’ve totally missed the point!? lol

Cheers

Tim

Hey Sherm

Thats really great thank you! Much much clearer now :slight_smile:

In ligt of your suggestions I have reworked it so my couple of methods
are

def showConnectionSheet
NSBundle.loadNibNamed_owner(‘Connection’, self)
NSApp.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(@connection,
self.window, self, ‘didEndSheet:returnCode:contextInfo:’, nil)
end

def didEndSheet_returnCode_contextInfo(sheet, code, context)
return
end

But then I get an assertion error:

*** Assertion failure in -[NSApplication
_commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:didEndSelector:contextInfo:],
AppKit.subproj/NSApplication.m:3057

In the initial Apple example code there method is marked as (void) and
not an (IBAction), can this method not be called directly? Also, I have
establised an IB outlet which im guessing the nib is loaded into? Are
there any tutorials at all out there on using sheets?!

Cheers again for your ongoing help

Tim

Tim P. [email protected] writes:

return

end

But then I get an assertion error:

*** Assertion failure in -[NSApplication
_commonBeginModalSessionForWindow:relativeToWindow:modalDelegate:didEndSelector:contextInfo:],
AppKit.subproj/NSApplication.m:3057

In the initial Apple example code there method is marked as (void) and
not an (IBAction), can this method not be called directly?

It’s a callback - you don’t actually connect an event to it, or call it
yourself. In your action method, you’d call:

OSX.NSApp.endSheet_returnCode(@connection, 0)

Then, Cocoa will call your callback, passing along whatever return code
you’ve specified. This allows your action methods to perform whatever
action is specific to the action that was performed, then the callback
does whatever action-neutral cleanup is needed - including sending an
orderOut message to @connection to make it go away.

Also, I have
establised an IB outlet which im guessing the nib is loaded into?

What are you referring to when you say “established an outlet”? Have you
declared it in Ruby with ib_outlets? Have you also connected it in
Interface Builder? I’ve a suspicion that you might have forgotten that
second part, so…

In IB, double-click the “file’s owner” to edit the class definition.
Choose
“Classes/Subclass NSObject”, and enter the name of your Ruby class.
Then,
add the outlet to the class in the “attributes” pane of the inspector
panel.
That doesn’t actually declare your class or add an outlet to it, it
simply
lets IB know about it.

Objective-C programmers can simply drag and drop .h files to do this
step,
or do this step manually and let IB create the .h files, but IB doesn’t
grok scripting languages… so we have to do both steps by hand,
connecting
the outlet in IB and declaring it in our code.

To make the connection, click back over to the “instances” tab. Then,
control-
drag a connection starting with “file’s owner” and ending on the window
you’re
using as a sheet. The inspector panel should switch over to its
“connections”
pane - there, double-click the outlet you just added, or click the
“connect”
button.

Are there any tutorials at all out there on using sheets?!

None that I know of. But then, I’m biased - I wrote CamelBones, and I’ve
only
recently started looking at “other” bridges. :slight_smile:

sherm–

In the initial Apple example code there method is marked as (void) and
not an (IBAction), can this method not be called directly?

I actually meant the code that calls the sheet in the first place? In
there example it seems to be marked as void? If you wanted to call the
sheet from a button click for instance im guessing it would need to be
called by an IBAction?

In IB, double-click the “file’s owner” to edit the class definition.
Choose
“Classes/Subclass NSObject”, and enter the name of your Ruby class.
Then,
add the outlet to the class in the “attributes” pane of the inspector
panel.
That doesn’t actually declare your class or add an outlet to it, it
simply
lets IB know about it.

Ok no problem, I understand letting IB know about new objects you create

  • however in your example you say by subclassing NSObject it will be
    avalible in the file owners connection pane? I thought you normally had
    to instansiate any NSObject subclasses? When I drag from file owner to
    my pannel i only see the file owner outlets

I have declared the outlet called :connection, so i add my demo NSObject
subclass into IB. Without instansiating my new “demo” object, surley I
cant use anything defined on it as there is no instance from which it
can call?

I feel like we are nearly there, its just getting the sheet to present
itself?

Cheers

Tim

Tim P. [email protected] writes:

In the initial Apple example code there method is marked as (void) and
not an (IBAction), can this method not be called directly?

I actually meant the code that calls the sheet in the first place? In
there example it seems to be marked as void? If you wanted to call the
sheet from a button click for instance im guessing it would need to be
called by an IBAction?

Yes, exactly. Button clicks and other GUI events can only call methods
that take one object argument and return void. Obviously, nothing stops
you from implementing such a method as a one-liner that does nothing but
call NSApp’s sheet method.

Ok no problem, I understand letting IB know about new objects you create

  • however in your example you say by subclassing NSObject it will be
    avalible in the file owners connection pane? I thought you normally had
    to instansiate any NSObject subclasses?

You can, but you don’t have to. In your earlier code, you had code that
loaded the NIB and made your object its owner; if you also instantiate
an instance of your class in the NIB itself, you’ll then wind up with
two
instances of your class.

I have declared the outlet called :connection, so i add my demo NSObject
subclass into IB. Without instansiating my new “demo” object, surley I
cant use anything defined on it as there is no instance from which it
can call?

The “file’s owner” icon in IB is just a visual proxy of sorts for
whatever
object you pass as the second argument to loadNibNamed_owner(). It’s
there
so you can make connections to that object.

When you define the class of the “file’s owner”, you’re not creating an
instance of that class. You’re just informing IB what class the NIB’s
owner will belong to, when it’s loaded and assigned an owner.

sherm–

Tim P. [email protected] writes:

Radar – O’Reilly

Does that help at all?

You’re the one asking for help - you tell me. :slight_smile:

sherm–

You’re the one asking for help - you tell me. :slight_smile:

sherm–

LOL!!! good point, give me a little bit of time to re-work where im
too based on that tutorial and i’ll see where im too

Cheers sherm

Tim

Hey I just found this:

Does that help at all?

Cheers

Tim