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:
154
src/widgets/FileDialog/FileDialog.cpp
Normal file
154
src/widgets/FileDialog/FileDialog.cpp
Normal 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;
|
||||
}
|
||||
|
||||
96
src/widgets/FileDialog/FileDialog.h
Normal file
96
src/widgets/FileDialog/FileDialog.h
Normal 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
|
||||
643
src/widgets/FileDialog/gtk/FileDialogPrivate.cpp
Normal file
643
src/widgets/FileDialog/gtk/FileDialogPrivate.cpp
Normal 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);
|
||||
}
|
||||
|
||||
91
src/widgets/FileDialog/gtk/FileDialogPrivate.h
Normal file
91
src/widgets/FileDialog/gtk/FileDialogPrivate.h
Normal 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
|
||||
107
src/widgets/FileDialog/mac/FileDialogPrivate.h
Normal file
107
src/widgets/FileDialog/mac/FileDialogPrivate.h
Normal 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
|
||||
721
src/widgets/FileDialog/mac/FileDialogPrivate.mm
Normal file
721
src/widgets/FileDialog/mac/FileDialogPrivate.mm
Normal 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];
|
||||
}
|
||||
|
||||
1224
src/widgets/FileDialog/win/FileDialogPrivate.cpp
Normal file
1224
src/widgets/FileDialog/win/FileDialogPrivate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
src/widgets/FileDialog/win/FileDialogPrivate.h
Normal file
124
src/widgets/FileDialog/win/FileDialogPrivate.h
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user