Mac Display sheet after drag?

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
I'm trying to display a window as a sheet after a drag operation onto my main window. I'm not sure what the problem is, but the error 'Modal session requires modal window' makes me think that calling a method in another class to call the sheet from the dragOperationConclusion method is a bad idea (i.e the operation hasn't concluded, therefore it's not modal and can't display a sheet. But then, how do you get it to display a sheet if you can't call out from the conclusion method?).

I am writing this using cocoa-java, but I have no problem accepting code in the form of ObjC for me to translate.

Thanks.
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
reikon said:
I'm trying to display a window as a sheet after a drag operation onto my main window. I'm not sure what the problem is, but the error 'Modal session requires modal window' makes me think that calling a method in another class to call the sheet from the dragOperationConclusion method is a bad idea (i.e the operation hasn't concluded, therefore it's not modal and can't display a sheet. But then, how do you get it to display a sheet if you can't call out from the conclusion method?).

I am writing this using cocoa-java, but I have no problem accepting code in the form of ObjC for me to translate.

Thanks.
Can you show us the bit of code where you show the sheet?
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
Of course.

I use Apple's JDragNDrop example's code in a custom view, and in the concludeDragOperation method i call

Code:
DropHandler instanceHandler = new DropHandler();
            instanceHandler.ProcessDroppedFiles(filenames);
And in the ProcessDroppedFilenames method I've tried several ways of calling the sheet.

This is what i'm using the call the sheet as an "IBAction".

Code:
NSApplication nsapp=NSApplication.sharedApplication();
        nsapp.beginSheet(encipherPanel, mainWindow, null, null, null);
        nsapp.runModalForWindow(encipherPanel);
        nsapp.endSheet(encipherPanel);
        encipherPanel.orderOut(this);
This works when I put it as an action to a button...but as stated, not on a drag. Even if I create a new instance of my sheetcontroller class and call the sheet with a null argument.

Thanks for the reply.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,015
315
Harrogate
1) Are you sure encipherPanel!=null? Can you start a modal session for a sheet? Do you not start it for the window the sheet is attached to?

2) The docs do not say that the third parameter is optional.
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
robbieduncan said:
1) Are you sure encipherPanel!=null? Can you start a modal session for a sheet? Do you not start it for the window the sheet is attached to?

2) The docs do not say that the third parameter is optional.
As stated previously, the code works like a dream when used as an action attached to an object (read as: button). Therefore i think it has to be something to do with the drag not being concluded. encipherPanel isn't null, and is an NSPanel Object. Thanks for the reply.

EDIT: Supposedly I hav eot use performSelector..but I can't find any actual examples of use anywhere...anyone have any ideas?
 

HiRez

macrumors 603
Jan 6, 2004
5,872
1,855
Western US
reikon said:
As stated previously, the code works like a dream when used as an action attached to an object (read as: button). Therefore i think it has to be something to do with the drag not being concluded. encipherPanel isn't null, and is an NSPanel Object. Thanks for the reply.

EDIT: Supposedly I hav eot use performSelector..but I can't find any actual examples of use anywhere...anyone have any ideas?
The performSelector: methods simply send a message to an object just like you were calling the method directly, but they can do it after a delay, after the current method has exited the current scope, or from other threads and modes. I think you are right in thinking it's because you're inside a callback of an unconcluded drag operation. I have had instances where I needed to use this technique to get around calling from a method invoked by something else, including during sheet operations. In one app, I have a method that takes an NSTimer, invalidates it, and destroys it. But, it fails if I call that method from the method that the timer itself calls. That sounds like something similar to your drag callbacks. I would try using
Code:
[self performSelector:@selector(myDoStuffHereMethod) withObject:nil afterDelay:0];

-- or --

[[NSRunLoop currentRunLoop] performSelector:@selector(myDoStuffHereMethod) target:self argument:nil order:0 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
HiRez said:
The performSelector: methods simply send a message to an object just like you were calling the method directly, but they can do it after a delay, after the current method has exited the current scope, or from other threads and modes. I think you are right in thinking it's because you're inside a callback of an unconcluded drag operation. I have had instances where I needed to use this technique to get around calling from a method invoked by something else, including during sheet operations. In one app, I have a method that takes an NSTimer, invalidates it, and destroys it. But, it fails if I call that method from the method that the timer itself calls. That sounds like something similar to your drag callbacks. I would try using
Code:
[self performSelector:@selector(myDoStuffHereMethod) withObject:nil afterDelay:0];

-- or --

[[NSRunLoop currentRunLoop] performSelector:@selector(myDoStuffHereMethod) target:self argument:nil order:0 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
Thanks a lot! The problem I find, is...I can't find the performSelector method...I don't think Cocoa Java has it...The only documentation I can find is it using com.webobjects.foundation, which I don't have and can't install since I don't have iLife 05 which is required. It looks like I'm going to have to either figure out where Apple is hiding this crap (I don't think I've seen more poor documentation for an API than Cocoa Java) or write a method that wraps the performSelector method in Java, allowing me to call it. This is getting to be a lot more harder than I thougth it would be.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,571
654
Cork, Ireland.
reikon said:
Thanks a lot! The problem I find, is...I can't find the performSelector method...I don't think Cocoa Java has it...The only documentation I can find is it using com.webobjects.foundation, which I don't have and can't install since I don't have iLife 05 which is required. It looks like I'm going to have to either figure out where Apple is hiding this crap (I don't think I've seen more poor documentation for an API than Cocoa Java) or write a method that wraps the performSelector method in Java, allowing me to call it. This is getting to be a lot more harder than I thougth it would be.
I think you're right, it doesn't seem to be available in Java.

You could probably achieve the same result using an NSTimer, just start a timer with a short interval, and when it fires, you can call the method in the normal way then.
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
Having checked the NSObject docs for Java and Objective-C there's a load missing from the Java version. The thing is Apple doesn't really care about the 'Java bridge' anymore. See this quote

Cocoa-Java technology is only a learning tool. Applications targeted for release to customers must be developed using Objective-C to take advantage of all the programming interfaces available in Cocoa. Programming interfaces added to Cocoa in Mac OS X versions later than 10.4 will not be available to Cocoa-Java applications.
which can be found here.
 

HiRez

macrumors 603
Jan 6, 2004
5,872
1,855
Western US
If performSelector: is not available, and using a timer doesn't work, maybe try to schedule the window action on the AWT event thread using the Java method SwingUtilities.invokeLater()? I know that (at least in the old days) there were some issues with calling Swing GUI components from the event thread. How Cocoa-Java works in this regard I have no idea, but maybe try something like this (called from your drag method):
Code:
Runnable doStuff = new Runnable() {
    public void run() {
        // do stuff here
    }
};

SwingUtilities.invokeLater(doStuff);
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
This is really killing me. Using a NSTimer does nothing. I delay the timer for as long as 10 seconds and the thing fires and gives me an error. The same error to boot.

I'll try using Swing's invokeLater.
Having checked the NSObject docs for Java and Objective-C there's a load missing from the Java version. The thing is Apple doesn't really care about the 'Java bridge' anymore. See this quote
I am aware Apple is trying to force everyone who wants to do almost anything in Cocoa to use Objective-C/++ (or AppleScript). I think thats stupid, personally.
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
If it doesn't work with a timer, then something else must be wrong. You're definitely no longer in some kind of drag-mode.
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
reikon said:
I am aware Apple is trying to force everyone who wants to do almost anything in Cocoa to use Objective-C/++ (or AppleScript). I think thats stupid, personally.
Because you're a Java programmer? If you're Apple, wasting your time keeping up a Java bridge that very few people use for production apps seems a waste of time and money. Should they maintain a Cobol-bridge as well just to keep cobol old-timers happy?
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
reikon said:
Code:
NSApplication nsapp=NSApplication.sharedApplication();
nsapp.beginSheet(encipherPanel, mainWindow, null, null, null);
nsapp.runModalForWindow(encipherPanel);
nsapp.endSheet(encipherPanel);
encipherPanel.orderOut(this);
According to Apple's "How to use Sheets documentation" your code isn't as it should be. Docs -> Cocoa -> User Experience -> Sheets

To show the sheet, just the two first lines should be sufficient.

To close the sheet, listen to actions from a button or something similar and call
Code:
nsapp.endSheet(encipherPanel)
there.

Then you need to order the sheet out when the endSheet is done, in Objective C you would have set a didEndSelector where this is done, but I don't know how to do that in Java.

Your third line shouldn't be anywhere at all if I read the docs correctly.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,571
654
Cork, Ireland.
I'm not at all familiar with Java-Cocoa (nor much with sheets either), but the code above looks a little strange to me. runModalForWindow has been deprecated, and in the example above looks redundant. What occurs if you comment out that line?

Oops, gekko513 beat me to it..
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
gekko513 said:
According to Apple's "How to use Sheets documentation" your code isn't as it should be. Docs -> Cocoa -> User Experience -> Sheets

To show the sheet, just the two first lines should be sufficient.

To close the sheet, listen to actions from a button or something similar and call
Code:
nsapp.endSheet(encipherPanel)
there.

Then you need to order the sheet out when the endSheet is done, in Objective C you would have set a didEndSelector where this is done, but I don't know how to do that in Java.

Your third line shouldn't be anywhere at all if I read the docs correctly.
Like I said...it works fine when called from a button. Even if it is depreciated, so is the Cocoa-Java bridge, and therefore it may require it.

caveman_uk said:
Because you're a Java programmer? If you're Apple, wasting your time keeping up a Java bridge that very few people use for production apps seems a waste of time and money. Should they maintain a Cobol-bridge as well just to keep cobol old-timers happy?
I'm not just a Java programmer. I'm using Java because I already wrote the implementation of the cipher I'm using, and cipher mode in Java, and I don't want to mess with endians or pointers doing it in C, and then wrapping it in Objective-C objects.

I find it very odd for you to compare a legacy language to Java.

If you look at a company like Microsoft, they have C#, J#, etc which they not only maintain, but document thoroughly.

I just feel that by limiting the languages that can access the primary API, you're limiting the number of applications for your platform.

In addition, very few people use it because there is no documentation for it. There are no real examples. I've talked to dozons of Java programmers who've tried and given up on Cocoa Java...not because they didn't know Java well, but because they couldn't figure out Cocoa Java due to lack of documentation and examples.

I have an idea of what is wrong with my program. I'll re-do a few things, and see if I can get it to work.

Thanks to all who have replied up to this point. I'll keep you informed on how it goes.
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
reikon said:
Like I said...it works fine when called from a button. Even if it is depreciated, so is the Cocoa-Java bridge, and therefore it may require it.
Yeah, but have you tried writing it the way Apple describes on those pages?
 

whooleytoo

macrumors 604
Aug 2, 2002
6,571
654
Cork, Ireland.
reikon said:
Like I said...it works fine when called from a button. Even if it is depreciated, so is the Cocoa-Java bridge, and therefore it may require it.
But runModalForWindow was superceded by beginSheet; according to the documentation there's no need to call both. Even though the code you have may work in some cases, it still doesn't necessarily mean it's correct.

I'd try it as per Apple's docs, as gekko513 advises.
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
I found my problem, but still have no solution. After the NSTimer fires all my UI objects are set to null. So in effect I'm telling a null object to display a sheet on a null object.

When I derrive the windows from the array of windows, it works smooth as a hot knife through butter. Any ideas why all my UI objects become null, and how to fix that without going to the NSApp's window array and choosing them specifically? (I've been told you can't relay on the ordering of the windows in the array, etc)

Thanks for the replies.
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
How do you keep the reference to the Window in question? Does the Cocoa-Java bridge require you to retain Cocoa objects you want to keep or is it all handled by Java's garbage collection?
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
gekko513 said:
How do you keep the reference to the Window in question? Does the Cocoa-Java bridge require you to retain Cocoa objects you want to keep or is it all handled by Java's garbage collection?
You link the objects through outlets in IB and they're declared in the instance you connect them to.

So I have a list of objects in my Controller class..

Code:
    public NSWindow window; /* IBOutlet */
    public NSImageView imageWell;
    public NSPanel progressPanel; /* IBOutlet */
and so on.

I _hope_ they're not getting picked up by Java's gc. I don't see any reason why they would be...

I've tried setting it back using an object in the window on awakeFromNib. aka

Code:
window = imageWell.window()
And it goes null as soon as the timer fires.

Right now I'm stuck doing this:

But I least I know the actual code for calling the sheet isn't wrong.

Code:
NSArray windows = NSApplication.sharedApplication().windows();
        NSWindow window = (NSWindow) windows.objectAtIndex(0);
        NSWindow window1 = (NSWindow) windows.objectAtIndex(1);
        NSApplication nsapp=NSApplication.sharedApplication();
        nsapp.beginSheet(window1, window, this, null, null);
        nsapp.runModalForWindow(window1);
        nsapp.endSheet(window1);
        window1.orderOut(this);
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
Then I also see no reason why the references should all of a sudden be null. I can't see more solutions without seeing and playing with the code I think.

I still think the sheet code is a bit weird even if it works. Are you sure you need the line: nsapp.runModalForWindow(window1);?
 

reikon

macrumors newbie
Original poster
Jan 15, 2006
20
0
gekko513 said:
Then I also see no reason why the references should all of a sudden be null. I can't see more solutions without seeing and playing with the code I think.

I still think the sheet code is a bit weird even if it works. Are you sure you need the line: nsapp.runModalForWindow(window1);?
PM your e-mail to me and I'll send you my project if you like, I can't guarantee it'll be pretty seeing as I've been at this for a while and have tried lots of things.

I'll try removing the runModalForWindow to see if it works without it.

EDIT: removing runModalForWindow causes the app to crash. Or rather exit with status 0 without notice :p
 

gekko513

macrumors 603
Oct 16, 2003
6,302
1
reikon said:
PM your e-mail to me and I'll send you my project if you like, I can't guarantee it'll be pretty seeing as I've been at this for a while and have tried lots of things.

I'll try removing the runModalForWindow to see if it works without it.

EDIT: removing runModalForWindow causes the app to crash. Or rather exit with status 0 without notice :p
How rude of it. ;) Well, then I guess you have to keep it there. It's still strange, since it doesn't seem to be right according to the docs. (I sent you a PM)
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
reikon said:
I find it very odd for you to compare a legacy language to Java.

If you look at a company like Microsoft, they have C#, J#, etc which they not only maintain, but document thoroughly.

I just feel that by limiting the languages that can access the primary API, you're limiting the number of applications for your platform.
I wasn't saying cobol was as modern as Java. I was trying to point out where do you draw the line on what languages you support. Apple supports two API's (Cocoa and Carbon) - one primarily for objective-C and the other primarily for C and C++ (I know you can mix and match if you want). There are a number of third party bridges to the Apple APIs (for example PyObjC) so you aren't exactly limited to just the languages Apple chooses to support. It is also worth bearing in mind that Microsoft has an awful lot more developers and money to throw at keeping their range of languages maintained. They also charge for their developer tools - hundreds of dollars if you want the grown up editions - whilst Apple gives it all away for nothing.

Besides I would have thought the main reason for using Java (other than you know it already or have assets already written in it) would be it's platform independence. By using java with Cocoa you've lost that advantage so all you're left with is it's disadvantages. There are alternatives to Cocoa you could use in Java that would retain your platform independence.

Cocoa is designed to be used by objective-C and it's littered with design decisions made on that assumption. Those assumptions don't necessarily apply to Java which has it's own way of doing things. Consequently the Java-cocoa bridge was always going to be the bastard child that no-one loved.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.