[Gtkradiant] r4795 - in GtkRadiant/trunk: docs/developer include
radiant
svn-noreply at zerowing.idsoftware.com
svn-noreply at zerowing.idsoftware.com
Wed Sep 22 05:28:14 CDT 2004
Author: spog
Date: 2004-09-21 18:00:19 -0500 (Tue, 21 Sep 2004)
New Revision: 4795
Modified:
GtkRadiant/trunk/docs/developer/CHANGES
GtkRadiant/trunk/docs/developer/TODO
GtkRadiant/trunk/include/ifiletypes.h
GtkRadiant/trunk/radiant/gtkmisc.cpp
Log:
file-choosers changed to use GtkFileChooser
Modified: GtkRadiant/trunk/docs/developer/CHANGES
===================================================================
--- GtkRadiant/trunk/docs/developer/CHANGES 2004-09-21 20:49:06 UTC (rev 4794)
+++ GtkRadiant/trunk/docs/developer/CHANGES 2004-09-21 23:00:19 UTC (rev 4795)
@@ -2,6 +2,10 @@
that we distribute with the binaries. (see changelog)
20/09/2004
+Michael Schlueter
+- Changed file-chooser dialogs to use GtkFileChooser.
+
+20/09/2004
SPoG
- Added basic rendering for 'curve_CatmullRomSpline' on doom3 entities.
Modified: GtkRadiant/trunk/docs/developer/TODO
===================================================================
--- GtkRadiant/trunk/docs/developer/TODO 2004-09-21 20:49:06 UTC (rev 4794)
+++ GtkRadiant/trunk/docs/developer/TODO 2004-09-21 23:00:19 UTC (rev 4795)
@@ -18,7 +18,6 @@
HIGH priority features
Brush: make edge/vertex/face dragging with QE tool select equal points
-UI: change file-choosers to use GtkFileChooser on linux
Model: add support for doom3 md5anim format
Model: support doom3 .skin files
VFS: add ability to browse VFS from file-open dialogs.
Modified: GtkRadiant/trunk/include/ifiletypes.h
===================================================================
--- GtkRadiant/trunk/include/ifiletypes.h 2004-09-21 20:49:06 UTC (rev 4794)
+++ GtkRadiant/trunk/include/ifiletypes.h 2004-09-21 23:00:19 UTC (rev 4795)
@@ -7,10 +7,12 @@
public:
filetype_t()
: name(""), pattern("")
- {}
+ {
+ }
filetype_t(const char* _name, const char* _pattern)
: name(_name), pattern(_pattern)
- {}
+ {
+ }
const char* name;
const char* pattern;
};
Modified: GtkRadiant/trunk/radiant/gtkmisc.cpp
===================================================================
--- GtkRadiant/trunk/radiant/gtkmisc.cpp 2004-09-21 20:49:06 UTC (rev 4794)
+++ GtkRadiant/trunk/radiant/gtkmisc.cpp 2004-09-21 23:00:19 UTC (rev 4795)
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <set>
+#include <vector>
#include <gtk/gtkframe.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkhbox.h>
@@ -66,6 +67,8 @@
#include "math/vector.h"
#include "pathlib.h"
#include "str.h"
+#include "auto_array.h"
+#include "stringstream.h"
#include "error.h"
#include "filetypes.h"
@@ -1502,40 +1505,8 @@
// =============================================================================
// File dialog
-// fenris #3078 WHENHELLISFROZENOVER
-
-//#define FILEDLG_DBG
-
-static void file_sel_callback (GtkWidget *widget, gpointer data)
-{
- GtkWidget *parent;
- int *loop;
- bool *success;
-
- parent = gtk_widget_get_toplevel (widget);
- loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");
- success = (bool*)g_object_get_data (G_OBJECT (parent), "success");
-
- if ((EMessageBoxReturn)gpointer_to_int(data) == eIDOK)
- *success = true;
-
- *loop = 0;
-}
-
-gint file_sel_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- int *loop;
-
- gtk_widget_hide (widget);
- loop = (int*)g_object_get_data (G_OBJECT (widget), "loop");
- *loop = 0;
-
- return TRUE;
-}
-
char* dir_dialog(GtkWidget* parent, const char* title, const char* path)
{
-#if 0
GtkWidget* dialog = gtk_file_chooser_dialog_new(title,
GTK_WINDOW(parent),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
@@ -1557,47 +1528,6 @@
gtk_widget_destroy(dialog);
return filename;
-#else
-
- GtkWidget* file_sel;
- char* filename = 0;
- int loop = 1;
- bool success = false;
-
- file_sel = gtk_file_selection_new (title);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
- GTK_SIGNAL_FUNC (file_sel_callback), gint_to_pointer (eIDOK));
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
- GTK_SIGNAL_FUNC (file_sel_callback), gint_to_pointer (eIDCANCEL));
- gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
- GTK_SIGNAL_FUNC (file_sel_delete_callback), 0);
- gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
-
- if (parent != 0)
- gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
-
- gtk_widget_hide (GTK_FILE_SELECTION (file_sel)->file_list->parent);
-
- g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
- g_object_set_data (G_OBJECT (file_sel), "filename", &filename);
- g_object_set_data (G_OBJECT (file_sel), "success", &success);
-
- if (path != 0)
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), path);
-
- gtk_grab_add (file_sel);
- gtk_widget_show (file_sel);
-
- while (loop)
- gtk_main_iteration ();
-
- filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
-
- gtk_grab_remove (file_sel);
- gtk_widget_destroy (file_sel);
-
- return filename;
-#endif
}
bool color_dialog (GtkWidget *parent, Vector3& color, const char* title)
@@ -1838,178 +1768,133 @@
gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 0);
}
-
-class CFileType : public IFileTypeList
+struct filetype_pair_t
{
- struct filetype_pair_t
+ filetype_pair_t()
+ : m_minor("")
{
- filetype_pair_t()
- : m_minor(""), m_type(filetype_t())
- {}
- filetype_pair_t(const char* minor, filetype_t type)
- : m_minor(minor), m_type(type)
- {}
- const char* m_minor;
- filetype_t m_type;
- };
+ }
+ filetype_pair_t(const char* minor, filetype_t type)
+ : m_minor(minor), m_type(type)
+ {
+ }
+ const char* m_minor;
+ filetype_t m_type;
+};
+class FileTypeList : public IFileTypeList
+{
struct filetype_copy_t
{
- void operator=(const filetype_pair_t& other)
+ filetype_copy_t(const filetype_pair_t& other)
+ : m_minor(other.m_minor), m_name(other.m_type.name), m_pattern(other.m_type.pattern)
{
- m_minor = other.m_minor;
- m_name = other.m_type.name;
- m_pattern = other.m_type.pattern;
}
string_t m_minor;
string_t m_name;
string_t m_pattern;
};
+
+ typedef std::list<filetype_copy_t> Types;
+ Types m_types;
public:
- CFileType()
+
+ typedef Types::const_iterator const_iterator;
+ const_iterator begin() const
{
- m_nTypes = 0;
- m_pTypes = 0;
- m_strWin32Filters = 0;
- m_pstrGTKMasks = 0;
+ return m_types.begin();
}
-
- ~CFileType()
+ const_iterator end() const
{
- delete[] m_pTypes;
- DestroyWin32Filters();
- DestroyGTKMasks();
+ return m_types.end();
}
- void addType(const char* minor, filetype_t type)
+ std::size_t size() const
{
- filetype_copy_t* newTypes = new filetype_copy_t [m_nTypes+1];
- if(m_nTypes > 0)
- {
- for(int i=0; i<m_nTypes; i++)
- newTypes[i] = m_pTypes[i];
- delete[] m_pTypes;
- }
- m_pTypes = newTypes;
- m_pTypes[m_nTypes] = filetype_pair_t(minor, type);
- m_nTypes++;
- ConstructGTKMasks();
- ConstructWin32Filters();
+ return m_types.size();
}
-
- filetype_pair_t GetTypeForWin32Filter(const char *filter) const
- {
- for(int i=0; i<m_nTypes; i++)
- if(strcmp(m_pTypes[i].m_pattern.c_str(), filter)==0)
- return filetype_pair_t(m_pTypes[i].m_minor.c_str(), filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str()));
- return filetype_pair_t();
- }
- filetype_pair_t GetTypeForGTKMask(const char *mask) const
+ void addType(const char* minor, filetype_t type)
{
- for(int i=0; i<m_nTypes; i++)
- if(strcmp(m_pstrGTKMasks[i],mask)==0)
- return filetype_pair_t(m_pTypes[i].m_minor.c_str(), filetype_t(m_pTypes[i].m_name.c_str(), m_pTypes[i].m_pattern.c_str()));
- return filetype_pair_t();
+ m_types.push_back(filetype_pair_t(minor, type));
}
+};
- char *m_strWin32Filters;
- char **m_pstrGTKMasks;
-private:
- int m_nTypes;
- filetype_copy_t *m_pTypes;
+#ifdef WIN32
- void DestroyWin32Filters()
+class Win32Filters
+{
+ const FileTypeList& m_types;
+ auto_array<char> m_filters;
+public:
+ Win32Filters(const FileTypeList& typeList) : m_types(typeList)
{
- delete[] m_strWin32Filters;
- }
-
- void ConstructWin32Filters()
- {
- DestroyWin32Filters();
std::size_t len = 0;
- for(int i=0; i<m_nTypes; i++)
- len = len + strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str())*2 + 5;
- m_strWin32Filters = new char[len+1]; // length + null char
- char *w = m_strWin32Filters;
- for(int i=0; i<m_nTypes; i++)
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
{
- for(const char *r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
+ len = len + strlen((*i).m_name.c_str()) + strlen((*i).m_pattern.c_str()) * 2 + 5;
+ }
+ m_filters.allocate(len + 1); // length + null char
+ char *w = m_filters.data();
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
+ {
+ for(const char *r = (*i).m_name.c_str(); *r!='\0'; r++, w++)
+ {
*w = *r;
+ }
*w++ = ' ';
*w++ = '(';
- for(const char *r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
+ for(const char *r = (*i).m_pattern.c_str(); *r!='\0'; r++, w++)
+ {
*w = *r;
+ }
*w++ = ')';
*w++ = '\0';
- for(const char *r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
+ for(const char *r = (*i).m_pattern.c_str(); *r!='\0'; r++, w++)
+ {
*w = (*r == ',') ? ';' : *r;
+ }
*w++ = '\0';
}
- m_strWin32Filters[len] = '\0';
+ m_filters[len] = '\0';
}
-
- void DestroyGTKMasks()
+ filetype_pair_t getType(const char *filter) const
{
- if(m_pstrGTKMasks != 0)
- for(char **p = m_pstrGTKMasks; *p != 0; p++)
- delete[] *p;
- delete[] m_pstrGTKMasks;
- }
-
- void ConstructGTKMasks()
- {
- DestroyGTKMasks();
- m_pstrGTKMasks = new char*[m_nTypes+1];
- for(int i=0; i<m_nTypes; i++)
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
{
- std::size_t len = strlen(m_pTypes[i].m_name.c_str()) + strlen(m_pTypes[i].m_pattern.c_str()) + 3;
- m_pstrGTKMasks[i] = new char[len+1]; // length + null char
- char *w = m_pstrGTKMasks[i];
- for(const char *r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
- *w = *r;
- *w++ = ' ';
- *w++ = '<';
- for(const char *r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
- *w = *r;
- *w++ = '>';
- *w++ = '\0';
+ if(string_equal((*i).m_pattern.c_str(), filter))
+ {
+ return filetype_pair_t((*i).m_minor.c_str(), filetype_t((*i).m_name.c_str(), (*i).m_pattern.c_str()));
+ }
}
- m_pstrGTKMasks[m_nTypes] = 0;
+ return filetype_pair_t();
}
-
+ const char* getFilters() const
+ {
+ return m_filters.data();
+ }
};
-#ifdef WIN32
-
#define WIN32_LEAN_AND_MEAN
#include <gdk/gdkwin32.h>
#include <commdlg.h>
-static OPENFILENAME ofn; /* common dialog box structure */
-static char szDirName[MAX_PATH]; /* directory string */
-static char szFile[MAX_PATH]; /* filename string */
-static char szFileTitle[MAX_PATH]; /* file title string */
-static int i, cbString; /* integer count variables */
-static HANDLE hf; /* file handle */
-#else
-static char szFile[1024];
-#endif
+static char szFile[MAX_PATH]; /* filename string */
+
#define FILEDLG_CUSTOM_FILTER_LENGTH 64
// to be used with the advanced file selector
-const char* file_dialog_show(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
+const char* file_dialog_show_win32(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
{
// Gtk dialog
- GtkWidget* file_sel;
int loop = 1;
char *new_path = 0;
const char* r;
char* w;
filetype_t type;
- CFileType typelist;
+ FileTypeList typelist;
if(pattern == 0)
{
@@ -2018,193 +1903,289 @@
GetFileTypeRegistry()->getTypeList(pattern, &typelist);
-#ifdef WIN32
+ Win32Filters filters(typelist);
+
// win32 dialog stores the selected "save as type" extension in the second null-terminated string
char customfilter[FILEDLG_CUSTOM_FILTER_LENGTH];
- if (g_layout_globals.m_bNativeGUI)
+ static OPENFILENAME ofn; /* common dialog box structure */
+ static char szDirName[MAX_PATH]; /* directory string */
+ static char szFile[MAX_PATH]; /* filename string */
+ static char szFileTitle[MAX_PATH]; /* file title string */
+ static int i, cbString; /* integer count variables */
+ static HANDLE hf; /* file handle */
+
+ // do that the native way
+ /* Place the terminating null character in the szFile. */
+ szFile[0] = '\0';
+ customfilter[0] = customfilter[1] = customfilter[2] = '\0';
+
+ /* Set the members of the OPENFILENAME structure. */
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window);
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFilter = filters.getFilters();
+ ofn.lpstrCustomFilter = customfilter;
+ ofn.nMaxCustFilter = sizeof(customfilter);
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = 0; // we don't need to get the name of the file
+ if(path)
{
- // do that the native way
- /* Place the terminating null character in the szFile. */
- szFile[0] = '\0';
- customfilter[0] = customfilter[1] = customfilter[2] = '\0';
-
- /* Set the members of the OPENFILENAME structure. */
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window);
- ofn.nFilterIndex = 0;
- ofn.lpstrFilter = typelist.m_strWin32Filters;
- ofn.lpstrCustomFilter = customfilter;
- ofn.nMaxCustFilter = sizeof(customfilter);
- ofn.lpstrFile = szFile;
- ofn.nMaxFile = sizeof(szFile);
- ofn.lpstrFileTitle = 0; // we don't need to get the name of the file
- if(path)
+ // szDirName: Radiant uses unix convention for paths internally
+ // Win32 (of course) and Gtk (who would have thought) expect the '\\' convention
+ // copy path, replacing dir separators as appropriate
+ for(r=path, w=szDirName; *r!='\0'; r++)
+ *w++ = (*r=='/') ? '\\' : *r;
+ // terminate string
+ *w = '\0';
+ ofn.lpstrInitialDir = szDirName;
+ }
+ else ofn.lpstrInitialDir = 0;
+ ofn.lpstrTitle = title;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+
+ /* Display the Open dialog box. */
+ // it's open or close depending on 'open' parameter
+ if (open)
+ {
+ if (!GetOpenFileName(&ofn))
+ return 0; // canceled
+ }
+ else
+ {
+ if (!GetSaveFileName(&ofn))
+ return 0; // canceled
+ }
+
+ if(!string_equal(pattern, "*"))
+ {
+ type = filters.getType(customfilter+1).m_type;
+ }
+
+ // don't return an empty filename
+ if(szFile[0] == '\0') return 0;
+
+ // convert back to unix format
+ for(w=szFile; *w!='\0'; w++)
+ {
+ if(*w=='\\')
{
- // szDirName: Radiant uses unix convention for paths internally
- // Win32 (of course) and Gtk (who would have thought) expect the '\\' convention
- // copy path, replacing dir separators as appropriate
- for(r=path, w=szDirName; *r!='\0'; r++)
- *w++ = (*r=='/') ? '\\' : *r;
- // terminate string
- *w = '\0';
- ofn.lpstrInitialDir = szDirName;
+ *w = '/';
}
- else ofn.lpstrInitialDir = 0;
- ofn.lpstrTitle = title;
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
-
- /* Display the Open dialog box. */
- // it's open or close depending on 'open' parameter
- if (open)
+ }
+ // when saving, force an extension depending on filetype
+ /* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
+ if(!open && !string_equal(pattern, "*"))
+ {
+ // last ext separator
+ const char* extension = path_get_extension(szFile);
+ // no extension
+ if(string_empty(extension))
{
- if (!GetOpenFileName(&ofn))
- return 0; // canceled
+ strcat(szFile, type.pattern+1);
}
else
{
- if (!GetSaveFileName(&ofn))
- return 0; // canceled
+ strcpy(szFile + (extension - szFile), type.pattern+2);
}
-
- if(!string_equal(pattern, "*"))
- type = typelist.GetTypeForWin32Filter(customfilter+1).m_type;
-
}
- else
- {
-#endif
- // do that the Gtk way
- if (title == 0)
- title = open ? "Open File" : "Save File";
-
- // we expect an actual path below, if the path is 0 we might crash
- if (!path || path[0] == '\0')
- {
-#ifdef WIN32
- path = "C:\\";
-#elif defined (__linux__) || defined (__APPLE__)
- path = "/";
-#else
- path = "/";
-#endif
- }
- // alloc new path with extra char for dir separator
- new_path = new char[strlen(path)+1+1];
- // copy path, replacing dir separators as appropriate
- for(r=path, w=new_path; *r!='\0'; r++)
- *w++ = (*r=='/') ? G_DIR_SEPARATOR : *r;
- // add dir separator to end of path if required
- if(*(w-1) != G_DIR_SEPARATOR) *w++ = G_DIR_SEPARATOR;
- // terminate string
- *w = '\0';
+ return szFile;
+}
- file_sel = gtk_file_selection_new (title);
-
-#if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0
- // set the masks
- gtk_file_selection_clear_masks (GTK_FILE_SELECTION (file_sel));
- gtk_file_selection_set_masks (GTK_FILE_SELECTION (file_sel), const_cast<const char**>(typelist.m_pstrGTKMasks));
#endif
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
- GTK_SIGNAL_FUNC (file_sel_callback), gint_to_pointer (eIDOK));
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
- GTK_SIGNAL_FUNC (file_sel_callback), gint_to_pointer (eIDCANCEL));
- gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
- GTK_SIGNAL_FUNC (file_sel_delete_callback), 0);
- gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
-
- if (parent != 0)
+
+class GTKMasks
+{
+ const FileTypeList& m_types;
+public:
+ std::vector<string_t> m_filters;
+ std::vector<string_t> m_masks;
+
+ GTKMasks(const FileTypeList& types) : m_types(types)
+ {
+ m_masks.reserve(m_types.size());
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
{
- gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
+ std::size_t len = strlen((*i).m_name.c_str()) + strlen((*i).m_pattern.c_str()) + 3;
+ StringOutputStream buffer(len + 1); // length + null char
+
+ buffer << (*i).m_name.c_str() << " <" << (*i).m_pattern.c_str() << ">";
+
+ m_masks.push_back(buffer.c_str());
}
-
- bool success = false;
- g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
- g_object_set_data (G_OBJECT (file_sel), "success", &success);
-
- if (!open)
+
+ m_filters.reserve(m_types.size());
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
{
- g_object_set_data (G_OBJECT (file_sel), "overwrite", gint_to_pointer (1));
+ m_filters.push_back((*i).m_pattern);
}
-
- if (new_path != 0)
+ }
+
+ filetype_pair_t GetTypeForGTKMask(const char *mask) const
+ {
+ std::vector<string_t>::const_iterator j = m_masks.begin();
+ for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i, ++j)
{
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), new_path);
- delete[] new_path;
+ if(string_equal((*j).c_str(), mask))
+ {
+ return filetype_pair_t((*i).m_minor.c_str(), filetype_t((*i).m_name.c_str(), (*i).m_pattern.c_str()));
+ }
}
+ return filetype_pair_t();
+ }
- gtk_grab_add (file_sel);
- gtk_widget_show (file_sel);
+};
- while (loop)
- {
- gtk_main_iteration ();
- }
- if(success)
- {
-#if 0 //!\todo Add masks to GtkFileSelection in gtk2
- if(!string_equal(pattern, "*"))
- type = typelist.GetTypeForGTKMask(GTK_FILE_SELECTION (file_sel)->mask).m_type;
-#endif
- strcpy(szFile, gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
- }
+static char g_file_dialog_file[1024];
+
+const char* file_dialog_show(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
+{
+ char *new_path = 0;
+
+ const char* r;
+ char* w;
+ filetype_t type;
+
+ if(pattern == 0)
+ {
+ pattern = "*";
+ }
+
+ FileTypeList typelist;
+ GetFileTypeRegistry()->getTypeList(pattern, &typelist);
+
+ GTKMasks masks(typelist);
+
+ if (title == 0)
+ title = open ? "Open File" : "Save File";
- gtk_grab_remove (file_sel);
- gtk_widget_destroy (file_sel);
+ // we expect an actual path below, if the path is 0 we might crash
+ if (!path || path[0] == '\0')
+ {
#ifdef WIN32
- }
+ path = "C:\\";
+#elif defined (__linux__) || defined (__APPLE__)
+ path = "/";
+#else
+ path = "/";
#endif
+ }
- // don't return an empty filename
- if(szFile[0] == '\0') return 0;
+ // alloc new path with extra char for dir separator
+ new_path = new char[strlen(path)+1+1];
+ // copy path, replacing dir separators as appropriate
+ for(r=path, w=new_path; *r!='\0'; r++)
+ *w++ = (*r=='/') ? G_DIR_SEPARATOR : *r;
+ // add dir separator to end of path if required
+ if(*(w-1) != G_DIR_SEPARATOR) *w++ = G_DIR_SEPARATOR;
+ // terminate string
+ *w = '\0';
- // convert back to unix format
- for(w=szFile; *w!='\0'; w++)
- if(*w=='\\')
- *w = '/';
+ GtkWidget* dialog;
+ if (open)
+ {
+ dialog = gtk_file_chooser_dialog_new(title,
+ GTK_WINDOW(parent),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ }
+ else
+ {
+ dialog = gtk_file_chooser_dialog_new(title,
+ GTK_WINDOW(parent),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "unnamed");
+ }
-#if defined(WIN32)
- if (g_layout_globals.m_bNativeGUI) // filetype mask not supported in gtk dialog yet
+ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
+
+ if (new_path != 0)
{
- // when saving, force an extension depending on filetype
- /* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
- if(!open && !string_equal(pattern, "*"))
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), new_path);
+ delete[] new_path;
+ }
+
+ // we should add all important paths as shortcut folder...
+ // gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog), "/tmp/", NULL);
+
+
+ for(std::size_t i = 0; i < masks.m_filters.size(); ++i)
+ {
+ GtkFileFilter* filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern(filter, masks.m_filters[i].c_str());
+ gtk_file_filter_set_name(filter, masks.m_masks[i].c_str());
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+ }
+
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ strcpy(g_file_dialog_file, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
+
+ if(!string_equal(pattern, "*"))
{
+ GtkFileFilter* filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
+ type = masks.GetTypeForGTKMask(gtk_file_filter_get_name(filter)).m_type;
// last ext separator
- const char* extension = path_get_extension(szFile);
+ const char* extension = path_get_extension(g_file_dialog_file);
// no extension
if(string_empty(extension))
{
- strcat(szFile, type.pattern+1);
+ strcat(g_file_dialog_file, type.pattern+1);
}
else
{
- strcpy(szFile + (extension - szFile), type.pattern+2);
+ strcpy(g_file_dialog_file + (extension - g_file_dialog_file), type.pattern+2);
}
}
+
+ // convert back to unix format
+ for(w=g_file_dialog_file; *w!='\0'; w++)
+ {
+ if(*w=='\\')
+ {
+ *w = '/';
+ }
+ }
}
-#endif
+ else
+ {
+ g_file_dialog_file[0] = '\0';
+ }
- return szFile;
+ gtk_widget_destroy(dialog);
+
+ // don't return an empty filename
+ if(g_file_dialog_file[0] == '\0') return NULL;
+
+ return g_file_dialog_file;
}
const char* file_dialog (GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
{
for(;;)
{
- const char* file = file_dialog_show(parent, open, title, path, pattern);
+ const char* file = g_layout_globals.m_bNativeGUI
+ ? file_dialog_show_win32(parent, open, title, path, pattern)
+ : file_dialog_show(parent, open, title, path, pattern);
+
if(open
- || !file_exists(szFile)
+ || !file_exists(file)
|| gtk_MessageBox(parent, "File already exists.\nOverwrite?", "GtkRadiant", eMB_NOYES) == eIDYES)
{
return file;
}
}
- return 0;
+ return NULL;
}
#ifdef WIN32
More information about the Gtkradiant
mailing list