Display sheet after drag?

Discussion in 'Mac Programming' started by reikon, Jan 15, 2006.

  1. macrumors newbie

    Joined:
    Jan 15, 2006
    #1
    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.
     
  2. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #2
    Can you show us the bit of code where you show the sheet?
     
  3. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #3
    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.
     
  4. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    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.
     
  5. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #5
    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?
     
  6. macrumors 601

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #6
    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]];
     
  7. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #7
    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.
     
  8. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #8
    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.
     
  9. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #9
    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

    which can be found here.
     
  10. macrumors 601

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #10
    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);
     
  11. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #11
    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.
    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.
     
  12. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #12
    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.
     
  13. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #13
    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?
     
  14. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #14
    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.
     
  15. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #15
    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..
     
  16. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #16
    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.

    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.
     
  17. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #17
    Yeah, but have you tried writing it the way Apple describes on those pages?
     
  18. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #18
    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.
     
  19. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #19
    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.
     
  20. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #20
    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?
     
  21. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #21
    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);
     
  22. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #22
    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);?
     
  23. thread starter macrumors newbie

    Joined:
    Jan 15, 2006
    #23
    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
     
  24. macrumors 603

    gekko513

    Joined:
    Oct 16, 2003
    #24
    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)
     
  25. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #25
    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.
     

Share This Page