1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-14 09:03:54 +01:00

Cleaning up lib-src

FileDialog goes into audacity/src/widgets and the mod-* directories go into
audacity/modules.

This leaves nothing in lib-src that isn't a 3rd-party libs or supporting
files.
This commit is contained in:
Leland Lucius
2020-05-24 16:21:26 -05:00
parent bf8387327e
commit 30dbdf40a9
73 changed files with 12788 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
/**********************************************************************
Audacity: A Digital Audio Editor
FileDialog.cpp
Leland Lucius
*******************************************************************//**
\class FileDialog
\brief Dialog used to present platform specific "Save As" dialog with
custom controls.
*//*******************************************************************/
#include "FileDialog.h"
FileDialogBase::FileDialogBase()
{
m_creator = NULL;
m_userdata = 0;
}
bool FileDialogBase::HasUserPaneCreator() const
{
return m_creator != NULL;
}
void FileDialogBase::SetUserPaneCreator(UserPaneCreatorFunction creator, wxUIntPtr userdata)
{
m_creator = creator;
m_userdata = userdata;
}
void FileDialogBase::CreateUserPane(wxWindow *parent)
{
if (m_creator)
{
(*m_creator)(parent, m_userdata);
}
}
//
// Copied from wx 3.0.2 and modified to support additional features
//
/////////////////////////////////////////////////////////////////////////////
// Name: src/common/fldlgcmn.cpp
// Purpose: wxFileDialog common functions
// Author: John Labenski
// Modified by: Leland Lucius
// Created: 14.06.03 (extracted from src/*/filedlg.cpp)
// Copyright: (c) Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// FileDialog convenience functions
//----------------------------------------------------------------------------
wxString FileSelector(const wxString& title,
const wxString& defaultDir,
const wxString& defaultFileName,
const wxString& defaultExtension,
const wxString& filter,
int flags,
wxWindow *parent,
int x, int y)
{
// The defaultExtension, if non-empty, is
// appended to the filename if the user fails to type an extension. The new
// implementation (taken from FileSelectorEx) appends the extension
// automatically, by looking at the filter specification. In fact this
// should be better than the native Microsoft implementation because
// Windows only allows *one* default extension, whereas here we do the
// right thing depending on the filter the user has chosen.
// If there's a default extension specified but no filter, we create a
// suitable filter.
wxString filter2;
if ( !defaultExtension.empty() && filter.empty() )
filter2 = wxString(wxT("*.")) + defaultExtension;
else if ( !filter.empty() )
filter2 = filter;
FileDialog fileDialog(parent, title, defaultDir,
defaultFileName, filter2,
flags, wxPoint(x, y));
// if filter is of form "All files (*)|*|..." set correct filter index
if ( !defaultExtension.empty() && filter2.find(wxT('|')) != wxString::npos )
{
int filterIndex = 0;
wxArrayString descriptions, filters;
// don't care about errors, handled already by FileDialog
(void)wxParseCommonDialogsFilter(filter2, descriptions, filters);
for (size_t n=0; n<filters.GetCount(); n++)
{
if (filters[n].Contains(defaultExtension))
{
filterIndex = n;
break;
}
}
if (filterIndex > 0)
fileDialog.SetFilterIndex(filterIndex);
}
wxString filename;
if ( fileDialog.ShowModal() == wxID_OK )
{
filename = fileDialog.GetPath();
}
return filename;
}
//----------------------------------------------------------------------------
// FileSelectorEx
//----------------------------------------------------------------------------
wxString FileSelectorEx(const wxString& title,
const wxString& defaultDir,
const wxString& defaultFileName,
int* defaultFilterIndex,
const wxString& filter,
int flags,
wxWindow* parent,
int x,
int y)
{
FileDialog fileDialog(parent,
title,
defaultDir,
defaultFileName,
filter,
flags, wxPoint(x, y));
wxString filename;
if ( fileDialog.ShowModal() == wxID_OK )
{
if ( defaultFilterIndex )
*defaultFilterIndex = fileDialog.GetFilterIndex();
filename = fileDialog.GetPath();
}
return filename;
}

View File

@@ -0,0 +1,96 @@
/**********************************************************************
Audacity: A Digital Audio Editor
FileDialog.h
Leland Lucius
*******************************************************************//**
\class FileDialog
\brief Dialog used to present platform specific "Save As" dialog with
custom controls.
*//*******************************************************************/
#ifndef _FILEDIALOG_H_
#define _FILEDIALOG_H_
#include <wx/filedlg.h> // to inherit
#ifndef AUDACITY_DLL_API
#define AUDACITY_DLL_API
#endif
class AUDACITY_DLL_API FileDialogBase : public wxFileDialogBase
{
public:
FileDialogBase();
virtual ~FileDialogBase() {};
// FileDialogBase
typedef void (*UserPaneCreatorFunction)(wxWindow *parent, wxUIntPtr userdata);
virtual bool HasUserPaneCreator() const;
virtual void SetUserPaneCreator(UserPaneCreatorFunction creator, wxUIntPtr userdata);
virtual void SetFileExtension(const wxString& extension) {};
protected:
void CreateUserPane(wxWindow *parent);
UserPaneCreatorFunction m_creator;
wxUIntPtr m_userdata;
};
#if defined(__WXGTK__)
#include "gtk/FileDialogPrivate.h"
#elif defined(__WXMAC__)
#include "mac/FileDialogPrivate.h"
#elif defined(__WXMSW__)
#include "win/FileDialogPrivate.h"
#else
#error Unknown implementation
#endif
//
// Copied from wx 3.0.2 and modified to support additional features
//
/////////////////////////////////////////////////////////////////////////////
// Name: wx/filedlg.h
// Purpose: wxFileDialog base header
// Author: Robert Roebling
// Modified by: Leland Lucius
// Created: 8/17/99
// Copyright: (c) Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// FileDialog convenience functions
//----------------------------------------------------------------------------
wxString
FileSelector(const wxString& message = wxFileSelectorPromptStr,
const wxString& default_path = wxEmptyString,
const wxString& default_filename = wxEmptyString,
const wxString& default_extension = wxEmptyString,
const wxString& wildcard = wxFileSelectorDefaultWildcardStr,
int flags = 0,
wxWindow *parent = NULL,
int x = wxDefaultCoord, int y = wxDefaultCoord);
// An extended version of FileSelector
wxString
FileSelectorEx(const wxString& message = wxFileSelectorPromptStr,
const wxString& default_path = wxEmptyString,
const wxString& default_filename = wxEmptyString,
int *indexDefaultExtension = NULL,
const wxString& wildcard = wxFileSelectorDefaultWildcardStr,
int flags = 0,
wxWindow *parent = NULL,
int x = wxDefaultCoord, int y = wxDefaultCoord);
#endif

View File

@@ -0,0 +1,643 @@
//
// Copied from wxWidgets 3.0.2 and modified for Audacity
//
/////////////////////////////////////////////////////////////////////////////
// Name: src/gtk/filedlg.cpp
// Purpose: native implementation of wxFileDialog
// Author: Robert Roebling, Zbigniew Zagorski, Mart Raudsepp
// Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski, 2005 Mart Raudsepp
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include <gtk/gtk.h>
#include "../FileDialog.h"
#include "wx/intl.h"
#include "wx/msgdlg.h"
#ifdef __UNIX__
#include <unistd.h> // chdir
#endif
#include <wx/filename.h> // wxFilename
#include <wx/tokenzr.h> // wxStringTokenizer
#include <wx/filefn.h> // ::wxGetCwd
#include <wx/modalhook.h>
#include <wx/sizer.h>
#define wxGTK_CONV(s) (s).utf8_str()
#define wxGTK_CONV_FN(s) (s).fn_str()
// ----------------------------------------------------------------------------
// Convenience class for g_freeing a gchar* on scope exit automatically
// ----------------------------------------------------------------------------
class wxGtkString
{
public:
explicit wxGtkString(gchar *s) : m_str(s) { }
~wxGtkString() { g_free(m_str); }
const gchar *c_str() const { return m_str; }
operator gchar *() const { return m_str; }
private:
gchar *m_str;
wxDECLARE_NO_COPY_CLASS(wxGtkString);
};
//-----------------------------------------------------------------------------
// "clicked" for OK-button
//-----------------------------------------------------------------------------
extern "C" {
static void gtk_filedialog_ok_callback(GtkWidget *widget, FileDialog *dialog)
{
int style = dialog->GetWindowStyle();
wxGtkString filename(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)));
// gtk version numbers must be identical with the one in ctor (that calls set_do_overwrite_confirmation)
#ifndef __WXGTK3__
#if GTK_CHECK_VERSION(2,7,3)
if (gtk_check_version(2, 7, 3) != NULL)
#endif
{
if ((style & wxFD_SAVE) && (style & wxFD_OVERWRITE_PROMPT))
{
if ( g_file_test(filename, G_FILE_TEST_EXISTS) )
{
wxString msg;
msg.Printf(
_("File '%s' already exists, do you really want to overwrite it?"),
wxString::FromUTF8(filename));
wxMessageDialog dlg(dialog, msg, _("Confirm"),
wxYES_NO | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES)
return;
}
}
}
#endif
if (style & wxFD_FILE_MUST_EXIST)
{
if ( !g_file_test(filename, G_FILE_TEST_EXISTS) )
{
wxMessageDialog dlg( dialog, _("Please choose an existing file."),
_("Error"), wxOK| wxICON_ERROR);
dlg.ShowModal();
return;
}
}
// change to the directory where the user went if asked
if (style & wxFD_CHANGE_DIR)
{
// Use chdir to not care about filename encodings
wxGtkString folder(g_path_get_dirname(filename));
chdir(folder);
}
wxCommandEvent event(wxEVT_BUTTON, wxID_OK);
event.SetEventObject(dialog);
dialog->HandleWindowEvent(event);
}
}
//-----------------------------------------------------------------------------
// "clicked" for Cancel-button
//-----------------------------------------------------------------------------
extern "C"
{
static void
gtk_filedialog_cancel_callback(GtkWidget * WXUNUSED(w), FileDialog *dialog)
{
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
event.SetEventObject(dialog);
dialog->HandleWindowEvent(event);
}
static void gtk_filedialog_response_callback(GtkWidget *w,
gint response,
FileDialog *dialog)
{
if (response == GTK_RESPONSE_ACCEPT)
gtk_filedialog_ok_callback(w, dialog);
else // GTK_RESPONSE_CANCEL or GTK_RESPONSE_NONE
gtk_filedialog_cancel_callback(w, dialog);
}
static void gtk_filedialog_selchanged_callback(GtkFileChooser *chooser,
FileDialog *dialog)
{
wxGtkString filename(gtk_file_chooser_get_preview_filename(chooser));
dialog->GTKSelectionChanged(wxString::FromUTF8(filename));
}
static void gtk_filedialog_update_preview_callback(GtkFileChooser *chooser,
gpointer user_data)
{
GtkWidget *preview = GTK_WIDGET(user_data);
wxGtkString filename(gtk_file_chooser_get_preview_filename(chooser));
if ( !filename )
return;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL);
gboolean have_preview = pixbuf != NULL;
gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf);
if ( pixbuf )
g_object_unref (pixbuf);
gtk_file_chooser_set_preview_widget_active(chooser, have_preview);
}
static void gtk_filedialog_folderchanged_callback(GtkFileChooser *chooser,
FileDialog *dialog)
{
dialog->GTKFolderChanged();
}
static void gtk_filedialog_filterchanged_callback(GtkFileChooser *chooser,
GParamSpec *pspec,
FileDialog *dialog)
{
dialog->GTKFilterChanged();
}
static GtkWidget* find_widget(GtkWidget* parent, const gchar* name, int depth)
{
// printf("%*.*c%s\n", depth, depth, ' ', gtk_widget_get_name(parent));
GtkWidget *widget = NULL;
if (g_strcasecmp(gtk_widget_get_name(parent), name) == 0)
{
return parent;
}
if (GTK_IS_BIN(parent))
{
return find_widget(gtk_bin_get_child(GTK_BIN(parent)), name, depth + 1);
}
if (GTK_IS_CONTAINER(parent))
{
GList *list = gtk_container_get_children(GTK_CONTAINER(parent));
for (GList *node = list; node; node = node->next)
{
widget = find_widget(GTK_WIDGET(node->data), name, depth + 1);
if (widget)
{
break;
}
}
g_list_free(list);
}
return widget;
}
} // extern "C"
void FileDialog::AddChildGTK(wxWindowGTK* child)
{
// allow dialog to be resized smaller horizontally
gtk_widget_set_size_request(
child->m_widget, child->GetMinWidth(), child->m_height);
// In GTK 3+, adding our container as the extra widget can cause the
// the filter combo to grow to the same height as our container. This
// makes for a very odd looking filter combo. So, we manually add our
// container below the action bar.
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *actionbar = find_widget(m_widget, "GtkActionBar", 0);
if (actionbar)
{
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add(GTK_CONTAINER(vbox), child->m_widget);
gtk_box_set_child_packing(GTK_BOX(vbox), child->m_widget, TRUE, TRUE, 0, GTK_PACK_START);
gtk_widget_show(vbox);
GtkWidget *abparent = gtk_widget_get_parent(actionbar);
gtk_container_add(GTK_CONTAINER(abparent), vbox);
gtk_box_set_child_packing(GTK_BOX(abparent), vbox, FALSE, FALSE, 0, GTK_PACK_END);
gtk_box_reorder_child(GTK_BOX(abparent), actionbar, -2);
}
#else
gtk_file_chooser_set_extra_widget(
GTK_FILE_CHOOSER(m_widget), child->m_widget);
#endif
}
//-----------------------------------------------------------------------------
// FileDialog
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(FileDialog,FileDialogBase)
BEGIN_EVENT_TABLE(FileDialog,FileDialogBase)
EVT_BUTTON(wxID_OK, FileDialog::OnFakeOk)
EVT_SIZE(FileDialog::OnSize)
END_EVENT_TABLE()
FileDialog::FileDialog(wxWindow *parent, const wxString& message,
const wxString& defaultDir,
const wxString& defaultFileName,
const wxString& wildCard,
long style, const wxPoint& pos,
const wxSize& sz,
const wxString& name)
: FileDialogBase()
{
Create(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name);
}
bool FileDialog::Create(wxWindow *parent, const wxString& message,
const wxString& defaultDir,
const wxString& defaultFileName,
const wxString& wildCard,
long style, const wxPoint& pos,
const wxSize& sz,
const wxString& name)
{
parent = GetParentForModalDialog(parent, style);
if (!FileDialogBase::Create(parent, message, defaultDir, defaultFileName,
wildCard, style, pos, sz, name))
{
return false;
}
if (!PreCreation(parent, pos, wxDefaultSize) ||
!CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style,
wxDefaultValidator, wxT("filedialog")))
{
wxFAIL_MSG( wxT("FileDialog creation failed") );
return false;
}
GtkFileChooserAction gtk_action;
GtkWindow* gtk_parent = NULL;
if (parent)
gtk_parent = GTK_WINDOW( gtk_widget_get_toplevel(parent->m_widget) );
const gchar* ok_btn_stock;
if ( style & wxFD_SAVE )
{
gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
ok_btn_stock = GTK_STOCK_SAVE;
}
else
{
gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
ok_btn_stock = GTK_STOCK_OPEN;
}
m_widget = gtk_file_chooser_dialog_new(
wxGTK_CONV(m_message),
gtk_parent,
gtk_action,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
ok_btn_stock, GTK_RESPONSE_ACCEPT,
NULL);
g_object_ref(m_widget);
GtkFileChooser* file_chooser = GTK_FILE_CHOOSER(m_widget);
m_fc.SetWidget(file_chooser);
gtk_dialog_set_default_response(GTK_DIALOG(m_widget), GTK_RESPONSE_ACCEPT);
if ( style & wxFD_MULTIPLE )
gtk_file_chooser_set_select_multiple(file_chooser, true);
// local-only property could be set to false to allow non-local files to be
// loaded. In that case get/set_uri(s) should be used instead of
// get/set_filename(s) everywhere and the GtkFileChooserDialog should
// probably also be created with a backend, e.g. "gnome-vfs", "default", ...
// (gtk_file_chooser_dialog_new_with_backend). Currently local-only is kept
// as the default - true:
// gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true);
g_signal_connect (m_widget, "response",
G_CALLBACK (gtk_filedialog_response_callback), this);
g_signal_connect (m_widget, "selection-changed",
G_CALLBACK (gtk_filedialog_selchanged_callback), this);
g_signal_connect (m_widget, "current-folder-changed",
G_CALLBACK (gtk_filedialog_folderchanged_callback), this);
g_signal_connect (m_widget, "notify::filter",
G_CALLBACK (gtk_filedialog_filterchanged_callback), this);
// deal with extensions/filters
SetWildcard(wildCard);
wxString defaultFileNameWithExt = defaultFileName;
if ( !wildCard.empty() && !defaultFileName.empty() &&
!wxFileName(defaultFileName).HasExt() )
{
// append the default extension, if any, to the initial file name: GTK
// won't do it for us by default (unlike e.g. MSW)
const wxFileName fnWC(m_fc.GetCurrentWildCard());
if ( fnWC.HasExt() )
{
// Notice that we shouldn't append the extension if it's a wildcard
// because this is not useful: the user would need to change it to use
// some fixed extension anyhow.
const wxString& ext = fnWC.GetExt();
if ( ext.find_first_of("?*") == wxString::npos )
defaultFileNameWithExt << "." << ext;
}
}
// if defaultDir is specified it should contain the directory and
// defaultFileName should contain the default name of the file, however if
// directory is not given, defaultFileName contains both
wxFileName fn;
if ( defaultDir.empty() )
fn.Assign(defaultFileNameWithExt);
else if ( !defaultFileNameWithExt.empty() )
fn.Assign(defaultDir, defaultFileNameWithExt);
else
fn.AssignDir(defaultDir);
// set the initial file name and/or directory
fn.MakeAbsolute(); // GTK+ needs absolute path
const wxString dir = fn.GetPath();
if ( !dir.empty() )
{
gtk_file_chooser_set_current_folder(file_chooser, wxGTK_CONV_FN(dir));
}
const wxString fname = fn.GetFullName();
if ( style & wxFD_SAVE )
{
if ( !fname.empty() )
{
gtk_file_chooser_set_current_name(file_chooser, wxGTK_CONV_FN(fname));
}
#if GTK_CHECK_VERSION(2,7,3)
if ((style & wxFD_OVERWRITE_PROMPT)
#ifndef __WXGTK3__
&& gtk_check_version(2,7,3) == NULL
#endif
)
{
gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, true);
}
#endif
}
else // wxFD_OPEN
{
if ( !fname.empty() )
{
gtk_file_chooser_set_filename(file_chooser,
wxGTK_CONV_FN(fn.GetFullPath()));
}
}
if ( style & wxFD_PREVIEW )
{
GtkWidget *previewImage = gtk_image_new();
gtk_file_chooser_set_preview_widget(file_chooser, previewImage);
g_signal_connect(m_widget, "update-preview",
G_CALLBACK(gtk_filedialog_update_preview_callback),
previewImage);
}
return true;
}
FileDialog::~FileDialog()
{
if (m_extraControl)
{
// get chooser to drop its reference right now, allowing wxWindow dtor
// to verify that ref count drops to zero
gtk_file_chooser_set_extra_widget(
GTK_FILE_CHOOSER(m_widget), NULL);
}
}
void FileDialog::OnFakeOk(wxCommandEvent& WXUNUSED(event))
{
// Update the current directory from here, accessing it later may not work
// due to the strange way GtkFileChooser works.
wxGtkString
str(gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(m_widget)));
m_dir = wxString::FromUTF8(str);
EndDialog(wxID_OK);
}
int FileDialog::ShowModal()
{
WX_HOOK_MODAL_DIALOG();
// Create the root window
wxBoxSizer *verticalSizer = new wxBoxSizer(wxVERTICAL);
wxPanel *root = new wxPanel(this, wxID_ANY);
if (HasUserPaneCreator())
{
wxPanel *userpane = new wxPanel(root, wxID_ANY);
CreateUserPane(userpane);
wxBoxSizer *horizontalSizer = new wxBoxSizer(wxHORIZONTAL);
horizontalSizer->Add(userpane, 1, wxEXPAND, 0);
verticalSizer->Add(horizontalSizer, 1, wxEXPAND|wxALL, 0);
}
root->SetSizer(verticalSizer);
root->Layout();
verticalSizer->SetSizeHints(root);
// Send an initial filter changed event
GTKFilterChanged();
return wxDialog::ShowModal();
}
// Change the currently displayed extension
void FileDialog::SetFileExtension(const wxString& extension)
{
wxString filename;
#if defined(__WXGTK3__)
filename = wxString::FromUTF8(gtk_file_chooser_get_current_name(GTK_FILE_CHOOSER(m_widget)));
#else
GtkWidget *entry = find_widget(m_widget, "GtkFileChooserEntry", 0);
if (entry)
{
filename = wxString::FromUTF8(gtk_entry_get_text(GTK_ENTRY(entry)));
}
#endif
if (filename == wxEmptyString)
{
filename = m_fc.GetFilename();
}
if (filename != wxEmptyString)
{
wxFileName fn(filename);
fn.SetExt(extension);
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), fn.GetFullName().utf8_str());
}
}
void FileDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
int WXUNUSED(width), int WXUNUSED(height),
int WXUNUSED(sizeFlags))
{
}
void FileDialog::OnSize(wxSizeEvent&)
{
// avoid calling DoLayout(), which will set the (wrong) size of
// m_extraControl, its size is managed by GtkFileChooser
}
wxString FileDialog::GetPath() const
{
return m_fc.GetPath();
}
void FileDialog::GetFilenames(wxArrayString& files) const
{
m_fc.GetFilenames( files );
}
void FileDialog::GetPaths(wxArrayString& paths) const
{
m_fc.GetPaths( paths );
}
void FileDialog::SetMessage(const wxString& message)
{
m_message = message;
SetTitle(message);
}
void FileDialog::SetPath(const wxString& path)
{
FileDialogBase::SetPath(path);
// Don't do anything if no path is specified, in particular don't set the
// path to m_dir below as this would result in opening the dialog in the
// parent directory of this one instead of m_dir itself.
if ( path.empty() )
return;
// we need an absolute path for GTK native chooser so ensure that we have
// it: use the initial directory if it was set or just CWD otherwise (this
// is the default behaviour if m_dir is empty)
wxFileName fn(path);
fn.MakeAbsolute(m_dir);
m_fc.SetPath(fn.GetFullPath());
}
void FileDialog::SetDirectory(const wxString& dir)
{
FileDialogBase::SetDirectory(dir);
m_fc.SetDirectory(dir);
}
void FileDialog::SetFilename(const wxString& name)
{
FileDialogBase::SetFilename(name);
if (HasFdFlag(wxFD_SAVE))
{
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxGTK_CONV(name));
}
else
{
wxString path( GetDirectory() );
if (path.empty())
{
// SetPath() fires an assert if fed other than filepaths
return;
}
SetPath(wxFileName(path, name).GetFullPath());
}
}
wxString FileDialog::GetFilename() const
{
wxString currentFilename( m_fc.GetFilename() );
if (currentFilename.empty())
{
// m_fc.GetFilename() will return empty until the dialog has been shown
// in which case use any previously provided value
currentFilename = m_fileName;
}
return currentFilename;
}
void FileDialog::SetWildcard(const wxString& wildCard)
{
FileDialogBase::SetWildcard(wildCard);
m_fc.SetWildcard( GetWildcard() );
}
void FileDialog::SetFilterIndex(int filterIndex)
{
m_fc.SetFilterIndex( filterIndex );
}
int FileDialog::GetFilterIndex() const
{
return m_fc.GetFilterIndex();
}
void FileDialog::GTKSelectionChanged(const wxString& filename)
{
m_currentlySelectedFilename = filename;
wxFileCtrlEvent event(wxEVT_FILECTRL_SELECTIONCHANGED, this, GetId());
wxArrayString filenames;
GetFilenames(filenames);
event.SetDirectory(GetDirectory());
event.SetFiles(filenames);
GetEventHandler()->ProcessEvent(event);
}
void FileDialog::GTKFolderChanged()
{
wxFileCtrlEvent event(wxEVT_FILECTRL_FOLDERCHANGED, this, GetId());
event.SetDirectory(GetDirectory());
GetEventHandler()->ProcessEvent(event);
}
void FileDialog::GTKFilterChanged()
{
wxFileCtrlEvent event(wxEVT_FILECTRL_FILTERCHANGED, this, GetId());
event.SetFilterIndex(GetFilterIndex());
GetEventHandler()->ProcessEvent(event);
}

View File

@@ -0,0 +1,91 @@
//
// Copied from wxWidgets 3.0.2 and modified for Audacity
//
/////////////////////////////////////////////////////////////////////////////
// Name: wx/gtk/filedlg.h
// Purpose:
// Author: Robert Roebling
// Copyright: (c) 1998 Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _GTK_FILEDIALOGPRIVATE_H_
#define _GTK_FILEDIALOGPRIVATE_H_
#include <wx/gtk/filectrl.h> // for wxGtkFileChooser
#include <wx/panel.h>
//-------------------------------------------------------------------------
// FileDialog
//-------------------------------------------------------------------------
class WXDLLIMPEXP_CORE FileDialog: public FileDialogBase
{
public:
FileDialog() { }
FileDialog(wxWindow *parent,
const wxString& message = wxFileSelectorPromptStr,
const wxString& defaultDir = wxEmptyString,
const wxString& defaultFile = wxEmptyString,
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
const wxString& name = wxFileDialogNameStr);
bool Create(wxWindow *parent,
const wxString& message = wxFileSelectorPromptStr,
const wxString& defaultDir = wxEmptyString,
const wxString& defaultFile = wxEmptyString,
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
const wxString& name = wxFileDialogNameStr);
virtual ~FileDialog();
virtual wxString GetPath() const;
virtual void GetPaths(wxArrayString& paths) const;
virtual wxString GetFilename() const;
virtual void GetFilenames(wxArrayString& files) const;
virtual int GetFilterIndex() const;
virtual void SetMessage(const wxString& message);
virtual void SetPath(const wxString& path);
virtual void SetDirectory(const wxString& dir);
virtual void SetFilename(const wxString& name);
virtual void SetWildcard(const wxString& wildCard);
virtual void SetFilterIndex(int filterIndex);
virtual int ShowModal();
virtual bool SupportsExtraControl() const { return true; }
virtual void SetFileExtension(const wxString& extension);
// Implementation only.
void GTKSelectionChanged(const wxString& filename);
void GTKFolderChanged();
void GTKFilterChanged();
protected:
// override this from wxTLW since the native
// form doesn't have any m_wxwindow
virtual void DoSetSize(int x, int y,
int width, int height,
int sizeFlags = wxSIZE_AUTO);
private:
void OnFakeOk( wxCommandEvent &event );
void OnSize(wxSizeEvent&);
virtual void AddChildGTK(wxWindowGTK* child);
wxGtkFileChooser m_fc;
DECLARE_DYNAMIC_CLASS(FileDialog)
DECLARE_EVENT_TABLE()
};
#endif

View File

@@ -0,0 +1,107 @@
//
// Copied from wx 3.0.2 and modified to support additional features
//
/////////////////////////////////////////////////////////////////////////////
// Name: wx/osx/filedlg.h
// Purpose: wxFileDialog class
// Author: Stefan Csomor
// Modified by: Leland Lucius
// Created: 1998-01-01
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _MAC_FILEDIALOG_H_
#define _MAC_FILEDIALOG_H_
#include "../FileDialog.h"
class wxChoice;
//-------------------------------------------------------------------------
// wxFileDialog
//-------------------------------------------------------------------------
class WXDLLIMPEXP_CORE FileDialog: public FileDialogBase
{
DECLARE_DYNAMIC_CLASS(FileDialog)
protected:
wxArrayString m_fileNames;
wxArrayString m_paths;
public:
FileDialog();
FileDialog(wxWindow *parent,
const wxString& message = wxFileSelectorPromptStr,
const wxString& defaultDir = wxEmptyString,
const wxString& defaultFile = wxEmptyString,
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
const wxString& name = wxFileDialogNameStr);
void Create(wxWindow *parent,
const wxString& message = wxFileSelectorPromptStr,
const wxString& defaultDir = wxEmptyString,
const wxString& defaultFile = wxEmptyString,
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
const wxString& name = wxFileDialogNameStr);
#if wxOSX_USE_COCOA
~FileDialog();
#endif
virtual void GetPaths(wxArrayString& paths) const { paths = m_paths; }
virtual void GetFilenames(wxArrayString& files) const { files = m_fileNames ; }
virtual int ShowModal();
#if wxOSX_USE_COCOA
virtual void ModalFinishedCallback(void* panel, int resultCode);
#endif
virtual bool SupportsExtraControl() const;
virtual void SetFileExtension(const wxString& extension);
// implementation only
#if wxOSX_USE_COCOA
void DoViewResized(void* object);
void DoSendFolderChangedEvent(void* panel, const wxString& path);
void DoSendSelectionChangedEvent(void* panel);
#endif
protected:
// not supported for file dialog, RR
virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
int WXUNUSED(width), int WXUNUSED(height),
int WXUNUSED(sizeFlags) = wxSIZE_AUTO) {}
void SetupExtraControls(WXWindow nativeWindow);
#if wxOSX_USE_COCOA
void DoOnFilterSelected(int index);
virtual void OnFilterSelected(wxCommandEvent &event);
wxArrayString m_filterExtensions;
wxArrayString m_filterNames;
wxChoice* m_filterChoice;
wxWindow* m_filterPanel;
bool m_useFileTypeFilter;
int m_firstFileTypeFilter;
wxArrayString m_currentExtensions;
WX_NSObject m_delegate;
WX_NSObject m_sheetDelegate;
#endif
private:
// Common part of all ctors.
void Init();
};
#endif

View File

@@ -0,0 +1,721 @@
///
// Copied from wxWidgets 3.0.2 and modified to support additional features
//
/////////////////////////////////////////////////////////////////////////////
// Name: src/cocoa/filedlg.mm
// Purpose: wxFileDialog for wxCocoa
// Author: Ryan Norton
// Modified by: Leland Lucius
// Created: 2004-10-02
// Copyright: (c) Ryan Norton
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#undef WXINTL_NO_GETTEXT_MACRO
// For compilers that support precompilation, includes "wx.h".
#include <wx/wxprec.h>
#include "../FileDialog.h"
#ifndef WX_PRECOMP
#include <wx/msgdlg.h>
#include <wx/app.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/choice.h>
#endif
#include <wx/clipbrd.h>
#include <wx/filectrl.h>
#include <wx/filename.h>
#include <wx/tokenzr.h>
#include <wx/evtloop.h>
#include <wx/osx/core/private.h>
#include <wx/sysopt.h>
#include <wx/modalhook.h>
#include <AppKit/AppKit.h>
// ============================================================================
// implementation
// ============================================================================
@interface OSPanelDelegate : NSObject <NSOpenSavePanelDelegate>
{
FileDialog* _dialog;
}
- (FileDialog*) fileDialog;
- (void) setFileDialog:(FileDialog*) dialog;
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url;
- (void)panelSelectionDidChange:(id)sender;
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError * _Nullable *)outError;
- (void)viewResized:(NSNotification *)notification;
@end
@implementation OSPanelDelegate
- (void)viewResized:(NSNotification *)notification
{
_dialog->DoViewResized([notification object]);
}
- (id) init
{
if ( self = [super init] )
{
_dialog = NULL;
}
return self;
}
- (FileDialog*) fileDialog
{
return _dialog;
}
- (void) setFileDialog:(FileDialog*) dialog
{
_dialog = dialog;
}
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
{
wxString path = wxCFStringRef::AsStringWithNormalizationFormC( [url path] );
_dialog->DoSendFolderChangedEvent(sender, path);
}
- (void)panelSelectionDidChange:(id)sender AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
{
_dialog->DoSendSelectionChangedEvent(sender);
}
// Do NOT remove this method. For an explanation, refer to:
//
// http://bugzilla.audacityteam.org/show_bug.cgi?id=2371
//
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError * _Nullable *)outError;
{
// We handle filename validation after the panel closes
return YES;
}
@end
wxIMPLEMENT_CLASS(FileDialog, FileDialogBase)
FileDialog::FileDialog()
: FileDialogBase()
{
Init();
}
FileDialog::FileDialog(wxWindow *parent,
const wxString& message,
const wxString& defaultDir,
const wxString& defaultFile,
const wxString& wildCard,
long style,
const wxPoint& pos,
const wxSize& sz,
const wxString& name)
: FileDialogBase()
{
Init();
Create(parent,message,defaultDir,defaultFile,wildCard,style,pos,sz,name);
}
void FileDialog::Init()
{
m_filterIndex = -1;
m_delegate = nil;
m_filterPanel = NULL;
m_filterChoice = NULL;
}
void FileDialog::Create(
wxWindow *parent, const wxString& message,
const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard,
long style, const wxPoint& pos, const wxSize& sz, const wxString& name)
{
FileDialogBase::Create(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name);
}
FileDialog::~FileDialog()
{
}
bool FileDialog::SupportsExtraControl() const
{
return true;
}
NSArray* GetTypesFromExtension( const wxString extensiongroup, wxArrayString& extensions )
{
NSMutableArray* types = nil;
extensions.Clear();
wxStringTokenizer tokenizer( extensiongroup, wxT(";") ) ;
while ( tokenizer.HasMoreTokens() )
{
wxString extension = tokenizer.GetNextToken() ;
// Remove leading '*'
if ( extension.length() && (extension.GetChar(0) == '*') )
extension = extension.Mid( 1 );
// Remove leading '.'
if ( extension.length() && (extension.GetChar(0) == '.') )
extension = extension.Mid( 1 );
// Remove leading '*', this is for handling *.*
if ( extension.length() && (extension.GetChar(0) == '*') )
extension = extension.Mid( 1 );
if ( extension.IsEmpty() )
{
extensions.Clear();
[types release];
types = nil;
return nil;
}
if ( types == nil )
types = [[NSMutableArray alloc] init];
extensions.Add(extension.Lower());
wxCFStringRef cfext(extension);
[types addObject: (NSString*)cfext.AsNSString() ];
}
[types autorelease];
return types;
}
NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArrayString& extensiongroups )
{
NSMutableArray* types = nil;
bool allowAll = false;
names.Clear();
extensiongroups.Clear();
if ( !filter.empty() )
{
wxStringTokenizer tokenizer( filter, wxT("|") );
int numtokens = (int)tokenizer.CountTokens();
if(numtokens == 1)
{
// we allow for compatibility reason to have a single filter expression (like *.*) without
// an explanatory text, in that case the first part is name and extension at the same time
wxString extension = tokenizer.GetNextToken();
names.Add( extension );
extensiongroups.Add( extension );
}
else
{
int numextensions = numtokens / 2;
for(int i = 0; i < numextensions; i++)
{
wxString name = tokenizer.GetNextToken();
wxString extension = tokenizer.GetNextToken();
names.Add( name );
extensiongroups.Add( extension );
}
}
const size_t extCount = extensiongroups.GetCount();
wxArrayString extensions;
for ( size_t i = 0 ; i < extCount; i++ )
{
NSArray* exttypes = GetTypesFromExtension(extensiongroups[i], extensions);
if ( exttypes != nil )
{
if ( allowAll == false )
{
if ( types == nil )
types = [[NSMutableArray alloc] init];
[types addObjectsFromArray:exttypes];
}
}
else
{
allowAll = true;
[types release];
types = nil;
}
}
}
[types autorelease];
return types;
}
void FileDialog::DoOnFilterSelected(int index)
{
if (index == wxNOT_FOUND)
{
return;
}
NSArray* types = GetTypesFromExtension(m_filterExtensions[index],m_currentExtensions);
NSSavePanel* panel = (NSSavePanel*) GetWXWindow();
[panel setAllowedFileTypes:types];
m_filterIndex = index;
wxFileCtrlEvent event( wxEVT_FILECTRL_FILTERCHANGED, this, GetId() );
event.SetFilterIndex( m_filterIndex );
GetEventHandler()->ProcessEvent( event );
}
// An item has been selected in the file filter wxChoice:
void FileDialog::OnFilterSelected( wxCommandEvent &WXUNUSED(event) )
{
DoOnFilterSelected( m_filterChoice->GetSelection() );
}
void FileDialog::DoViewResized(void* object)
{
m_filterPanel->Layout();
}
void FileDialog::DoSendFolderChangedEvent(void* panel, const wxString & path)
{
m_dir = path;
wxFileCtrlEvent event( wxEVT_FILECTRL_FOLDERCHANGED, this, GetId() );
event.SetDirectory( m_dir );
GetEventHandler()->ProcessEvent( event );
}
void FileDialog::DoSendSelectionChangedEvent(void* panel)
{
if ( HasFlag( wxFD_SAVE ) )
{
NSSavePanel* sPanel = (NSSavePanel*) panel;
NSString* path = [[sPanel URL] path];
wxFileName fn(wxCFStringRef::AsStringWithNormalizationFormC( path ));
if (!fn.GetFullPath().empty())
{
m_path = fn.GetFullPath();
m_dir = fn.GetPath();
m_fileName = fn.GetFullName();
m_fileNames.Clear();
m_fileNames.Add( m_fileName );
}
}
else
{
NSOpenPanel* oPanel = (NSOpenPanel*) panel;
m_paths.Clear();
m_fileNames.Clear();
NSArray* urls = [oPanel URLs];
for ( size_t i = 0 ; i < [urls count] ; ++ i )
{
NSString *path = [[urls objectAtIndex:i] path];
wxString fnstr = wxCFStringRef::AsStringWithNormalizationFormC( path );
m_paths.Add( fnstr );
m_fileNames.Add( wxFileNameFromPath( fnstr ) );
if ( i == 0 )
{
m_path = fnstr;
m_fileName = wxFileNameFromPath( fnstr );
m_dir = wxPathOnly( fnstr );
}
}
}
wxFileCtrlEvent event( wxEVT_FILECTRL_SELECTIONCHANGED, this, GetId() );
event.SetDirectory( m_dir );
event.SetFiles( m_fileNames );
GetEventHandler()->ProcessEvent( event );
}
void FileDialog::SetupExtraControls(WXWindow nativeWindow)
{
NSSavePanel* panel = (NSSavePanel*) nativeWindow;
// for sandboxed app we cannot access the outer structures
// this leads to problems with extra controls, so as a temporary
// workaround for crashes we don't support those yet
if ( [panel contentView] == nil || getenv("APP_SANDBOX_CONTAINER_ID") != NULL )
return;
OSPanelDelegate* del = [[OSPanelDelegate alloc]init];
[del setFileDialog:this];
[panel setDelegate:del];
m_delegate = del;
wxNonOwnedWindow::Create( GetParent(), nativeWindow );
m_filterPanel = NULL;
m_filterChoice = NULL;
NSView* accView = nil;
if ( m_useFileTypeFilter || HasUserPaneCreator() )
{
wxBoxSizer *verticalSizer = new wxBoxSizer( wxVERTICAL );
m_filterPanel = new wxPanel( this, wxID_ANY );
accView = m_filterPanel->GetHandle();
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:del
selector:@selector(viewResized:)
name:NSViewFrameDidChangeNotification
object:accView];
if ( m_useFileTypeFilter )
{
wxBoxSizer *horizontalSizer = new wxBoxSizer( wxHORIZONTAL );
wxStaticText *stattext = new wxStaticText( m_filterPanel, wxID_ANY, _("File type:") );
horizontalSizer->Add( stattext, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_filterChoice = new wxChoice( m_filterPanel, wxID_ANY );
m_filterChoice->Append( m_filterNames );
if ( m_filterNames.GetCount() > 0 )
{
if ( m_firstFileTypeFilter >= 0 )
m_filterChoice->SetSelection( m_firstFileTypeFilter );
}
m_filterChoice->Bind(wxEVT_CHOICE, &FileDialog::OnFilterSelected, this);
horizontalSizer->Add( m_filterChoice, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
verticalSizer->Add( horizontalSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
}
if ( HasUserPaneCreator() )
{
wxPanel *userpane = new wxPanel( m_filterPanel, wxID_ANY );
CreateUserPane( userpane );
wxBoxSizer *horizontalSizer = new wxBoxSizer( wxHORIZONTAL );
horizontalSizer->Add( userpane, 1, wxEXPAND, 0 );
verticalSizer->Add( horizontalSizer, 1, wxEXPAND, 0 );
}
m_filterPanel->SetSizer( verticalSizer );
m_filterPanel->Layout();
wxSize ws = m_filterPanel->GetBestSize();
m_filterPanel->SetSize(ws);
m_filterPanel->SetMinSize(ws);
}
if ( accView != nil )
{
[accView removeFromSuperview];
[accView setAutoresizingMask:NSViewWidthSizable];
[panel setAccessoryView:accView];
}
}
int FileDialog::ShowModal()
{
WX_HOOK_MODAL_DIALOG();
wxCFEventLoopPauseIdleEvents pause;
wxMacAutoreleasePool autoreleasepool;
wxCFStringRef cf( m_message );
wxCFStringRef dir( m_dir );
wxCFStringRef file( m_fileName );
m_path.clear();
m_fileNames.Clear();
m_paths.Clear();
wxNonOwnedWindow* parentWindow = NULL;
int returnCode = -1;
if (GetParent())
{
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
}
NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions ) ;
m_useFileTypeFilter = m_filterExtensions.GetCount() > 0;
#if defined(we_always_want_the_types)
if( HasFlag(wxFD_OPEN) )
{
if ( !(wxSystemOptions::HasOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES ) && (wxSystemOptions::GetOptionInt( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES ) == 1)) )
m_useFileTypeFilter = false;
}
#endif
m_firstFileTypeFilter = wxNOT_FOUND;
if ( m_useFileTypeFilter
&& m_filterIndex >= 0 && m_filterIndex < m_filterExtensions.GetCount() )
{
m_firstFileTypeFilter = m_filterIndex;
}
else if ( m_useFileTypeFilter )
{
types = nil;
bool useDefault = true;
for ( size_t i = 0; i < m_filterExtensions.GetCount(); ++i )
{
types = GetTypesFromExtension(m_filterExtensions[i], m_currentExtensions);
if ( m_currentExtensions.GetCount() == 0 )
{
useDefault = false;
m_firstFileTypeFilter = i;
break;
}
for ( size_t j = 0; j < m_currentExtensions.GetCount(); ++j )
{
if ( m_fileName.EndsWith(m_currentExtensions[j]) )
{
m_firstFileTypeFilter = i;
useDefault = false;
break;
}
}
if ( !useDefault )
break;
}
if ( useDefault )
{
types = GetTypesFromExtension(m_filterExtensions[0], m_currentExtensions);
m_firstFileTypeFilter = 0;
}
}
OSXBeginModalDialog();
if ( HasFlag(wxFD_SAVE) )
{
NSSavePanel* sPanel = [NSSavePanel savePanel];
SetupExtraControls(sPanel);
// PRL:
// Hack for bug 1300: intercept key down events, implement a
// Command+V handler, but it's a bit crude. It always pastes
// the entire text field, ignoring the insertion cursor, and ignoring
// which control really has the focus.
id handler;
if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
handler = [
NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^NSEvent *(NSEvent *event)
{
if ([event modifierFlags] & NSCommandKeyMask)
{
auto chars = [event charactersIgnoringModifiers];
auto character = [chars characterAtIndex:0];
if (character == 'v')
{
if (wxTheClipboard->Open()) {
wxTextDataObject data;
wxTheClipboard->GetData(data);
wxTheClipboard->Close();
wxString text = data.GetText();
auto rawText = text.utf8_str();
auto length = text.Length();
NSString *myString = [[NSString alloc]
initWithBytes:rawText.data()
length: rawText.length()
encoding: NSUTF8StringEncoding
];
[sPanel setNameFieldStringValue:myString];
[myString release];
return nil;
}
}
}
return event;
}
];
}
// makes things more convenient:
[sPanel setCanCreateDirectories:YES];
[sPanel setMessage:cf.AsNSString()];
// if we should be able to descend into pacakges we must somehow
// be able to pass this in
[sPanel setTreatsFilePackagesAsDirectories:NO];
[sPanel setCanSelectHiddenExtension:YES];
[sPanel setExtensionHidden:NO];
[sPanel setAllowedFileTypes:types];
[sPanel setAllowsOtherFileTypes:YES];
if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
{
}
/*
Let the file dialog know what file type should be used initially.
If this is not done then when setting the filter index
programmatically to 1 the file will still have the extension
of the first file type instead of the second one. E.g. when file
types are foo and bar, a filename "myletter" with SetDialogIndex(1)
would result in saving as myletter.foo, while we want myletter.bar.
*/
// if(m_firstFileTypeFilter > 0)
{
DoOnFilterSelected(m_firstFileTypeFilter);
}
[sPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString()]];
[sPanel setNameFieldStringValue:file.AsNSString()];
returnCode = [sPanel runModal];
ModalFinishedCallback(sPanel, returnCode);
if (wxTheClipboard->IsSupported(wxDF_TEXT))
[NSEvent removeMonitor:handler];
}
else
{
NSOpenPanel* oPanel = [NSOpenPanel openPanel];
SetupExtraControls(oPanel);
[oPanel setTreatsFilePackagesAsDirectories:NO];
[oPanel setCanChooseDirectories:NO];
[oPanel setResolvesAliases:YES];
[oPanel setCanChooseFiles:YES];
[oPanel setMessage:cf.AsNSString()];
[oPanel setAllowsMultipleSelection: (HasFlag(wxFD_MULTIPLE) ? YES : NO )];
// Note that the test here is intentionally different from the one
// above, in the wxFD_SAVE case: we need to call DoOnFilterSelected()
// even for m_firstFileTypeFilter == 0, i.e. when using the default
// filter.
if ( m_firstFileTypeFilter >= 0 )
{
DoOnFilterSelected(m_firstFileTypeFilter);
}
else
{
[oPanel setAllowedFileTypes: (m_delegate == nil ? types : nil)];
}
if ( !m_dir.IsEmpty() )
[oPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString()
isDirectory:YES]];
{
DoOnFilterSelected(m_firstFileTypeFilter);
}
returnCode = [oPanel runModal];
ModalFinishedCallback(oPanel, returnCode);
}
OSXEndModalDialog();
return GetReturnCode();
}
void FileDialog::ModalFinishedCallback(void* panel, int returnCode)
{
m_paths.Clear();
m_fileNames.Clear();
int result = wxID_CANCEL;
if (HasFlag(wxFD_SAVE))
{
NSSavePanel* sPanel = (NSSavePanel*)panel;
if (returnCode == NSOKButton )
{
result = wxID_OK;
NSString* path = [[sPanel URL] path];
wxFileName fn(wxCFStringRef::AsStringWithNormalizationFormC( path ));
m_dir = fn.GetPath();
m_fileName = fn.GetFullName();
m_path = fn.GetFullPath();
if (m_filterChoice)
{
m_filterIndex = m_filterChoice->GetSelection();
}
}
[sPanel setDelegate:nil];
}
else
{
NSOpenPanel* oPanel = (NSOpenPanel*)panel;
if (returnCode == NSOKButton )
{
panel = oPanel;
result = wxID_OK;
if (m_filterChoice)
{
m_filterIndex = m_filterChoice->GetSelection();
}
NSArray* filenames = [oPanel URLs];
for ( size_t i = 0 ; i < [filenames count] ; ++ i )
{
wxString fnstr = wxCFStringRef::AsStringWithNormalizationFormC([[filenames objectAtIndex:i] path]);
m_paths.Add( fnstr );
m_fileNames.Add( wxFileNameFromPath(fnstr) );
if ( i == 0 )
{
m_path = fnstr;
m_fileName = wxFileNameFromPath(fnstr);
m_dir = wxPathOnly( fnstr );
}
}
}
[oPanel setDelegate:nil];
}
if ( m_delegate )
{
[[NSNotificationCenter defaultCenter] removeObserver:m_delegate];
[m_delegate release];
m_delegate = nil;
}
SetReturnCode(result);
if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED );
// workaround for sandboxed app, see above
if ( m_isNativeWindowWrapper )
UnsubclassWin();
[(NSSavePanel*) panel setAccessoryView:nil];
}
// Change the currently displayed extension
void FileDialog::SetFileExtension(const wxString& extension)
{
NSSavePanel* sPanel = (NSSavePanel*) GetWXWindow();
m_filterExtensions[m_filterIndex] = extension;
NSArray* types = GetTypesFromExtension(m_filterExtensions[m_filterIndex],m_currentExtensions);
[sPanel setAllowedFileTypes:types];
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,124 @@
//
// Copied from wxWidgets 3.0.2 and modified for Audacity
//
/////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/filedlg.h
// Purpose: wxFileDialog class
// Author: Julian Smart
// Modified by: Leland Lucius
// Created: 01/02/97
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WIN_FILEDIALOGPRIVATE_H_
#define _WIN_FILEDIALOGPRIVATE_H_
#include <windows.h>
#include <wx/modalhook.h>
//-------------------------------------------------------------------------
// FileDialog
//-------------------------------------------------------------------------
class AUDACITY_DLL_API FileDialog : public FileDialogBase
{
public:
FileDialog();
FileDialog(wxWindow *parent,
const wxString& message = wxFileSelectorPromptStr,
const wxString& defaultDir = wxEmptyString,
const wxString& defaultFile = wxEmptyString,
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
const wxString& name = wxFileDialogNameStr);
virtual void GetPaths(wxArrayString& paths) const;
virtual void GetFilenames(wxArrayString& files) const;
virtual int ShowModal();
virtual void SetFileExtension(const wxString& extension);
protected:
// -----------------------------------------
// wxMSW-specific implementation from now on
// -----------------------------------------
#if !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
virtual void DoMoveWindow(int x, int y, int width, int height);
virtual void DoCentre(int dir);
virtual void DoGetSize(int *width, int *height) const;
virtual void DoGetPosition(int *x, int *y) const;
#endif // !(__SMARTPHONE__ && __WXWINCE__)
private:
void Init();
wxString GetFullPath(HWND hwnd, int itm);
void FilterFiles(HWND hwnd, bool refresh);
void ParseFilter(int index);
// Parent dialog hook
static UINT_PTR APIENTRY ParentHook(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
virtual UINT_PTR MSWParentHook(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam, OPENFILENAME *pOfn);
// Message handlers for the parent dialog
virtual void MSWOnSize(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnGetMinMaxInfo(HWND hwnd, LPOPENFILENAME pOfn, LPMINMAXINFO pMmi);
// Child dialog hook
static UINT_PTR APIENTRY DialogHook(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
virtual UINT_PTR MSWDialogHook(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam, OPENFILENAME *pOfn);
// Message handlers for the child dialog
virtual void MSWOnInitDialog(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnDestroy(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnInitDone(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnFolderChange(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnSelChange(HWND hwnd, LPOPENFILENAME pOfn);
virtual void MSWOnTypeChange(HWND hwnd, LPOPENFILENAME pOfn);
private:
wxArrayString m_fileNames;
// remember if our SetPosition() or Centre() (which requires special
// treatment) was called
bool m_bMovedWindow;
int m_centreDir; // nothing to do if 0
wxArrayString m_FilterGroups;
wxArrayString m_Filters;
HWND mParentDlg;
HWND mChildDlg;
WNDPROC mParentProc;
POINT mMinSize;
wxPanel *mRoot;
class Disabler : public wxModalDialogHook
{
public:
Disabler();
void Init(wxWindow *root, HWND hwnd);
protected:
int Enter(wxDialog *dialog);
void Exit(wxDialog *dialog);
bool IsChild(const wxDialog *dialog) const;
private:
wxWindow *mRoot;
HWND mHwnd;
int mModalCount;
} mDisabler;
DECLARE_DYNAMIC_CLASS(FileDialog)
DECLARE_NO_COPY_CLASS(FileDialog)
};
#endif