1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/mac/carbon/dirdlg.cpp
3// Purpose:     wxDirDialog
4// Author:      Stefan Csomor
5// Modified by:
6// Created:     1998-01-01
7// RCS-ID:      $Id: dirdlg.cpp 57849 2009-01-06 09:36:54Z SC $
8// Copyright:   (c) Stefan Csomor
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
14#if wxUSE_DIRDLG
15
16#include "wx/dirdlg.h"
17
18#ifndef WX_PRECOMP
19    #include "wx/utils.h"
20    #include "wx/dialog.h"
21    #include "wx/cmndata.h"
22#endif // WX_PRECOMP
23
24#include "wx/filename.h"
25
26#include "wx/mac/private.h"
27
28#ifdef __DARWIN__
29    #include <Carbon/Carbon.h>
30#else
31    #include <Navigation.h>
32#endif
33
34IMPLEMENT_CLASS(wxDirDialog, wxDialog)
35
36static pascal void NavEventProc(
37                                NavEventCallbackMessage inSelector,
38                                NavCBRecPtr ioParams,
39                                NavCallBackUserData ioUserData );
40
41static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
42
43static pascal void NavEventProc(
44                                NavEventCallbackMessage inSelector,
45                                NavCBRecPtr ioParams,
46                                NavCallBackUserData ioUserData )
47{
48    wxDirDialog * data = ( wxDirDialog *) ioUserData ;
49    if ( inSelector == kNavCBStart )
50    {
51        if (data && !data->GetPath().empty() )
52        {
53            // Set default location for the modern Navigation APIs
54            // Apple Technical Q&A 1151
55            FSRef theFile;
56            wxMacPathToFSRef(data->GetPath(), &theFile);
57            AEDesc theLocation = { typeNull, NULL };
58            if (noErr == ::AECreateDesc(typeFSRef, &theFile, sizeof(FSRef), &theLocation))
59                 ::NavCustomControl(ioParams->context, kNavCtlSetLocation, (void *) &theLocation);
60        }
61    }
62}
63
64wxDirDialog::wxDirDialog(wxWindow *parent,
65                         const wxString& message,
66                         const wxString& defaultPath,
67                         long style,
68                         const wxPoint& WXUNUSED(pos),
69                         const wxSize& WXUNUSED(size),
70                         const wxString& WXUNUSED(name))
71{
72    wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
73    m_message = message;
74    m_parent = parent;
75    m_path = defaultPath;
76}
77
78int wxDirDialog::ShowModal()
79{
80    NavDialogRef dialog = NULL;
81    NavDialogCreationOptions options;
82    NavReplyRecord reply ;
83    bool disposeReply = false ;
84    OSStatus err = noErr;
85
86    err = NavGetDefaultDialogCreationOptions(&options);
87    options.optionFlags &= ~kNavAllowMultipleFiles;
88    if (err == noErr)
89    {
90        wxMacCFStringHolder message(m_message, GetFont().GetEncoding());
91        options.message = message;
92        err = NavCreateChooseFolderDialog(&options, sStandardNavEventFilter , NULL,  this , &dialog);
93        if (err == noErr)
94        {
95            err = NavDialogRun(dialog);
96            if ( err == noErr )
97            {
98                err = NavDialogGetReply(dialog, &reply);
99                disposeReply = true ;
100            }
101        }
102    }
103
104    if ( err == noErr )
105    {
106        if ( reply.validRecord )
107        {
108            FSRef folderInfo;
109            AEDesc specDesc ;
110
111            OSErr err = ::AECoerceDesc( &reply.selection , typeFSRef, &specDesc);
112            if ( err != noErr )
113            {
114                m_path = wxEmptyString ;
115            }
116            else
117            {
118                folderInfo = **(FSRef**) specDesc.dataHandle;
119                m_path = wxMacFSRefToPath( &folderInfo ) ;
120                if (specDesc.dataHandle != nil)
121                {
122                    ::AEDisposeDesc(&specDesc);
123                }
124            }
125        }
126        else
127        {
128            err = paramErr ; // could be any error, only used for giving back wxID_CANCEL
129        }
130    }
131
132    if ( disposeReply )
133        ::NavDisposeReply(&reply);
134
135    // apparently cancelling shouldn't change m_path
136    if ( err != noErr && err != userCanceledErr )
137        m_path = wxEmptyString ;
138
139	if ( dialog )
140    	::NavDialogDispose(dialog);
141
142    return (err == noErr) ? wxID_OK : wxID_CANCEL ;
143}
144
145#endif
146