1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/cocoa/filedlg.mm
3// Purpose:     wxFileDialog for wxCocoa
4// Author:      Ryan Norton
5// Modified by:
6// Created:     2004-10-02
7// Copyright:   (c) Ryan Norton
8// Licence:     wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#if wxUSE_FILEDLG
23
24#include "wx/filedlg.h"
25
26#ifndef WX_PRECOMP
27    #include "wx/msgdlg.h"
28    #include "wx/app.h"
29#endif
30
31#include "wx/filename.h"
32
33#include "wx/cocoa/autorelease.h"
34#include "wx/cocoa/string.h"
35#include "wx/modalhook.h"
36
37#import <AppKit/NSOpenPanel.h>
38#import <AppKit/NSSavePanel.h>
39
40#import <Foundation/NSArray.h>
41// ============================================================================
42// implementation
43// ============================================================================
44
45IMPLEMENT_CLASS(wxCocoaFileDialog, wxFileDialogBase)
46
47// ----------------------------------------------------------------------------
48// wxFileDialog
49// ----------------------------------------------------------------------------
50
51wxFileDialog::wxFileDialog(wxWindow *parent,
52                           const wxString& message,
53                           const wxString& defaultDir,
54                           const wxString& defaultFileName,
55                           const wxString& wildCard,
56                           long style,
57                           const wxPoint& pos,
58                           const wxSize& sz,
59                           const wxString& name)
60            : wxFileDialogBase(parent, message, defaultDir, defaultFileName,
61                               wildCard, style, pos, sz, name)
62{
63    wxTopLevelWindows.Append(this);
64
65    wxASSERT(CreateBase(parent,wxID_ANY,pos,wxDefaultSize,style,wxDefaultValidator,wxDialogNameStr));
66
67    if ( parent )
68        parent->AddChild(this);
69
70    m_cocoaNSWindow = nil;
71    m_cocoaNSView = nil;
72
73    //Init the wildcard array
74    m_wildcards = [[NSMutableArray alloc] initWithCapacity:0];
75
76    //If the user requests to save - use a NSSavePanel
77    //else use a NSOpenPanel
78    if (HasFlag(wxFD_SAVE))
79    {
80        SetNSPanel([NSSavePanel savePanel]);
81
82        [GetNSSavePanel() setTitle:wxNSStringWithWxString(message)];
83
84        [GetNSSavePanel() setPrompt:@"Save"];
85        [GetNSSavePanel() setTreatsFilePackagesAsDirectories:YES];
86        [GetNSSavePanel() setCanSelectHiddenExtension:YES];
87
88//        Cached as per-app in obj-c
89//        [GetNSSavePanel() setExtensionHidden:YES];
90
91        //
92        // NB:  Note that only Panther supports wildcards
93        // with save dialogs - not that wildcards in save
94        // dialogs are all that useful, anyway :)
95        //
96    }
97    else //m_dialogStyle & wxFD_OPEN
98    {
99        SetNSPanel([NSOpenPanel openPanel]);
100        [m_cocoaNSWindow setTitle:wxNSStringWithWxString(message)];
101
102        [(NSOpenPanel*)m_cocoaNSWindow setAllowsMultipleSelection:(HasFlag(wxFD_MULTIPLE))];
103        [(NSOpenPanel*)m_cocoaNSWindow setResolvesAliases:YES];
104        [(NSOpenPanel*)m_cocoaNSWindow setCanChooseFiles:YES];
105        [(NSOpenPanel*)m_cocoaNSWindow setCanChooseDirectories:NO];
106        [GetNSSavePanel() setPrompt:@"Open"];
107
108        //convert wildcards - open panel only takes file extensions -
109        //no actual wildcards here :)
110        size_t lastwcpos = 0;
111        bool bDescription = true;
112        size_t i;
113        for(i = wildCard.find('|');
114                i != wxString::npos;
115                i = wildCard.find('|', lastwcpos+1))
116        {
117            size_t oldi = i;
118
119            if(!bDescription)
120            {
121                bDescription = !bDescription;
122
123                //work backwards looking for a period
124                while(i != lastwcpos && wildCard[--i] != '.') {}
125
126                if(i == lastwcpos)
127                {
128                    //no extension - can't use this wildcard
129                    lastwcpos = oldi;
130                    continue;
131                }
132
133                [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
134            }
135            else
136                bDescription = !bDescription;
137            lastwcpos = oldi;
138        }
139
140        if (!bDescription)
141        {
142            //get last wildcard
143            size_t oldi = wildCard.length();
144            i = oldi;
145
146            //work backwards looking for a period
147            while(i != lastwcpos && wildCard[--i] != '.') {}
148
149            if(i != lastwcpos)
150                [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
151        }
152
153        if ([m_wildcards count] == 0)
154        {
155            [m_wildcards release];
156            m_wildcards = nil;
157        }
158    }
159}
160
161wxFileDialog::~wxFileDialog()
162{
163    [m_wildcards release];
164}
165
166void wxFileDialog::GetPaths(wxArrayString& paths) const
167{
168    paths.Empty();
169
170    wxString dir(m_dir);
171    if ( m_dir.Last() != wxT('\\') )
172        dir += wxT('\\');
173
174    size_t count = m_fileNames.GetCount();
175    for ( size_t n = 0; n < count; n++ )
176    {
177        if (wxFileName(m_fileNames[n]).IsAbsolute())
178            paths.Add(m_fileNames[n]);
179        else
180            paths.Add(dir + m_fileNames[n]);
181    }
182}
183
184void wxFileDialog::GetFilenames(wxArrayString& files) const
185{
186    files = m_fileNames;
187}
188
189void wxFileDialog::SetPath(const wxString& path)
190{
191    wxString ext;
192    wxFileName::SplitPath(path, &m_dir, &m_fileName, &ext);
193    if ( !ext.empty() )
194        m_fileName << wxT('.') << ext;
195}
196
197int wxFileDialog::ShowModal()
198{
199    WX_HOOK_MODAL_DIALOG();
200
201    wxAutoNSAutoreleasePool thePool;
202
203    m_fileNames.Empty();
204
205    int nResult;
206
207    if (HasFlag(wxFD_SAVE))
208    {
209        nResult = [GetNSSavePanel()
210                    runModalForDirectory:wxNSStringWithWxString(m_dir)
211                    file:wxNSStringWithWxString(m_fileName)];
212
213        if (nResult == NSOKButton)
214        {
215            m_fileNames.Add(wxStringWithNSString([GetNSSavePanel() filename]));
216            m_path = m_fileNames[0];
217        }
218    }
219    else //m_dialogStyle & wxFD_OPEN
220    {
221        nResult = [(NSOpenPanel*)m_cocoaNSWindow
222                    runModalForDirectory:wxNSStringWithWxString(m_dir)
223                    file:wxNSStringWithWxString(m_fileName)
224                    types:m_wildcards];
225
226        if (nResult == NSOKButton)
227        {
228            for(unsigned i = 0; i < [[(NSOpenPanel*)m_cocoaNSWindow filenames] count]; ++i)
229            {
230                m_fileNames.Add(wxStringWithNSString([[(NSOpenPanel*)m_cocoaNSWindow filenames] objectAtIndex:(i)]));
231            }
232
233            m_path = m_fileNames[0];
234        }
235    }
236
237    return nResult == NSOKButton ? wxID_OK : wxID_CANCEL;
238}
239
240#endif // wxUSE_FILEDLG
241