How to implement an open dialog in a sheet and process its output?

  • Now, I'm pretty new to cocoa, so please have patience with me, but I'm
    having a heck of a time figuring something out.  I have what seems to
    me to be a very simple task, yet I'm struggling with it.  Here it is:

    I have an NSDocument-based application, and I want a certain button
    to, when clicked,  display an "open" dialog sheet that only accepts
    QuickTime movies and then passes the movie the user has chosen into a
    QTMovieView in the active window.  It's primarily the sheet that's
    giving me trouble; I know this sounds stupid, but I need help simply
    creating it in response to some user action.  Is there any easy code
    to simply stick in and tweak slightly that implements the modal sheet
    open dialog that I'm looking for?

    My NSDocument subclass has an instance variable wired up to the
    QTMovieView, but I'm having extreme difficulty getting a movie into
    it.  Once the user selects a movie, will I just dump it into that
    instance variable, or is there more that's required?

    Again, I apologize for my ignorance.  I've been wrestling with this
    stuff for hours and I feel really stupid.

    ---------------------------------
    Nathaniel Gottlieb-Graham
    <sladuuch...>
    techpaladin.com
  • On 12/11/2007, at 5:44 PM, Nathaniel Gottlieb-Graham wrote:

    > Now, I'm pretty new to cocoa, so please have patience with me, but
    > I'm having a heck of a time figuring something out.  I have what
    > seems to me to be a very simple task, yet I'm struggling with it.
    > Here it is:
    >
    > I have an NSDocument-based application, and I want a certain button
    > to, when clicked,  display an "open" dialog sheet that only accepts
    > QuickTime movies and then passes the movie the user has chosen into
    > a QTMovieView in the active window.  It's primarily the sheet
    > that's giving me trouble; I know this sounds stupid, but I need
    > help simply creating it in response to some user action.  Is there
    > any easy code to simply stick in and tweak slightly that implements
    > the modal sheet open dialog that I'm looking for?
    >
    > My NSDocument subclass has an instance variable wired up to the
    > QTMovieView, but I'm having extreme difficulty getting a movie into
    > it.  Once the user selects a movie, will I just dump it into that
    > instance variable, or is there more that's required?
    >
    > Again, I apologize for my ignorance.  I've been wrestling with this
    > stuff for hours and I feel really stupid.
    >

    Hi Nathaniel,

    you're right, it is easy.

    First step, look at the documentation for NSOpenPanel.  You'll see
    the instance method
    beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSel
    ector:contextInfo:.  Because it's an instance method, you first
    create an instance of NSOpenPanel using the class method +
    (NSOpenPanel *)openPanel, which, as the documentation states, creates
    and returns an NSOpenPanel instance.  For example,

    NSOpenPanel *myOpenPanel = [NSOpenPanel openPanel];

    So now configure your open panel however you like.  Look at the
    documentation to find out how.

    Then, note the instance method -filenames.  Using what you get in the
    filenames NSArray, feed your QTMovieView with whatever it needs to
    play the movie.

    If you need more of an explanation, read the topics referenced at the
    top of the NSOpenPanel Class reference document, namely, "Application
    File Management" and "Sheet Programming Topics for Cocoa".  The
    second one is probably what you want to read.

    Hope this helps,

    Ron

    PS.  If you don't already have it, I'd recommend Aaron Hillegass'
    excellent "Cocoa Programming For Mac OS X" book.
  • Thanks Ron, that was a great help.  I now have the following code in
    the .m file, but nothing happens when the button I've wired up to this
    is clicked on.  I know the method is getting called, but the sheet
    never appears.

    - (IBAction)askForQuickTimeMovieSheet:(id)sender {

    NSOpenPanel *panel = [NSOpenPanel openPanel];
    NSArray *fileTypes = [NSArray arrayWithObjects:@"mov", @"mp4",
    @"avi", nil];

    [panel beginSheetForDirectory:@"~Movies/"
                                file:nil
          types:fileTypes
                     modalForWindow:[welcomeWindow window]
        modalDelegate:self
                     didEndSelector:@selector(filePanelDidEnd:
              returnCode:
              contextInfo:)
                         contextInfo:nil];
    }

    -(void)filePanelDidEnd:(NSOpenPanel*)sheet
                returnCode:(int)returnCode
                contextInfo:(void*)contextInfo {
    // Do stuff here as soon as the sheet displays properly
    }

    Thanks again,
    Nathaniel

    > Hi Nathaniel,
    >
    > you're right, it is easy.
    >
    > First step, look at the documentation for NSOpenPanel.  You'll see
    > the instance method
    > beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
    > :.  Because it's an instance method, you first create an instance of
    > NSOpenPanel using the class method + (NSOpenPanel *)openPanel,
    > which, as the documentation states, creates and returns an
    > NSOpenPanel instance.  For example,
    >
    > NSOpenPanel *myOpenPanel = [NSOpenPanel openPanel];
    >
    > So now configure your open panel however you like.  Look at the
    > documentation to find out how.
    >
    > Then, note the instance method -filenames.  Using what you get in
    > the filenames NSArray, feed your QTMovieView with whatever it needs
    > to play the movie.
    >
    >
    > If you need more of an explanation, read the topics referenced at
    > the top of the NSOpenPanel Class reference document, namely,
    > "Application File Management" and "Sheet Programming Topics for
    > Cocoa".  The second one is probably what you want to read.
    >
    >
    > Hope this helps,
    >
    > Ron
    >
    > PS.  If you don't already have it, I'd recommend Aaron Hillegass'
    > excellent "Cocoa Programming For Mac OS X" book.

    ---------------------------------
    Nathaniel Gottlieb-Graham
    Mac specialist
    <sladuuch...>
    techpaladin.com
  • On 13/11/2007, at 6:30 AM, Nathaniel Gottlieb-Graham wrote:

    > Thanks Ron, that was a great help.  I now have the following code
    > in the .m file, but nothing happens when the button I've wired up
    > to this is clicked on.  I know the method is getting called, but
    > the sheet never appears.
    >
    >
    > - (IBAction)askForQuickTimeMovieSheet:(id)sender {
    >
    > NSOpenPanel *panel = [NSOpenPanel openPanel];
    > NSArray *fileTypes = [NSArray arrayWithObjects:@"mov", @"mp4",
    > @"avi", nil];
    >
    > [panel beginSheetForDirectory:@"~Movies/"
    > file:nil
    > types:fileTypes
    > modalForWindow:[welcomeWindow window]
    > modalDelegate:self
    > didEndSelector:@selector(filePanelDidEnd:
    > returnCode:
    > contextInfo:)
    > contextInfo:nil];
    > }
    >
    > -(void)filePanelDidEnd:(NSOpenPanel*)sheet
    > returnCode:(int)returnCode
    > contextInfo:(void*)contextInfo {
    > // Do stuff here as soon as the sheet displays properly
    > }
    >
    > Thanks again,
    > Nathaniel

    Nathaniel,

    I pasted your code into a sandpit project, and the sheet appears
    fine.  Did you actually connect the button to the IBAction in
    Interface Builder?  If you don't know how to do that, you should look
    for a tutorial on the web or at Apple's site.

    Also, the sheet opens at the default Documents folder because the
    value of the first argument to the beginSheet... method is wrong.
    The tilde character is used by shells which expand it to the user's
    home directory.  In a program (ie, not a shell), you'll need to pass
    a real path.  Have a look in the docs for NSHomeDirectory() or
    NSString's -stringByExpandingTildeInPath method.

    Ron
  • No, I know that the button is connected to the IBAction, because I put
    an NSLog() at the beginning of the method definition, and clicking on
    the button does indeed log the string to the console.  While I was
    there, something I noticed the console producing was:
    -[NSWindow window]: unrecognized selector sent to instance 0x12f180

    I get no compiler errors or warnings.  Is this because the selector is
    calling the filePanelDidEnd: method at runtime?  So what's wrong with
    filePanelDidEnd:?  The code I'm using is exactly as shown below.

    Thanks again,
    Nathaniel

    >> - (IBAction)askForQuickTimeMovieSheet:(id)sender {
    >>
    >> NSOpenPanel *panel = [NSOpenPanel openPanel];
    >> NSArray *fileTypes = [NSArray arrayWithObjects:@"mov", @"mp4",
    >> @"avi", nil];
    >>
    >> [panel beginSheetForDirectory:@"~Movies/"
    >> file:nil
    >> types:fileTypes
    >> modalForWindow:[welcomeWindow window]
    >> modalDelegate:self
    >> didEndSelector:@selector(filePanelDidEnd:
    >> returnCode:
    >> contextInfo:)
    >> contextInfo:nil];
    >> }
    >>
    >> -(void)filePanelDidEnd:(NSOpenPanel*)sheet
    >> returnCode:(int)returnCode
    >> contextInfo:(void*)contextInfo {
    >> // Do stuff here as soon as the sheet displays properly
    >> }
    >>
    >> Thanks again,
    >> Nathaniel
    >
    >
    > Nathaniel,
    >
    > I pasted your code into a sandpit project, and the sheet appears
    > fine.  Did you actually connect the button to the IBAction in
    > Interface Builder?  If you don't know how to do that, you should
    > look for a tutorial on the web or at Apple's site.
    >
    > Also, the sheet opens at the default Documents folder because the
    > value of the first argument to the beginSheet... method is wrong.
    > The tilde character is used by shells which expand it to the user's
    > home directory.  In a program (ie, not a shell), you'll need to pass
    > a real path.  Have a look in the docs for NSHomeDirectory() or
    > NSString's -stringByExpandingTildeInPath method.
    >
    > Ron

    ---------------------------------
    Nathaniel Gottlieb-Graham
    Mac specialist
    <sladuuch...>
    techpaladin.com
  • On 13/11/2007, at 8:54 AM, Nathaniel Gottlieb-Graham wrote:

    > No, I know that the button is connected to the IBAction, because I
    > put an NSLog() at the beginning of the method definition, and
    > clicking on the button does indeed log the string to the console.
    > While I was there, something I noticed the console producing was:
    > -[NSWindow window]: unrecognized selector sent to instance 0x12f180
    >
    > I get no compiler errors or warnings.  Is this because the selector
    > is calling the filePanelDidEnd: method at runtime?  So what's wrong
    > with filePanelDidEnd:?  The code I'm using is exactly as shown below.
    >
    > Thanks again,
    > Nathaniel

    Sorry, but it's unclear whether you actually made the connection --
    in Interface Builder -- between your button and the IBAction.  You
    "know" that it's being called, but did you Control-drag from the
    button to the IBAction in Interface Builder?  (I'm resisting the urge
    to write out that question in capitals.)

    The "unrecognized selector" warning means that your code is sending a
    message to an instance of NSWindow which the window doesn't
    understand.  This usually means that you are sending a message to an
    object that is no longer in existance or is out of scope when the
    message is sent.  The window receiving the message just happens to be
    at the address (0x12f180) where your intended object was.  Or you are
    sending the message to the NSWindow intentionally but haven't
    implemented the selector method in that window instance, for which
    you would need to subclass NSWindow or add a category which
    implements the method.

    Where is your IBAction method -askForQuickTimeMovieSheet: located?

    Like I said, I simply copied your code and pasted it into a small
    project and it worked.  The only change I had to make was to replace
    your [welcomeWindow window] with (in my case) [NSApp mainWindow].
    And, of course, I made Interface Builder aware of the changes to the
    object where I pasted the code and then Control-dragged from a button
    on the window to the action in the instantiated object in Interface
    Builder's main window.  Perhaps your welcomeWindow instance is the
    cause of your problem?

    Good luck,

    Ron
  • > Sorry, but it's unclear whether you actually made the connection --
    > in Interface Builder -- between your button and the IBAction.  You
    > "know" that it's being called, but did you Control-drag from the
    > button to the IBAction in Interface Builder?  (I'm resisting the
    > urge to write out that question in capitals.)

    YES I DID CONTROL-DRAG IN IB.  ;-)

    > Like I said, I simply copied your code and pasted it into a small
    > project and it worked.  The only change I had to make was to replace
    > your [welcomeWindow window] with (in my case) [NSApp mainWindow].
    > And, of course, I made Interface Builder aware of the changes to the
    > object where I pasted the code and then Control-dragged from a
    > button on the window to the action in the instantiated object in
    > Interface Builder's main window.  Perhaps your welcomeWindow
    > instance is the cause of your problem?

    You were right.  As soon as I changed [welcomeWindow window] to [NSApp
    window] is started working perfectly!  The problem was this:
    welcomeWindow is an IBOutlet to the window itself, so it was redundant
    to call [welcomeWindow window]; I could have used welcomeWindow all on
    its own as an argument for modalForWindow:, and when I did this, it
    also worked.

    Thank you so much for all your help and your extraordinary patience!

    Nathaniel

    ---------------------------------
    Nathaniel Gottlieb-Graham
    Mac specialist
    <sladuuch...>
    techpaladin.com
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today