[gedit] Implement native OS open/save dialogs



commit 94a87ac89337ed6ff71621b8cac0f2a32ea7aafc
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Tue Sep 2 15:16:27 2014 +0200

    Implement native OS open/save dialogs

 gedit/Makefile.am                     |   12 +-
 gedit/gedit-commands-file.c           |  104 ++--
 gedit/gedit-encoding-items.c          |  135 +++++
 gedit/gedit-encoding-items.h          |   40 ++
 gedit/gedit-encodings-combo-box.c     |   76 +---
 gedit/gedit-file-chooser-dialog-gtk.c |  620 +++++++++++++++++++++++
 gedit/gedit-file-chooser-dialog-gtk.h |   64 +++
 gedit/gedit-file-chooser-dialog-osx.c |  879 +++++++++++++++++++++++++++++++++
 gedit/gedit-file-chooser-dialog-osx.h |   64 +++
 gedit/gedit-file-chooser-dialog.c     |  625 +++++++-----------------
 gedit/gedit-file-chooser-dialog.h     |  126 ++++-
 gedit/gedit-marshal.list              |    1 +
 po/POTFILES.in                        |    4 +-
 13 files changed, 2149 insertions(+), 601 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index 0f388b3..32df810 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -49,9 +49,11 @@ gedit_libosx_la_LIBADD = -lobjc
 gedit_libosx_la_CPPFLAGS = $(gedit_common_cppflags)
 gedit_libosx_la_CFLAGS = -xobjective-c $(gedit_common_cflags)
 
-gedit_libosx_la_SOURCES =      \
-       gedit/gedit-app-osx.c   \
-       gedit/gedit-app-osx.h
+gedit_libosx_la_SOURCES =                      \
+       gedit/gedit-app-osx.c                   \
+       gedit/gedit-app-osx.h                   \
+       gedit/gedit-file-chooser-dialog-osx.c   \
+       gedit/gedit-file-chooser-dialog-osx.h
 
 gedit_libgedit_la_LIBADD += gedit/libosx.la
 endif
@@ -101,8 +103,10 @@ gedit_NOINST_H_FILES =                             \
        gedit/gedit-dirs.h                      \
        gedit/gedit-documents-panel.h           \
        gedit/gedit-encodings-dialog.h          \
+       gedit/gedit-encoding-items.h            \
        gedit/gedit-open-document-selector.h    \
        gedit/gedit-file-chooser-dialog.h       \
+       gedit/gedit-file-chooser-dialog-gtk.h   \
        gedit/gedit-highlight-mode-dialog.h     \
        gedit/gedit-highlight-mode-selector.h   \
        gedit/gedit-history-entry.h             \
@@ -173,8 +177,10 @@ gedit_libgedit_c_files =                   \
        gedit/gedit-documents-panel.c           \
        gedit/gedit-encodings-combo-box.c       \
        gedit/gedit-encodings-dialog.c          \
+       gedit/gedit-encoding-items.c            \
        gedit/gedit-open-document-selector.c    \
        gedit/gedit-file-chooser-dialog.c       \
+       gedit/gedit-file-chooser-dialog-gtk.c   \
        gedit/gedit-highlight-mode-dialog.c     \
        gedit/gedit-highlight-mode-selector.c   \
        gedit/gedit-history-entry.c             \
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index f4057d0..768e942 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -379,17 +379,17 @@ open_dialog_response_cb (GeditFileChooserDialog *dialog,
 
        if (response_id != GTK_RESPONSE_OK)
        {
-               gtk_widget_destroy (GTK_WIDGET (dialog));
+               gedit_file_chooser_dialog_destroy (dialog);
 
                return;
        }
 
-       files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog));
+       files = gedit_file_chooser_dialog_get_files (dialog);
        g_return_if_fail (files != NULL);
 
        encoding = gedit_file_chooser_dialog_get_encoding (dialog);
 
-       gtk_widget_destroy (GTK_WIDGET (dialog));
+       gedit_file_chooser_dialog_destroy (dialog);
 
        if (window == NULL)
        {
@@ -419,7 +419,7 @@ _gedit_cmd_file_open (GSimpleAction *action,
                       gpointer       user_data)
 {
        GeditWindow *window = NULL;
-       GtkWidget *open_dialog;
+       GeditFileChooserDialog *open_dialog;
 
        if (GEDIT_IS_WINDOW (user_data))
        {
@@ -448,13 +448,11 @@ _gedit_cmd_file_open (GSimpleAction *action,
        }
 
        /* Translators: "Open" is the title of the file chooser window */
-       open_dialog = gedit_file_chooser_dialog_new (_("Open"),
-                                                    window ? GTK_WINDOW (window) : NULL,
-                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
-                                                    NULL,
-                                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                                    _("_Open"), GTK_RESPONSE_OK,
-                                                    NULL);
+       open_dialog = gedit_file_chooser_dialog_create (_("Open"),
+                                                       window ? GTK_WINDOW (window) : NULL,
+                                                       GEDIT_FILE_CHOOSER_OPEN |
+                                                       GEDIT_FILE_CHOOSER_ENABLE_ENCODING,
+                                                       NULL);
 
        if (window != NULL)
        {
@@ -488,13 +486,7 @@ _gedit_cmd_file_open (GSimpleAction *action,
 
                if (default_path != NULL)
                {
-                       gchar *uri;
-
-                       uri = g_file_get_uri (default_path);
-                       gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (open_dialog),
-                                                                uri);
-
-                       g_free (uri);
+                       gedit_file_chooser_dialog_set_current_folder (open_dialog, default_path);
                        g_object_unref (default_path);
                }
        }
@@ -504,7 +496,7 @@ _gedit_cmd_file_open (GSimpleAction *action,
                          G_CALLBACK (open_dialog_response_cb),
                          window);
 
-       gtk_widget_show (open_dialog);
+       gedit_file_chooser_dialog_show (open_dialog);
 }
 
 void
@@ -715,7 +707,7 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
 
        if (response_id != GTK_RESPONSE_OK)
        {
-               gtk_widget_destroy (GTK_WIDGET (dialog));
+               gedit_file_chooser_dialog_destroy (dialog);
 
                goto save_next_tab;
        }
@@ -734,7 +726,7 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
                doc = gedit_tab_get_document (tab);
                file = gedit_document_get_file (doc);
 
-               location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+               location = gedit_file_chooser_dialog_get_file (dialog);
                g_return_if_fail (location != NULL);
 
                compression_type = get_compression_type_from_file (location);
@@ -747,7 +739,7 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
                                                 location,
                                                 compression_type != GTK_SOURCE_COMPRESSION_TYPE_NONE))
                        {
-                               gtk_widget_destroy (GTK_WIDGET (dialog));
+                               gedit_file_chooser_dialog_destroy (dialog);
                                g_object_unref (location);
 
                                goto save_next_tab;
@@ -757,7 +749,7 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
                encoding = gedit_file_chooser_dialog_get_encoding (dialog);
                newline_type = gedit_file_chooser_dialog_get_newline_type (dialog);
 
-               gtk_widget_destroy (GTK_WIDGET (dialog));
+               gedit_file_chooser_dialog_destroy (dialog);
 
                doc = gedit_tab_get_document (tab);
                g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
@@ -823,25 +815,30 @@ save_next_tab:
 }
 
 static GtkFileChooserConfirmation
-confirm_overwrite_callback (GtkFileChooser *dialog,
-                           gpointer        data)
+confirm_overwrite_callback (GeditFileChooserDialog *dialog,
+                           gpointer                data)
 {
-       gchar *uri;
        GFile *file;
        GtkFileChooserConfirmation res;
 
        gedit_debug (DEBUG_COMMANDS);
 
-       uri = gtk_file_chooser_get_uri (dialog);
-       file = g_file_new_for_uri (uri);
-       g_free (uri);
+       file = gedit_file_chooser_dialog_get_file (dialog);
 
        if (is_read_only (file))
        {
-               if (replace_read_only_file (GTK_WINDOW (dialog), file))
+               GtkWindow *win;
+
+               win = gedit_file_chooser_dialog_get_window (dialog);
+
+               if (replace_read_only_file (win, file))
+               {
                        res = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
+               }
                else
+               {
                        res = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
+               }
        }
        else
        {
@@ -858,29 +855,29 @@ void
 _gedit_cmd_file_save_as_tab (GeditTab    *tab,
                              GeditWindow *window)
 {
-       GtkWidget *save_dialog;
+       GeditFileChooserDialog *save_dialog;
        GtkWindowGroup *wg;
        GeditDocument *doc;
        GtkSourceFile *file;
        GFile *location;
        const GtkSourceEncoding *encoding;
        GtkSourceNewlineType newline_type;
+       GtkWindow *win;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (GEDIT_IS_WINDOW (window));
 
        gedit_debug (DEBUG_COMMANDS);
 
-       save_dialog = gedit_file_chooser_dialog_new (_("Save As"),
-                                                    GTK_WINDOW (window),
-                                                    GTK_FILE_CHOOSER_ACTION_SAVE,
-                                                    NULL,
-                                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                                    _("_Save"), GTK_RESPONSE_OK,
-                                                    NULL);
+       save_dialog = gedit_file_chooser_dialog_create (_("Save As"),
+                                                       GTK_WINDOW (window),
+                                                       GEDIT_FILE_CHOOSER_SAVE |
+                                                       GEDIT_FILE_CHOOSER_ENABLE_ENCODING |
+                                                       GEDIT_FILE_CHOOSER_ENABLE_LINE_ENDING,
+                                                       NULL);
+
+       gedit_file_chooser_dialog_set_do_overwrite_confirmation (save_dialog, TRUE);
 
-       gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (save_dialog),
-                                                       TRUE);
        g_signal_connect (save_dialog,
                          "confirm-overwrite",
                          G_CALLBACK (confirm_overwrite_callback),
@@ -888,10 +885,15 @@ _gedit_cmd_file_save_as_tab (GeditTab    *tab,
 
        wg = gedit_window_get_group (window);
 
-       gtk_window_group_add_window (wg, GTK_WINDOW (save_dialog));
+       win = gedit_file_chooser_dialog_get_window (save_dialog);
+
+       if (win != NULL)
+       {
+               gtk_window_group_add_window (wg, win);
+       }
 
        /* Save As dialog is modal to its main window */
-       gtk_window_set_modal (GTK_WINDOW (save_dialog), TRUE);
+       gedit_file_chooser_dialog_set_modal (save_dialog, TRUE);
 
        /* Set the suggested file name */
        doc = gedit_tab_get_document (tab);
@@ -900,9 +902,7 @@ _gedit_cmd_file_save_as_tab (GeditTab    *tab,
 
        if (location != NULL)
        {
-               gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog),
-                                          location,
-                                          NULL);
+               gedit_file_chooser_dialog_set_file (save_dialog, location);
        }
        else
        {
@@ -914,18 +914,14 @@ _gedit_cmd_file_save_as_tab (GeditTab    *tab,
 
                if (default_path != NULL)
                {
-                       gchar *uri;
-
-                       uri = g_file_get_uri (default_path);
-                       gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (save_dialog),
-                                                                uri);
+                       gedit_file_chooser_dialog_set_current_folder (save_dialog,
+                                                                     default_path);
 
-                       g_free (uri);
                        g_object_unref (default_path);
                }
 
-               gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog),
-                                                  docname);
+               gedit_file_chooser_dialog_set_current_name (save_dialog,
+                                                           docname);
 
                g_free (docname);
        }
@@ -955,7 +951,7 @@ _gedit_cmd_file_save_as_tab (GeditTab    *tab,
                          G_CALLBACK (save_dialog_response_cb),
                          window);
 
-       gtk_widget_show (save_dialog);
+       gedit_file_chooser_dialog_show (save_dialog);
 }
 
 void
diff --git a/gedit/gedit-encoding-items.c b/gedit/gedit-encoding-items.c
new file mode 100644
index 0000000..ae6964b
--- /dev/null
+++ b/gedit/gedit-encoding-items.c
@@ -0,0 +1,135 @@
+/*
+ * gedit-encoding-items.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-encoding-items.h"
+#include "gedit-settings.h"
+#include "gedit-utils.h"
+
+#include <glib/gi18n.h>
+
+struct _GeditEncodingItem
+{
+       const GtkSourceEncoding *encoding;
+       gchar *name;
+};
+
+static GeditEncodingItem *
+gedit_encoding_item_new (const GtkSourceEncoding *encoding,
+                         gchar                   *name)
+{
+       GeditEncodingItem *item = g_slice_new (GeditEncodingItem);
+
+       item->encoding = encoding;
+       item->name = name;
+
+       return item;
+}
+
+void
+gedit_encoding_item_free (GeditEncodingItem *item)
+{
+       if (item == NULL)
+       {
+               return;
+       }
+
+       g_free (item->name);
+       g_slice_free (GeditEncodingItem, item);
+}
+
+const GtkSourceEncoding *
+gedit_encoding_item_get_encoding (GeditEncodingItem *item)
+{
+       g_return_val_if_fail (item != NULL, NULL);
+
+       return item->encoding;
+}
+
+const gchar *
+gedit_encoding_item_get_name (GeditEncodingItem *item)
+{
+       g_return_val_if_fail (item != NULL, NULL);
+
+       return item->name;
+}
+
+GSList *
+gedit_encoding_items_get (void)
+{
+       GSList *ret = NULL;
+       const GtkSourceEncoding *utf8_encoding;
+       const GtkSourceEncoding *current_encoding;
+       GSettings *enc_settings;
+       gchar *str;
+       GSList *encodings;
+       gchar **enc_strv;
+
+       utf8_encoding = gtk_source_encoding_get_utf8 ();
+       current_encoding = gtk_source_encoding_get_current ();
+
+       enc_settings = g_settings_new ("org.gnome.gedit.preferences.encodings");
+
+       if (utf8_encoding != current_encoding)
+       {
+               str = gtk_source_encoding_to_string (utf8_encoding);
+       }
+       else
+       {
+               str = g_strdup_printf (_("Current Locale (%s)"),
+                                      gtk_source_encoding_get_charset (utf8_encoding));
+       }
+
+       ret = g_slist_prepend (ret, gedit_encoding_item_new (utf8_encoding, str));
+
+       if (current_encoding != utf8_encoding &&
+           current_encoding != NULL)
+       {
+               str = g_strdup_printf (_("Current Locale (%s)"),
+                                      gtk_source_encoding_get_charset (current_encoding));
+
+               ret = g_slist_prepend (ret, gedit_encoding_item_new (current_encoding, str));
+       }
+
+       enc_strv = g_settings_get_strv (enc_settings, GEDIT_SETTINGS_ENCODING_SHOWN_IN_MENU);
+
+       encodings = _gedit_utils_encoding_strv_to_list ((const gchar * const *)enc_strv);
+       g_strfreev (enc_strv);
+
+       g_object_unref (enc_settings);
+
+       while (encodings)
+       {
+               const GtkSourceEncoding *enc = encodings->data;
+
+               if (enc != current_encoding &&
+                   enc != utf8_encoding &&
+                   enc != NULL)
+               {
+                       str = gtk_source_encoding_to_string (enc);
+                       ret = g_slist_prepend (ret, gedit_encoding_item_new (enc, str));
+               }
+
+               encodings = g_slist_delete_link (encodings, encodings);
+       }
+
+       return g_slist_reverse (ret);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-encoding-items.h b/gedit/gedit-encoding-items.h
new file mode 100644
index 0000000..950ba87
--- /dev/null
+++ b/gedit/gedit-encoding-items.h
@@ -0,0 +1,40 @@
+/*
+ * gedit-encoding-items.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_ENCODING_ITEMS_H__
+#define __GEDIT_ENCODING_ITEMS_H__
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GeditEncodingItem GeditEncodingItem;
+
+GSList                         *gedit_encoding_items_get               (void);
+
+void                            gedit_encoding_item_free               (GeditEncodingItem *item);
+const GtkSourceEncoding                *gedit_encoding_item_get_encoding       (GeditEncodingItem *item);
+const gchar                    *gedit_encoding_item_get_name           (GeditEncodingItem *item);
+
+G_END_DECLS
+
+#endif /* __GEDIT_ENCODING_ITEMS_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-encodings-combo-box.c b/gedit/gedit-encodings-combo-box.c
index dad6b6d..88f19da 100644
--- a/gedit/gedit-encodings-combo-box.c
+++ b/gedit/gedit-encodings-combo-box.c
@@ -29,11 +29,10 @@
 #include "gedit-encodings-dialog.h"
 #include "gedit-settings.h"
 #include "gedit-utils.h"
+#include "gedit-encoding-items.h"
 
 struct _GeditEncodingsComboBoxPrivate
 {
-       GSettings *enc_settings;
-
        GtkListStore *store;
        glong changed_id;
 
@@ -108,7 +107,6 @@ gedit_encodings_combo_box_dispose (GObject *object)
        GeditEncodingsComboBox *combo = GEDIT_ENCODINGS_COMBO_BOX (object);
 
        g_clear_object (&combo->priv->store);
-       g_clear_object (&combo->priv->enc_settings);
 
        G_OBJECT_CLASS (gedit_encodings_combo_box_parent_class)->dispose (object);
 }
@@ -288,11 +286,7 @@ update_menu (GeditEncodingsComboBox *menu)
 {
        GtkListStore *store;
        GtkTreeIter iter;
-       GSList *encodings, *l;
-       gchar *str;
-       const GtkSourceEncoding *utf8_encoding;
-       const GtkSourceEncoding *current_encoding;
-       gchar **enc_strv;
+       GSList *encodings;
 
        store = menu->priv->store;
 
@@ -313,73 +307,23 @@ update_menu (GeditEncodingsComboBox *menu)
                add_separator (store);
        }
 
-       utf8_encoding = gtk_source_encoding_get_utf8 ();
-       current_encoding = gtk_source_encoding_get_current ();
+       encodings = gedit_encoding_items_get ();
 
-       if (utf8_encoding != current_encoding)
+       while (encodings)
        {
-               str = gtk_source_encoding_to_string (utf8_encoding);
-       }
-       else
-       {
-               str = g_strdup_printf (_("Current Locale (%s)"),
-                                      gtk_source_encoding_get_charset (utf8_encoding));
-       }
-
-       gtk_list_store_append (store, &iter);
-       gtk_list_store_set (store, &iter,
-                           COLUMN_NAME, str,
-                           COLUMN_ENCODING, utf8_encoding,
-                           COLUMN_CONFIGURE_ROW, FALSE,
-                           -1);
-
-       g_free (str);
-
-       if (current_encoding != utf8_encoding &&
-           current_encoding != NULL)
-       {
-               str = g_strdup_printf (_("Current Locale (%s)"),
-                                      gtk_source_encoding_get_charset (current_encoding));
+               GeditEncodingItem *item = encodings->data;
 
                gtk_list_store_append (store, &iter);
                gtk_list_store_set (store, &iter,
-                                   COLUMN_NAME, str,
-                                   COLUMN_ENCODING, current_encoding,
+                                   COLUMN_NAME, gedit_encoding_item_get_name (item),
+                                   COLUMN_ENCODING, gedit_encoding_item_get_encoding (item),
                                    COLUMN_CONFIGURE_ROW, FALSE,
                                    -1);
 
-               g_free (str);
+               gedit_encoding_item_free (item);
+               encodings = g_slist_delete_link (encodings, encodings);
        }
 
-       enc_strv = g_settings_get_strv (menu->priv->enc_settings,
-                                       GEDIT_SETTINGS_ENCODING_SHOWN_IN_MENU);
-
-       encodings = _gedit_utils_encoding_strv_to_list ((const gchar * const *)enc_strv);
-       g_strfreev (enc_strv);
-
-       for (l = encodings; l != NULL; l = g_slist_next (l))
-       {
-               const GtkSourceEncoding *enc = l->data;
-
-               if (enc != current_encoding &&
-                   enc != utf8_encoding &&
-                   enc != NULL)
-               {
-                       str = gtk_source_encoding_to_string (enc);
-
-                       gtk_list_store_append (store, &iter);
-                       gtk_list_store_set (store, &iter,
-                                           COLUMN_NAME, str,
-                                           COLUMN_ENCODING, enc,
-                                           COLUMN_CONFIGURE_ROW, FALSE,
-                                           -1);
-
-                       g_free (str);
-               }
-       }
-
-       g_slist_free (encodings);
-
        add_separator (store);
 
        gtk_list_store_append (store, &iter);
@@ -402,8 +346,6 @@ gedit_encodings_combo_box_init (GeditEncodingsComboBox *menu)
 {
        menu->priv = gedit_encodings_combo_box_get_instance_private (menu);
 
-       menu->priv->enc_settings = g_settings_new ("org.gnome.gedit.preferences.encodings");
-
        menu->priv->store = gtk_list_store_new (N_COLUMNS,
                                                G_TYPE_STRING,
                                                G_TYPE_POINTER,
diff --git a/gedit/gedit-file-chooser-dialog-gtk.c b/gedit/gedit-file-chooser-dialog-gtk.c
new file mode 100644
index 0000000..2409f87
--- /dev/null
+++ b/gedit/gedit-file-chooser-dialog-gtk.c
@@ -0,0 +1,620 @@
+/*
+ * gedit-file-chooser-dialog-gtk.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005-2007 - Paolo Maggi
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* TODO: Override set_extra_widget */
+/* TODO: add encoding property */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "gedit-file-chooser-dialog-gtk.h"
+#include "gedit-encodings-combo-box.h"
+#include "gedit-debug.h"
+#include "gedit-enum-types.h"
+#include "gedit-settings.h"
+
+#define ALL_FILES              _("All Files")
+#define ALL_TEXT_FILES         _("All Text Files")
+
+struct _GeditFileChooserDialogGtkPrivate
+{
+       GSettings *filter_settings;
+
+       GtkWidget *option_menu;
+       GtkWidget *extra_widget;
+
+       GtkWidget *newline_label;
+       GtkWidget *newline_combo;
+       GtkListStore *newline_store;
+};
+
+static void gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED (GeditFileChooserDialogGtk,
+                        gedit_file_chooser_dialog_gtk,
+                        GTK_TYPE_FILE_CHOOSER_DIALOG,
+                        0,
+                        G_IMPLEMENT_INTERFACE (GEDIT_TYPE_FILE_CHOOSER_DIALOG,
+                                               gedit_file_chooser_dialog_gtk_chooser_init)
+                        G_ADD_PRIVATE (GeditFileChooserDialogGtk))
+
+
+static void
+chooser_set_encoding (GeditFileChooserDialog  *dialog,
+                      const GtkSourceEncoding *encoding)
+{
+       GeditFileChooserDialogGtkPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_GTK (dialog)->priv;
+
+       g_return_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (priv->option_menu));
+
+       gedit_encodings_combo_box_set_selected_encoding (GEDIT_ENCODINGS_COMBO_BOX (priv->option_menu),
+                                                        encoding);
+}
+
+static const GtkSourceEncoding *
+chooser_get_encoding (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogGtkPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_GTK (dialog)->priv;
+
+       g_return_val_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (priv->option_menu), NULL);
+       g_return_val_if_fail ((gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_OPEN ||
+                              gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE), NULL);
+
+       return gedit_encodings_combo_box_get_selected_encoding (
+                               GEDIT_ENCODINGS_COMBO_BOX (priv->option_menu));
+}
+
+static void
+set_enum_combo (GtkComboBox *combo,
+                gint         value)
+{
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+
+       model = gtk_combo_box_get_model (combo);
+
+       if (!gtk_tree_model_get_iter_first (model, &iter))
+       {
+               return;
+       }
+
+       do
+       {
+               gint nt;
+
+               gtk_tree_model_get (model, &iter, 1, &nt, -1);
+
+               if (value == nt)
+               {
+                       gtk_combo_box_set_active_iter (combo, &iter);
+                       break;
+               }
+       } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+chooser_set_newline_type (GeditFileChooserDialog *dialog,
+                          GtkSourceNewlineType    newline_type)
+{
+       GeditFileChooserDialogGtkPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_GTK (dialog)->priv;
+
+       g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE);
+
+       set_enum_combo (GTK_COMBO_BOX (priv->newline_combo), newline_type);
+}
+
+static GtkSourceNewlineType
+chooser_get_newline_type (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogGtkPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_GTK (dialog)->priv;
+       GtkTreeIter iter;
+       GtkSourceNewlineType newline_type;
+
+       g_return_val_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE,
+                             GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
+
+       gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->newline_combo),
+                                      &iter);
+
+       gtk_tree_model_get (GTK_TREE_MODEL (priv->newline_store),
+                           &iter,
+                           1,
+                           &newline_type,
+                           -1);
+
+       return newline_type;
+}
+
+static void
+chooser_set_current_folder (GeditFileChooserDialog *dialog,
+                            GFile                  *folder)
+{
+       gchar *uri = NULL;
+
+       if (folder != NULL)
+       {
+               uri = g_file_get_uri (folder);
+       }
+
+       gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri);
+       g_free (uri);
+}
+
+static void
+chooser_set_current_name (GeditFileChooserDialog *dialog,
+                          const gchar            *name)
+{
+       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), name);
+}
+
+static void
+chooser_set_file (GeditFileChooserDialog *dialog,
+                  GFile                  *file)
+{
+       gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), file, NULL);
+}
+
+static GFile *
+chooser_get_file (GeditFileChooserDialog *dialog)
+{
+       return gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+}
+
+
+static GSList *
+chooser_get_files (GeditFileChooserDialog *dialog)
+{
+       return gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog));
+}
+
+static void
+chooser_set_do_overwrite_confirmation (GeditFileChooserDialog *dialog,
+                                       gboolean                overwrite_confirmation)
+{
+       gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), overwrite_confirmation);
+}
+
+static void
+chooser_show (GeditFileChooserDialog *dialog)
+{
+       gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static void
+chooser_destroy (GeditFileChooserDialog *dialog)
+{
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+chooser_set_modal (GeditFileChooserDialog *dialog,
+                   gboolean is_modal)
+{
+       gtk_window_set_modal (GTK_WINDOW (dialog), is_modal);
+}
+
+static GtkWindow *
+chooser_get_window (GeditFileChooserDialog *dialog)
+{
+       return GTK_WINDOW (dialog);
+}
+
+static void
+gedit_file_chooser_dialog_gtk_chooser_init (gpointer g_iface,
+                                            gpointer iface_data)
+{
+       GeditFileChooserDialogInterface *iface = g_iface;
+
+       iface->set_encoding = chooser_set_encoding;
+       iface->get_encoding = chooser_get_encoding;
+
+       iface->set_newline_type = chooser_set_newline_type;
+       iface->get_newline_type = chooser_get_newline_type;
+
+       iface->set_current_folder = chooser_set_current_folder;
+       iface->set_current_name = chooser_set_current_name;
+       iface->set_file = chooser_set_file;
+       iface->get_file = chooser_get_file;
+       iface->get_files = chooser_get_files;
+       iface->set_do_overwrite_confirmation = chooser_set_do_overwrite_confirmation;
+       iface->show = chooser_show;
+       iface->destroy = chooser_destroy;
+       iface->set_modal = chooser_set_modal;
+       iface->get_window = chooser_get_window;
+}
+
+static void
+gedit_file_chooser_dialog_gtk_dispose (GObject *object)
+{
+       GeditFileChooserDialogGtk *dialog = GEDIT_FILE_CHOOSER_DIALOG_GTK (object);
+
+       g_clear_object (&dialog->priv->filter_settings);
+
+       G_OBJECT_CLASS (gedit_file_chooser_dialog_gtk_parent_class)->dispose (object);
+}
+
+static void
+gedit_file_chooser_dialog_gtk_class_init (GeditFileChooserDialogGtkClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = gedit_file_chooser_dialog_gtk_dispose;
+}
+
+static void
+create_option_menu (GeditFileChooserDialogGtk *dialog,
+                    GeditFileChooserFlags      flags)
+{
+       GtkWidget *label;
+       GtkWidget *menu;
+       gboolean save_mode;
+
+       label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
+       gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+       save_mode = (flags & GEDIT_FILE_CHOOSER_SAVE) != 0;
+       menu = gedit_encodings_combo_box_new (save_mode);
+
+       gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
+
+       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
+                           label,
+                           FALSE,
+                           TRUE,
+                           0);
+
+       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
+                           menu,
+                           TRUE,
+                           TRUE,
+                           0);
+
+       gtk_widget_show (label);
+       gtk_widget_show (menu);
+
+       dialog->priv->option_menu = menu;
+}
+
+static void
+newline_combo_append (GtkComboBox          *combo,
+                     GtkListStore         *store,
+                     GtkTreeIter          *iter,
+                     const gchar          *label,
+                     GtkSourceNewlineType  newline_type)
+{
+       gtk_list_store_append (store, iter);
+       gtk_list_store_set (store, iter, 0, label, 1, newline_type, -1);
+
+       if (newline_type == GTK_SOURCE_NEWLINE_TYPE_DEFAULT)
+       {
+               gtk_combo_box_set_active_iter (combo, iter);
+       }
+}
+
+static void
+create_newline_combo (GeditFileChooserDialogGtk *dialog)
+{
+       GtkWidget *label, *combo;
+       GtkListStore *store;
+       GtkCellRenderer *renderer;
+       GtkTreeIter iter;
+
+       label = gtk_label_new_with_mnemonic (_("L_ine Ending:"));
+       gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+       store = gtk_list_store_new (2, G_TYPE_STRING, GTK_SOURCE_TYPE_NEWLINE_TYPE);
+       combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+       renderer = gtk_cell_renderer_text_new ();
+
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo),
+                                   renderer,
+                                   TRUE);
+
+       gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo),
+                                      renderer,
+                                      "text",
+                                      0);
+
+       newline_combo_append (GTK_COMBO_BOX (combo),
+                             store,
+                             &iter,
+                             _("Unix/Linux"),
+                             GTK_SOURCE_NEWLINE_TYPE_LF);
+
+       newline_combo_append (GTK_COMBO_BOX (combo),
+                             store,
+                             &iter,
+                             _("Mac OS Classic"),
+                             GTK_SOURCE_NEWLINE_TYPE_CR);
+
+       newline_combo_append (GTK_COMBO_BOX (combo),
+                             store,
+                             &iter,
+                             _("Windows"),
+                             GTK_SOURCE_NEWLINE_TYPE_CR_LF);
+
+       gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+
+       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
+                           label,
+                           FALSE,
+                           TRUE,
+                           0);
+
+       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
+                           combo,
+                           TRUE,
+                           TRUE,
+                           0);
+
+       dialog->priv->newline_combo = combo;
+       dialog->priv->newline_label = label;
+       dialog->priv->newline_store = store;
+}
+
+static void
+create_extra_widget (GeditFileChooserDialogGtk *dialog,
+                     GeditFileChooserFlags      flags)
+{
+       gboolean needs_encoding;
+       gboolean needs_line_ending;
+
+       needs_encoding = (flags & GEDIT_FILE_CHOOSER_ENABLE_ENCODING) != 0;
+       needs_line_ending = (flags & GEDIT_FILE_CHOOSER_ENABLE_LINE_ENDING) != 0;
+
+       if (!needs_encoding && !needs_line_ending)
+       {
+               return;
+       }
+
+       dialog->priv->extra_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+       gtk_widget_show (dialog->priv->extra_widget);
+
+       if (needs_encoding)
+       {
+               create_option_menu (dialog, flags);
+       }
+
+       if (needs_line_ending)
+       {
+               create_newline_combo (dialog);
+       }
+
+       gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
+                                          dialog->priv->extra_widget);
+}
+
+static void
+filter_changed (GeditFileChooserDialogGtk *dialog,
+               GParamSpec             *pspec,
+               gpointer                data)
+{
+       GtkFileFilter *filter;
+
+       filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
+       if (filter != NULL)
+       {
+               const gchar *name;
+               gint id = 0;
+
+               name = gtk_file_filter_get_name (filter);
+               g_return_if_fail (name != NULL);
+
+               if (strcmp (name, ALL_TEXT_FILES) == 0)
+                       id = 1;
+
+               gedit_debug_message (DEBUG_COMMANDS, "Active filter: %s (%d)", name, id);
+
+               g_settings_set_int (dialog->priv->filter_settings,
+                                   GEDIT_SETTINGS_ACTIVE_FILE_FILTER, id);
+       }
+}
+
+/* FIXME: use globs too - Paolo (Aug. 27, 2007) */
+static gboolean
+all_text_files_filter (const GtkFileFilterInfo *filter_info,
+                      gpointer                 data)
+{
+       static GSList *known_mime_types = NULL;
+       GSList *mime_types;
+
+       if (known_mime_types == NULL)
+       {
+               GtkSourceLanguageManager *lm;
+               const gchar * const *languages;
+
+               lm = gtk_source_language_manager_get_default ();
+               languages = gtk_source_language_manager_get_language_ids (lm);
+
+               while ((languages != NULL) && (*languages != NULL))
+               {
+                       gchar **mime_types;
+                       gint i;
+                       GtkSourceLanguage *lang;
+
+                       lang = gtk_source_language_manager_get_language (lm, *languages);
+                       g_return_val_if_fail (GTK_SOURCE_IS_LANGUAGE (lang), FALSE);
+                       ++languages;
+
+                       mime_types = gtk_source_language_get_mime_types (lang);
+                       if (mime_types == NULL)
+                               continue;
+
+                       for (i = 0; mime_types[i] != NULL; i++)
+                       {
+                               if (!g_content_type_is_a (mime_types[i], "text/plain"))
+                               {
+                                       gedit_debug_message (DEBUG_COMMANDS,
+                                                            "Mime-type %s is not related to text/plain",
+                                                            mime_types[i]);
+
+                                       known_mime_types = g_slist_prepend (known_mime_types,
+                                                                           g_strdup (mime_types[i]));
+                               }
+                       }
+
+                       g_strfreev (mime_types);
+               }
+
+               /* known_mime_types always has "text/plain" as first item" */
+               known_mime_types = g_slist_prepend (known_mime_types, g_strdup ("text/plain"));
+       }
+
+       /* known mime_types contains "text/plain" and then the list of mime-types unrelated to "text/plain"
+        * that gedit recognizes */
+
+       if (filter_info->mime_type == NULL)
+               return FALSE;
+
+       /*
+        * The filter is matching:
+        * - the mime-types beginning with "text/"
+        * - the mime-types inheriting from a known mime-type (note the text/plain is
+        *   the first known mime-type)
+        */
+
+       if (strncmp (filter_info->mime_type, "text/", 5) == 0)
+               return TRUE;
+
+       mime_types = known_mime_types;
+       while (mime_types != NULL)
+       {
+               if (g_content_type_is_a (filter_info->mime_type, (const gchar*)mime_types->data))
+                       return TRUE;
+
+               mime_types = g_slist_next (mime_types);
+       }
+
+       return FALSE;
+}
+
+static void
+gedit_file_chooser_dialog_gtk_init (GeditFileChooserDialogGtk *dialog)
+{
+       dialog->priv = gedit_file_chooser_dialog_gtk_get_instance_private (dialog);
+
+       dialog->priv->filter_settings = g_settings_new ("org.gnome.gedit.state.file-filter");
+}
+
+GeditFileChooserDialog *
+gedit_file_chooser_dialog_gtk_create (const gchar             *title,
+                                     GtkWindow               *parent,
+                                     GeditFileChooserFlags    flags,
+                                     const GtkSourceEncoding *encoding)
+{
+       GtkWidget *result;
+       GtkFileFilter *filter;
+       gint active_filter;
+       GtkFileChooserAction action;
+       gboolean select_multiple;
+
+       if ((flags & GEDIT_FILE_CHOOSER_SAVE) != 0)
+       {
+               action = GTK_FILE_CHOOSER_ACTION_SAVE;
+               select_multiple = FALSE;
+       }
+       else
+       {
+               action = GTK_FILE_CHOOSER_ACTION_OPEN;
+               select_multiple = TRUE;
+       }
+
+       result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK,
+                              "title", title,
+                              "local-only", FALSE,
+                              "action", action,
+                              "select-multiple", select_multiple,
+                              NULL);
+
+       create_extra_widget (GEDIT_FILE_CHOOSER_DIALOG_GTK (result), flags);
+
+       if (encoding != NULL)
+       {
+               gedit_encodings_combo_box_set_selected_encoding (
+                               GEDIT_ENCODINGS_COMBO_BOX (GEDIT_FILE_CHOOSER_DIALOG_GTK 
(result)->priv->option_menu),
+                               encoding);
+       }
+
+       active_filter = g_settings_get_int (GEDIT_FILE_CHOOSER_DIALOG_GTK (result)->priv->filter_settings,
+                                           GEDIT_SETTINGS_ACTIVE_FILE_FILTER);
+       gedit_debug_message (DEBUG_COMMANDS, "Active filter: %d", active_filter);
+
+       /* Filters */
+       filter = gtk_file_filter_new ();
+
+       gtk_file_filter_set_name (filter, ALL_FILES);
+       gtk_file_filter_add_pattern (filter, "*");
+       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
+
+       if (active_filter != 1)
+       {
+               /* Make this filter the default */
+               gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
+       }
+
+       filter = gtk_file_filter_new ();
+       gtk_file_filter_set_name (filter, ALL_TEXT_FILES);
+       gtk_file_filter_add_custom (filter,
+                                   GTK_FILE_FILTER_MIME_TYPE,
+                                   all_text_files_filter,
+                                   NULL,
+                                   NULL);
+       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
+
+       if (active_filter == 1)
+       {
+               /* Make this filter the default */
+               gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
+       }
+
+       g_signal_connect (result,
+                         "notify::filter",
+                         G_CALLBACK (filter_changed),
+                         NULL);
+
+       if (parent != NULL)
+       {
+               gtk_window_set_transient_for (GTK_WINDOW (result), parent);
+               gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE);
+       }
+
+       gtk_dialog_add_button (GTK_DIALOG (result), _("_Cancel"), GTK_RESPONSE_CANCEL);
+
+       if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+               gtk_dialog_add_button (GTK_DIALOG (result), _("_Save"), GTK_RESPONSE_OK);
+       }
+       else
+       {
+               gtk_dialog_add_button (GTK_DIALOG (result), _("_Open"), GTK_RESPONSE_OK);
+       }
+
+       gtk_dialog_set_default_response (GTK_DIALOG (result), GTK_RESPONSE_OK);
+       return GEDIT_FILE_CHOOSER_DIALOG (result);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog-gtk.h b/gedit/gedit-file-chooser-dialog-gtk.h
new file mode 100644
index 0000000..f2e5da6
--- /dev/null
+++ b/gedit/gedit-file-chooser-dialog-gtk.h
@@ -0,0 +1,64 @@
+/*
+ * gedit-file-chooser-dialog-gtk.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_FILE_CHOOSER_DIALOG_GTK_H__
+#define __GEDIT_FILE_CHOOSER_DIALOG_GTK_H__
+
+#include <gtk/gtk.h>
+#include "gedit-file-chooser-dialog.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK             (gedit_file_chooser_dialog_gtk_get_type ())
+#define GEDIT_FILE_CHOOSER_DIALOG_GTK(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK, GeditFileChooserDialogGtk))
+#define GEDIT_FILE_CHOOSER_DIALOG_GTK_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK, GeditFileChooserDialogGtkClass))
+#define GEDIT_IS_FILE_CHOOSER_DIALOG_GTK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK))
+#define GEDIT_IS_FILE_CHOOSER_DIALOG_GTK_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK))
+#define GEDIT_FILE_CHOOSER_DIALOG_GTK_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_GTK, GeditFileChooserDialogGtkClass))
+
+typedef struct _GeditFileChooserDialogGtk              GeditFileChooserDialogGtk;
+typedef struct _GeditFileChooserDialogGtkClass         GeditFileChooserDialogGtkClass;
+typedef struct _GeditFileChooserDialogGtkPrivate       GeditFileChooserDialogGtkPrivate;
+
+struct _GeditFileChooserDialogGtkClass
+{
+       GtkFileChooserDialogClass parent_class;
+};
+
+struct _GeditFileChooserDialogGtk
+{
+       GtkFileChooserDialog parent_instance;
+
+       GeditFileChooserDialogGtkPrivate *priv;
+};
+
+GType                   gedit_file_chooser_dialog_gtk_get_type         (void) G_GNUC_CONST;
+
+GeditFileChooserDialog *gedit_file_chooser_dialog_gtk_create           (const gchar             *title,
+                                                                        GtkWindow               *parent,
+                                                                        GeditFileChooserFlags    flags,
+                                                                        const GtkSourceEncoding *encoding);
+
+G_END_DECLS
+
+#endif /* __GEDIT_FILE_CHOOSER_DIALOG_GTK_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog-osx.c b/gedit/gedit-file-chooser-dialog-osx.c
new file mode 100644
index 0000000..f383a67
--- /dev/null
+++ b/gedit/gedit-file-chooser-dialog-osx.c
@@ -0,0 +1,879 @@
+/*
+ * gedit-file-chooser-dialog-osx.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#import <Cocoa/Cocoa.h>
+#include <gdk/gdkquartz.h>
+#include <glib/gi18n.h>
+
+#include "gedit-file-chooser-dialog-osx.h"
+#include "gedit-encoding-items.h"
+#include "gedit-encodings-dialog.h"
+
+struct _GeditFileChooserDialogOSXPrivate
+{
+       /* Note this can be either an NSSavePanel or NSOpenPanel,
+        * and NSOpenPanel inherits from NSSavePanel. */
+       NSSavePanel *panel;
+       GtkWindow *parent;
+       NSPopUpButton *newline_button;
+       NSPopUpButton *encoding_button;
+
+       gboolean is_open;
+       gboolean is_modal;
+
+       GeditFileChooserFlags flags;
+};
+
+static void gedit_file_chooser_dialog_osx_chooser_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED (GeditFileChooserDialogOSX,
+                        gedit_file_chooser_dialog_osx,
+                        G_TYPE_OBJECT,
+                        0,
+                        G_IMPLEMENT_INTERFACE (GEDIT_TYPE_FILE_CHOOSER_DIALOG,
+                                               gedit_file_chooser_dialog_osx_chooser_init)
+                        G_ADD_PRIVATE (GeditFileChooserDialogOSX))
+
+ interface NewlineItem : NSMenuItem
+
+ property (readonly) GtkSourceNewlineType newline_type;
+
+-(id)initWithType:(GtkSourceNewlineType)type;
+
+ end
+
+ implementation NewlineItem
+-(id)initWithType:(GtkSourceNewlineType)type
+{
+       NSString *title;
+
+       switch (type)
+       {
+       case GTK_SOURCE_NEWLINE_TYPE_LF:
+               title = [NSString stringWithUTF8String:_("Unix/Linux")];
+               break;
+       case GTK_SOURCE_NEWLINE_TYPE_CR:
+               title = [NSString stringWithUTF8String:_("Mac OS Classic")];
+               break;
+       case GTK_SOURCE_NEWLINE_TYPE_CR_LF:
+               title = [NSString stringWithUTF8String:_("Windows")];
+               break;
+       }
+
+       self = [super initWithTitle:title action:nil keyEquivalent:@""];
+
+       if (self)
+       {
+               _newline_type = type;
+       }
+
+       return self;
+}
+ end
+
+ interface EncodingItem : NSMenuItem
+
+ property (readonly) GeditEncodingItem *encoding;
+
+-(id)initWithEncoding:(GeditEncodingItem *)encoding;
+
+-(void)dealloc;
+-(const GtkSourceEncoding *)source_encoding;
+
+ end
+
+ implementation EncodingItem
+-(id)initWithEncoding:(GeditEncodingItem *)encoding
+{
+       NSString *title;
+
+       title = [NSString stringWithUTF8String:gedit_encoding_item_get_name (encoding)];
+
+       self = [super initWithTitle:title action:nil keyEquivalent:@""];
+
+       if (self)
+       {
+               _encoding = encoding;
+       }
+
+       return self;
+}
+
+-(void)dealloc
+{
+       gedit_encoding_item_free (_encoding);
+       _encoding = NULL;
+
+       [super dealloc];
+}
+
+-(const GtkSourceEncoding *)source_encoding
+{
+       if (_encoding != NULL)
+       {
+               return gedit_encoding_item_get_encoding (_encoding);
+       }
+
+       return NULL;
+}
+
+ end
+
+static void
+chooser_set_encoding (GeditFileChooserDialog  *dialog,
+                      const GtkSourceEncoding *encoding)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+       gint i;
+
+       if (priv->encoding_button == NULL)
+       {
+               return;
+       }
+
+       NSMenu *menu = [priv->encoding_button menu];
+       NSArray *items = [menu itemArray];
+
+       for (i = 0; i < [items count]; i++)
+       {
+               NSMenuItem *item = [items objectAtIndex:i];
+
+               if ([item isKindOfClass:[EncodingItem class]])
+               {
+                       EncodingItem *eitem = (EncodingItem *)item;
+
+                       if ([eitem source_encoding] == encoding)
+                       {
+                               [priv->encoding_button selectItemAtIndex:i];
+                               break;
+                       }
+               }
+       }
+}
+
+static const GtkSourceEncoding *
+chooser_get_encoding (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+       NSMenuItem *item;
+
+       if (priv->encoding_button == NULL)
+       {
+               return gtk_source_encoding_get_utf8 ();
+       }
+
+       item = [priv->encoding_button selectedItem];
+
+       if (item != nil && [item isKindOfClass:[EncodingItem class]])
+       {
+               return [(EncodingItem *)item source_encoding];
+       }
+
+       return NULL;
+}
+
+static void
+chooser_set_newline_type (GeditFileChooserDialog *dialog,
+                          GtkSourceNewlineType    newline_type)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+       gint i;
+
+       if (priv->newline_button == NULL)
+       {
+               return;
+       }
+
+       NSMenu *menu = [priv->newline_button menu];
+       NSArray *items = [menu itemArray];
+
+       for (i = 0; i < [items count]; i++)
+       {
+               NewlineItem *item = (NewlineItem *)[items objectAtIndex:i];
+
+               if (item.newline_type == newline_type)
+               {
+                       [priv->newline_button selectItemAtIndex:i];
+                       break;
+               }
+       }
+}
+
+static GtkSourceNewlineType
+chooser_get_newline_type (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       if (priv->newline_button == NULL)
+       {
+               return GTK_SOURCE_NEWLINE_TYPE_DEFAULT;
+       }
+
+       NewlineItem *item = (NewlineItem *)[priv->newline_button selectedItem];
+       return item.newline_type;
+}
+
+static void
+chooser_set_current_folder (GeditFileChooserDialog *dialog,
+                            GFile                  *folder)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       if (folder != NULL)
+       {
+               gchar *uri;
+
+               uri = g_file_get_uri (folder);
+               [priv->panel setDirectoryURL:[NSURL URLWithString:[NSString stringWithUTF8String:uri]]];
+               g_free (uri);
+       }
+}
+
+static void
+chooser_set_current_name (GeditFileChooserDialog *dialog,
+                          const gchar            *name)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       [priv->panel setNameFieldStringValue:[NSString stringWithUTF8String:name]];
+}
+
+static void
+chooser_set_file (GeditFileChooserDialog *dialog,
+                  GFile                  *file)
+{
+       GFile *folder;
+       gchar *name;
+
+       if (file == NULL)
+       {
+               return;
+       }
+
+       folder = g_file_get_parent (file);
+       name = g_file_get_basename (file);
+
+       chooser_set_current_folder (dialog, folder);
+       chooser_set_current_name (dialog, name);
+
+       g_object_unref (folder);
+       g_free (name);
+}
+
+static GSList *chooser_get_files (GeditFileChooserDialog *dialog);
+
+static GFile *
+ns_url_to_g_file (NSURL *url)
+{
+       if (url == nil)
+       {
+               return NULL;
+       }
+
+       return g_file_new_for_uri ([[url absoluteString] UTF8String]);
+}
+
+static GFile *
+chooser_get_file (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       if (priv->is_open)
+       {
+               GSList *ret;
+               GFile *file = NULL;
+
+               ret = chooser_get_files (dialog);
+
+               if (ret != NULL)
+               {
+                       file = ret->data;
+                       ret = g_slist_delete_link (ret, ret);
+               }
+
+               g_slist_free_full (ret, (GDestroyNotify)g_object_unref);
+               return file;
+       }
+       else
+       {
+               return ns_url_to_g_file ([priv->panel URL]);
+       }
+}
+
+
+static GSList *
+chooser_get_files (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       GSList *ret = NULL;
+
+       if (priv->is_open)
+       {
+               NSArray *urls;
+               gint i;
+
+               urls = [(NSOpenPanel *)priv->panel URLs];
+
+               for (i = 0; i < [urls count]; i++)
+               {
+                       NSURL *url;
+
+                       url = (NSURL *)[urls objectAtIndex:i];
+                       ret = g_slist_prepend (ret, ns_url_to_g_file (url));
+               }
+       }
+       else
+       {
+               GFile *file;
+
+               file = chooser_get_file (dialog);
+
+               if (file != NULL)
+               {
+                       ret = g_slist_prepend (ret, file);
+               }
+       }
+
+       return g_slist_reverse (ret);
+}
+
+static void
+chooser_set_do_overwrite_confirmation (GeditFileChooserDialog *dialog,
+                                       gboolean                overwrite_confirmation)
+{
+       // TODO: this is only implementable on OS X through hacks
+       // I guess it's better just not having it
+}
+
+static void
+fill_encodings (GeditFileChooserDialogOSX *dialog)
+{
+       NSPopUpButton *button;
+       GSList *encodings;
+       NSMenu *menu;
+       gint i = 0;
+       gint first = 0;
+       const GtkSourceEncoding *encoding;
+
+       encoding = gedit_file_chooser_dialog_get_encoding (GEDIT_FILE_CHOOSER_DIALOG (dialog));
+
+       button = dialog->priv->encoding_button;
+       menu = [button menu];
+
+       while (i < [menu numberOfItems])
+       {
+               NSMenuItem *item = [menu itemAtIndex:i];
+
+               if ([item isKindOfClass:[EncodingItem class]])
+               {
+                       EncodingItem *eitem = (EncodingItem *)item;
+
+                       if ([eitem source_encoding] != NULL)
+                       {
+                               if (first == 0)
+                               {
+                                       first = i;
+                               }
+
+                               [menu removeItemAtIndex:i];
+                       }
+                       else
+                       {
+                               i++;
+                       }
+               }
+               else
+               {
+                       i++;
+
+                       if ((dialog->priv->flags & GEDIT_FILE_CHOOSER_OPEN) != 0 && first == 0)
+                       {
+                               first = i;
+                       }
+               }
+       }
+
+       encodings = gedit_encoding_items_get ();
+
+       while (encodings)
+       {
+               GeditEncodingItem *item = encodings->data;
+
+               [menu insertItem:[[EncodingItem alloc] initWithEncoding:item] atIndex:first];
+
+               if (encoding == gedit_encoding_item_get_encoding (item))
+               {
+                       [button selectItemAtIndex:first];
+               }
+
+               first++;
+               encodings = g_slist_delete_link (encodings, encodings);
+       }
+
+       if (encoding == NULL)
+       {
+               [button selectItemAtIndex:0];
+       }
+}
+
+static void
+dialog_response_cb (GtkDialog                 *dialog,
+                    gint                       response_id,
+                    GeditFileChooserDialogOSX *chooser_dialog)
+{
+       if (response_id == GTK_RESPONSE_OK)
+       {
+               fill_encodings (chooser_dialog);
+       }
+
+       if (response_id != GTK_RESPONSE_HELP)
+       {
+               [chooser_dialog->priv->panel setAlphaValue:1.0f];
+               gtk_widget_destroy (GTK_WIDGET (dialog));
+       }
+}
+
+ interface ConfigureEncodings : NSObject {
+       GeditFileChooserDialogOSX *_dialog;
+       const GtkSourceEncoding *_current;
+}
+
+-(id)initWithDialog:(GeditFileChooserDialogOSX *)dialog;
+
+-(void)activateConfigure:(id)sender;
+-(void)selectionChanged:(id)sender;
+
+ end
+
+ implementation ConfigureEncodings
+
+-(id)initWithDialog:(GeditFileChooserDialogOSX *)dialog
+{
+       self = [super init];
+
+       if (self)
+       {
+               _dialog = dialog;
+       }
+
+       return self;
+}
+
+-(void)activateConfigure:(id)sender
+{
+       GtkWidget *dialog;
+
+       gedit_file_chooser_dialog_set_encoding (GEDIT_FILE_CHOOSER_DIALOG (_dialog),
+                                               _current);
+
+       dialog = gedit_encodings_dialog_new ();
+
+       if (_dialog->priv->parent != NULL)
+       {
+               GtkWindowGroup *wg;
+
+               gtk_window_set_transient_for (GTK_WINDOW (dialog),
+                                             _dialog->priv->parent);
+
+               if (gtk_window_has_group (_dialog->priv->parent))
+               {
+                       wg = gtk_window_get_group (_dialog->priv->parent);
+               }
+               else
+               {
+                       wg = gtk_window_group_new ();
+                       gtk_window_group_add_window (wg, _dialog->priv->parent);
+               }
+
+               gtk_window_group_add_window (wg, GTK_WINDOW (dialog));
+       }
+
+       gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+       g_signal_connect_after (dialog,
+                               "response",
+                               G_CALLBACK (dialog_response_cb),
+                               _dialog);
+
+       gtk_widget_show (dialog);
+
+       /* We set the alpha value to 0 here because it was the only way that we could
+          find to make the panel not receive any events. Ideally the encodings dialog
+          should be modal on top of the NSPanel, but the modal loops of gtk and NS
+          do not mix. This is an ugly hack, but at least we can't interact with the
+          NSPanel while showing the encodings dialog... */
+       [_dialog->priv->panel setAlphaValue:0.0f];
+}
+
+-(void)selectionChanged:(id)sender
+{
+       _current = gedit_file_chooser_dialog_get_encoding (GEDIT_FILE_CHOOSER_DIALOG (_dialog));
+}
+
+ end
+
+static gint
+create_encoding_combo (GeditFileChooserDialogOSX *dialog,
+                       NSView                    *container)
+{
+       NSTextField *label;
+       NSPopUpButton *button;
+       NSMenu *menu;
+       ConfigureEncodings *config;
+       NSMenuItem *citem;
+
+       label = [NSTextField new];
+
+       [label setTranslatesAutoresizingMaskIntoConstraints:NO];
+       [label setStringValue:[NSString stringWithUTF8String:_("Character Encoding:")]];
+       [label setDrawsBackground:NO];
+       [label setBordered:NO];
+       [label setBezeled:NO];
+       [label setSelectable:NO];
+       [label setEditable:NO];
+
+       [container addSubview:label];
+
+       button = [NSPopUpButton new];
+       [button setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+       menu = [button menu];
+
+       if ((dialog->priv->flags & GEDIT_FILE_CHOOSER_OPEN) != 0)
+       {
+               NSString *title;
+
+               title = [NSString stringWithUTF8String:_("Automatically Detected")];
+
+               [menu addItem:[[EncodingItem alloc] initWithTitle:title action:nil keyEquivalent:@""]];
+               [menu addItem:[NSMenuItem separatorItem]];
+       }
+
+       config = [[ConfigureEncodings alloc] initWithDialog:dialog];
+
+       [menu addItem:[NSMenuItem separatorItem]];
+       citem = [[EncodingItem alloc] initWithTitle:[NSString stringWithUTF8String:_("Add or Remove...")]
+                                            action:@selector(activateConfigure:)
+                                     keyEquivalent:@""];
+
+       [citem setTarget:config];
+       [menu addItem:citem];
+
+       [button setTarget:config];
+       [button setAction:@selector(selectionChanged:)];
+
+       [button synchronizeTitleAndSelectedItem];
+       [config selectionChanged:nil];
+
+       [container addSubview:button];
+
+       [container addConstraint:[NSLayoutConstraint constraintWithItem:button
+                                                             attribute:NSLayoutAttributeTop
+                                                             relatedBy:NSLayoutRelationEqual
+                                                                toItem:container
+                                                             attribute:NSLayoutAttributeTop
+                                                            multiplier:1
+                                                              constant:3]];
+
+       [container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[label]-[button]"
+                                                                         
options:NSLayoutFormatAlignAllBaseline
+                                                                         metrics:nil
+                                                                           
views:NSDictionaryOfVariableBindings(label, button)]];
+
+       dialog->priv->encoding_button = button;
+
+       fill_encodings (dialog);
+
+       return (gint)([button intrinsicContentSize].width + [label intrinsicContentSize].width);
+}
+
+static gint
+create_newline_combo (GeditFileChooserDialogOSX *dialog,
+                      NSView                    *container)
+{
+       NSTextField *label;
+       NSMenu *menu;
+       NSPopUpButton *button;
+
+       label = [NSTextField new];
+
+       [label setTranslatesAutoresizingMaskIntoConstraints:NO];
+       [label setStringValue:[NSString stringWithUTF8String:_("Line Ending:")]];
+       [label setDrawsBackground:NO];
+       [label setBordered:NO];
+       [label setBezeled:NO];
+       [label setSelectable:NO];
+       [label setEditable:NO];
+
+       [container addSubview:label];
+
+       button = [NSPopUpButton new];
+
+       [button setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+       menu = [button menu];
+
+       [menu addItem:[[NewlineItem alloc] initWithType:GTK_SOURCE_NEWLINE_TYPE_LF]];
+       [menu addItem:[[NewlineItem alloc] initWithType:GTK_SOURCE_NEWLINE_TYPE_CR]];
+       [menu addItem:[[NewlineItem alloc] initWithType:GTK_SOURCE_NEWLINE_TYPE_CR_LF]];
+
+       [button synchronizeTitleAndSelectedItem];
+
+       [container addSubview:button];
+
+       [container addConstraint:[NSLayoutConstraint constraintWithItem:button
+                                                             attribute:NSLayoutAttributeTop
+                                                             relatedBy:NSLayoutRelationEqual
+                                                                toItem:container
+                                                             attribute:NSLayoutAttributeTop
+                                                            multiplier:1
+                                                              constant:3]];
+
+       [container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[label]-[button]-|"
+                                                                         
options:NSLayoutFormatAlignAllBaseline
+                                                                         metrics:nil
+                                                                           
views:NSDictionaryOfVariableBindings(label, button)]];
+
+       dialog->priv->newline_button = button;
+
+       return (gint)([button intrinsicContentSize].width + [label intrinsicContentSize].width);
+}
+
+static void
+create_extra_widget (GeditFileChooserDialogOSX *dialog)
+{
+       gboolean needs_encoding;
+       gboolean needs_line_ending;
+       GeditFileChooserFlags flags;
+       NSSize size;
+       NSView *parent;
+       NSView *container;
+       gint minw = 0;
+
+       flags = dialog->priv->flags;
+
+       needs_encoding = (flags & GEDIT_FILE_CHOOSER_ENABLE_ENCODING) != 0;
+       needs_line_ending = (flags & GEDIT_FILE_CHOOSER_ENABLE_LINE_ENDING) != 0;
+
+       if (!needs_encoding && !needs_line_ending)
+       {
+               return;
+       }
+
+       container = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 400, 30)];
+
+       if (needs_encoding)
+       {
+               minw += create_encoding_combo (dialog, container);
+       }
+
+       if (needs_line_ending)
+       {
+               minw += create_newline_combo (dialog, container);
+       }
+
+       minw += 90;
+
+       [container setFrame:NSMakeRect(0, 0, minw, 30)];
+
+       [dialog->priv->panel setAccessoryView:container];
+
+       parent = [[container superview] superview];
+
+       if ([parent isKindOfClass:[NSBox class]])
+       {
+               NSBox *box = (NSBox *)parent;
+               [box setTransparent:YES];
+       }
+
+       size = [[container superview] frame].size;
+       size.width = minw;
+
+       [container setFrame:NSMakeRect(0, 0, size.width, size.height)];
+       [dialog->priv->panel setContentMinSize:size];
+}
+
+static void
+chooser_show (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       // Keep alive for the handler
+       g_object_ref (dialog);
+
+       void (^handler)(NSInteger ret) = ^(NSInteger result) {
+               GtkResponseType response;
+
+               if (result == NSFileHandlingPanelOKButton)
+               {
+                       response = GTK_RESPONSE_OK;
+               }
+               else
+               {
+                       response = GTK_RESPONSE_CANCEL;
+               }
+
+               g_signal_emit_by_name (dialog, "response", response);
+               g_object_unref (dialog);
+       };
+
+       if (priv->parent != NULL && priv->is_modal)
+       {
+               GdkWindow *win;
+               NSWindow *nswin;
+
+               win = gtk_widget_get_window (GTK_WIDGET (priv->parent));
+               nswin = gdk_quartz_window_get_nswindow (win);
+
+               [priv->panel setLevel:NSModalPanelWindowLevel];
+
+               [priv->panel beginSheetModalForWindow:nswin completionHandler:handler];
+       }
+       else
+       {
+               [priv->panel setLevel:NSModalPanelWindowLevel];
+               [priv->panel beginWithCompletionHandler:handler];
+       }
+}
+
+static void
+chooser_destroy (GeditFileChooserDialog *dialog)
+{
+       g_object_unref (dialog);
+}
+
+static void
+chooser_set_modal (GeditFileChooserDialog *dialog,
+                   gboolean is_modal)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (dialog)->priv;
+
+       priv->is_modal = is_modal;
+}
+
+static void
+gedit_file_chooser_dialog_osx_chooser_init (gpointer g_iface,
+                                            gpointer iface_data)
+{
+       GeditFileChooserDialogInterface *iface = g_iface;
+
+       iface->set_encoding = chooser_set_encoding;
+       iface->get_encoding = chooser_get_encoding;
+
+       iface->set_newline_type = chooser_set_newline_type;
+       iface->get_newline_type = chooser_get_newline_type;
+
+       iface->set_current_folder = chooser_set_current_folder;
+       iface->set_current_name = chooser_set_current_name;
+       iface->set_file = chooser_set_file;
+       iface->get_file = chooser_get_file;
+       iface->get_files = chooser_get_files;
+       iface->set_do_overwrite_confirmation = chooser_set_do_overwrite_confirmation;
+       iface->show = chooser_show;
+       iface->destroy = chooser_destroy;
+       iface->set_modal = chooser_set_modal;
+}
+
+static void
+gedit_file_chooser_dialog_osx_dispose (GObject *object)
+{
+       GeditFileChooserDialogOSXPrivate *priv = GEDIT_FILE_CHOOSER_DIALOG_OSX (object)->priv;
+
+       if (priv->panel != NULL)
+       {
+               [priv->panel release];
+               priv->panel = NULL;
+       }
+
+       if (G_OBJECT_CLASS (gedit_file_chooser_dialog_osx_parent_class)->dispose != NULL)
+       {
+               G_OBJECT_CLASS (gedit_file_chooser_dialog_osx_parent_class)->dispose (object);
+       }
+}
+
+static void
+gedit_file_chooser_dialog_osx_class_init (GeditFileChooserDialogOSXClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = gedit_file_chooser_dialog_osx_dispose;
+}
+
+static void
+gedit_file_chooser_dialog_osx_init (GeditFileChooserDialogOSX *dialog)
+{
+       dialog->priv = gedit_file_chooser_dialog_osx_get_instance_private (dialog);
+}
+
+ protocol CanSetShowsTagField
+- (void)setShowsTagField:(BOOL)val;
+ end
+
+GeditFileChooserDialog *
+gedit_file_chooser_dialog_osx_create (const gchar             *title,
+                                     GtkWindow               *parent,
+                                     GeditFileChooserFlags    flags,
+                                     const GtkSourceEncoding *encoding)
+{
+       GeditFileChooserDialogOSX *ret;
+
+       ret = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX, NULL);
+
+       if ((flags & GEDIT_FILE_CHOOSER_SAVE) != 0)
+       {
+               NSSavePanel *panel = [[NSSavePanel savePanel] retain];
+
+               if ([panel respondsToSelector:@selector(setShowsTagField:)])
+               {
+                       [(id<CanSetShowsTagField>)panel setShowsTagField:NO];
+               }
+
+               ret->priv->panel = panel;
+               ret->priv->is_open = FALSE;
+       }
+       else
+       {
+               NSOpenPanel *panel = [[NSOpenPanel openPanel] retain];
+
+               [panel setAllowsMultipleSelection:YES];
+               [panel setCanChooseDirectories:NO];
+
+               ret->priv->panel = panel;
+               ret->priv->is_open = TRUE;
+       }
+
+       if (parent != NULL)
+       {
+               ret->priv->parent = g_object_ref (parent);
+       }
+
+       ret->priv->flags = flags;
+       create_extra_widget (ret);
+
+       [ret->priv->panel setTitle:[NSString stringWithUTF8String:title]];
+       return GEDIT_FILE_CHOOSER_DIALOG (ret);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog-osx.h b/gedit/gedit-file-chooser-dialog-osx.h
new file mode 100644
index 0000000..6192287
--- /dev/null
+++ b/gedit/gedit-file-chooser-dialog-osx.h
@@ -0,0 +1,64 @@
+/*
+ * gedit-file-chooser-dialog-gtk.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ * Copyright (C) 2014 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_FILE_CHOOSER_DIALOG_OSX_H__
+#define __GEDIT_FILE_CHOOSER_DIALOG_OSX_H__
+
+#include <gtk/gtk.h>
+#include "gedit-file-chooser-dialog.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX             (gedit_file_chooser_dialog_osx_get_type ())
+#define GEDIT_FILE_CHOOSER_DIALOG_OSX(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX, GeditFileChooserDialogOSX))
+#define GEDIT_FILE_CHOOSER_DIALOG_OSX_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX, GeditFileChooserDialogOSXClass))
+#define GEDIT_IS_FILE_CHOOSER_DIALOG_OSX(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX))
+#define GEDIT_IS_FILE_CHOOSER_DIALOG_OSX_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX))
+#define GEDIT_FILE_CHOOSER_DIALOG_OSX_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG_OSX, GeditFileChooserDialogOSXClass))
+
+typedef struct _GeditFileChooserDialogOSX              GeditFileChooserDialogOSX;
+typedef struct _GeditFileChooserDialogOSXClass         GeditFileChooserDialogOSXClass;
+typedef struct _GeditFileChooserDialogOSXPrivate       GeditFileChooserDialogOSXPrivate;
+
+struct _GeditFileChooserDialogOSXClass
+{
+       GtkFileChooserDialogClass parent_class;
+};
+
+struct _GeditFileChooserDialogOSX
+{
+       GtkFileChooserDialog parent_instance;
+
+       GeditFileChooserDialogOSXPrivate *priv;
+};
+
+GType                   gedit_file_chooser_dialog_osx_get_type         (void) G_GNUC_CONST;
+
+GeditFileChooserDialog *gedit_file_chooser_dialog_osx_create           (const gchar              *title,
+                                                                        GtkWindow                *parent,
+                                                                        GeditFileChooserFlags     flags,
+                                                                        const GtkSourceEncoding  *encoding);
+
+G_END_DECLS
+
+#endif /* __GEDIT_FILE_CHOOSER_DIALOG_OSX_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog.c b/gedit/gedit-file-chooser-dialog.c
index 63fb285..f0f01c2 100644
--- a/gedit/gedit-file-chooser-dialog.c
+++ b/gedit/gedit-file-chooser-dialog.c
@@ -1,8 +1,8 @@
 /*
- * gedit-file-chooser-dialog.c
+ * gedit-app-file-chooser-dialog.h
  * This file is part of gedit
  *
- * Copyright (C) 2005-2007 - Paolo Maggi
+ * Copyright (C) 2014 Jesse van den Kieboom
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,550 +18,279 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* TODO: Override set_extra_widget */
-/* TODO: add encoding property */
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <string.h>
-
-#include <glib/gi18n.h>
-
 #include "gedit-file-chooser-dialog.h"
-#include "gedit-encodings-combo-box.h"
-#include "gedit-debug.h"
-#include "gedit-enum-types.h"
-#include "gedit-settings.h"
-
-#define ALL_FILES              _("All Files")
-#define ALL_TEXT_FILES         _("All Text Files")
-
-struct _GeditFileChooserDialogPrivate
-{
-       GSettings *filter_settings;
-
-       GtkWidget *option_menu;
-       GtkWidget *extra_widget;
 
-       GtkWidget *newline_label;
-       GtkWidget *newline_combo;
-       GtkListStore *newline_store;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GeditFileChooserDialog, gedit_file_chooser_dialog, GTK_TYPE_FILE_CHOOSER_DIALOG)
-
-static void
-gedit_file_chooser_dialog_dispose (GObject *object)
-{
-       GeditFileChooserDialog *dialog = GEDIT_FILE_CHOOSER_DIALOG (object);
-
-       g_clear_object (&dialog->priv->filter_settings);
-
-       G_OBJECT_CLASS (gedit_file_chooser_dialog_parent_class)->dispose (object);
-}
+#ifdef OS_OSX
+#include "gedit-file-chooser-dialog-osx.h"
+#else
+#include "gedit-file-chooser-dialog-gtk.h"
+#endif
 
-static void
-gedit_file_chooser_dialog_class_init (GeditFileChooserDialogClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+#include "gedit-marshal.h"
 
-       object_class->dispose = gedit_file_chooser_dialog_dispose;
-}
+G_DEFINE_INTERFACE (GeditFileChooserDialog, gedit_file_chooser_dialog, G_TYPE_OBJECT)
 
-static void
-create_option_menu (GeditFileChooserDialog *dialog)
+static gboolean
+confirm_overwrite_accumulator (GSignalInvocationHint *ihint,
+                               GValue                *return_accu,
+                               const GValue          *handler_return,
+                               gpointer               dummy)
 {
-       GtkWidget *label;
-       GtkWidget *menu;
-
-       label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
-
-       menu = gedit_encodings_combo_box_new (
-               gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
-
-       gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
-
-       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
-                           label,
-                           FALSE,
-                           TRUE,
-                           0);
+       gboolean continue_emission;
+       GtkFileChooserConfirmation conf;
 
-       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
-                           menu,
-                           TRUE,
-                           TRUE,
-                           0);
+       conf = g_value_get_enum (handler_return);
+       g_value_set_enum (return_accu, conf);
+       continue_emission = (conf == GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM);
 
-       gtk_widget_show (label);
-       gtk_widget_show (menu);
-
-       dialog->priv->option_menu = menu;
+       return continue_emission;
 }
 
-static void
-update_newline_visibility (GeditFileChooserDialog *dialog)
-{
-       gboolean visible = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE;
-
-       gtk_widget_set_visible (dialog->priv->newline_label, visible);
-       gtk_widget_set_visible (dialog->priv->newline_combo, visible);
-}
-
-static void
-newline_combo_append (GtkComboBox          *combo,
-                     GtkListStore         *store,
-                     GtkTreeIter          *iter,
-                     const gchar          *label,
-                     GtkSourceNewlineType  newline_type)
+void
+gedit_file_chooser_dialog_default_init (GeditFileChooserDialogInterface *iface)
 {
-       gtk_list_store_append (store, iter);
-       gtk_list_store_set (store, iter, 0, label, 1, newline_type, -1);
+       static gboolean initialized = FALSE;
 
-       if (newline_type == GTK_SOURCE_NEWLINE_TYPE_DEFAULT)
+       if (G_UNLIKELY (!initialized))
        {
-               gtk_combo_box_set_active_iter (combo, iter);
+               g_signal_new ("response",
+                             G_TYPE_FROM_INTERFACE (iface),
+                             G_SIGNAL_RUN_LAST,
+                             0, NULL, NULL,
+                             g_cclosure_marshal_VOID__INT,
+                             G_TYPE_NONE,
+                             1,
+                             G_TYPE_INT);
+
+               g_signal_new ("confirm-overwrite",
+                             G_TYPE_FROM_INTERFACE (iface),
+                             G_SIGNAL_RUN_LAST,
+                             0,
+                             confirm_overwrite_accumulator, NULL,
+                             gedit_marshal_ENUM__VOID,
+                             GTK_TYPE_FILE_CHOOSER_CONFIRMATION,
+                             0);
+
+               initialized = TRUE;
        }
 }
 
-static void
-create_newline_combo (GeditFileChooserDialog *dialog)
+GeditFileChooserDialog *
+gedit_file_chooser_dialog_create (const gchar              *title,
+                                  GtkWindow                *parent,
+                                  GeditFileChooserFlags    flags,
+                                  const GtkSourceEncoding *encoding)
 {
-       GtkWidget *label, *combo;
-       GtkListStore *store;
-       GtkCellRenderer *renderer;
-       GtkTreeIter iter;
-
-       label = gtk_label_new_with_mnemonic (_("L_ine Ending:"));
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
-
-       store = gtk_list_store_new (2, G_TYPE_STRING, GTK_SOURCE_TYPE_NEWLINE_TYPE);
-       combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
-       renderer = gtk_cell_renderer_text_new ();
-
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo),
-                                   renderer,
-                                   TRUE);
-
-       gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo),
-                                      renderer,
-                                      "text",
-                                      0);
-
-       newline_combo_append (GTK_COMBO_BOX (combo),
-                             store,
-                             &iter,
-                             _("Unix/Linux"),
-                             GTK_SOURCE_NEWLINE_TYPE_LF);
-
-       newline_combo_append (GTK_COMBO_BOX (combo),
-                             store,
-                             &iter,
-                             _("Mac OS Classic"),
-                             GTK_SOURCE_NEWLINE_TYPE_CR);
-
-       newline_combo_append (GTK_COMBO_BOX (combo),
-                             store,
-                             &iter,
-                             _("Windows"),
-                             GTK_SOURCE_NEWLINE_TYPE_CR_LF);
-
-       gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
-
-       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
-                           label,
-                           FALSE,
-                           TRUE,
-                           0);
-
-       gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
-                           combo,
-                           TRUE,
-                           TRUE,
-                           0);
-
-       dialog->priv->newline_combo = combo;
-       dialog->priv->newline_label = label;
-       dialog->priv->newline_store = store;
-
-       update_newline_visibility (dialog);
+#ifdef OS_OSX
+       return gedit_file_chooser_dialog_osx_create (title,
+                                                    parent,
+                                                    flags,
+                                                    encoding);
+#else
+       return gedit_file_chooser_dialog_gtk_create (title,
+                                                    parent,
+                                                    flags,
+                                                    encoding);
+#endif
 }
 
-static void
-create_extra_widget (GeditFileChooserDialog *dialog)
+void
+gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog  *dialog,
+                                        const GtkSourceEncoding *encoding)
 {
-       dialog->priv->extra_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+       GeditFileChooserDialogInterface *iface;
 
-       gtk_widget_show (dialog->priv->extra_widget);
-
-       create_option_menu (dialog);
-       create_newline_combo (dialog);
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-       gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
-                                          dialog->priv->extra_widget);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_encoding != NULL);
 
+       iface->set_encoding (dialog, encoding);
 }
 
-static void
-action_changed (GeditFileChooserDialog *dialog,
-               GParamSpec             *pspec,
-               gpointer                data)
+const GtkSourceEncoding *
+gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog)
 {
-       GtkFileChooserAction action;
+       GeditFileChooserDialogInterface *iface;
 
-       action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
+       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
-       switch (action)
-       {
-               case GTK_FILE_CHOOSER_ACTION_OPEN:
-                       g_object_set (dialog->priv->option_menu,
-                                     "save_mode", FALSE,
-                                     NULL);
-                       gtk_widget_show (dialog->priv->option_menu);
-                       break;
-               case GTK_FILE_CHOOSER_ACTION_SAVE:
-                       g_object_set (dialog->priv->option_menu,
-                                     "save_mode", TRUE,
-                                     NULL);
-                       gtk_widget_show (dialog->priv->option_menu);
-                       break;
-               default:
-                       gtk_widget_hide (dialog->priv->option_menu);
-       }
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_val_if_fail (iface->get_encoding != NULL, NULL);
 
-       update_newline_visibility (dialog);
+       return iface->get_encoding (dialog);
 }
 
-static void
-filter_changed (GeditFileChooserDialog *dialog,
-               GParamSpec             *pspec,
-               gpointer                data)
+void
+gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog *dialog,
+                                            GtkSourceNewlineType    newline_type)
 {
-       GtkFileFilter *filter;
-
-       filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
-       if (filter != NULL)
-       {
-               const gchar *name;
-               gint id = 0;
-
-               name = gtk_file_filter_get_name (filter);
-               g_return_if_fail (name != NULL);
+       GeditFileChooserDialogInterface *iface;
 
-               if (strcmp (name, ALL_TEXT_FILES) == 0)
-                       id = 1;
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-               gedit_debug_message (DEBUG_COMMANDS, "Active filter: %s (%d)", name, id);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_newline_type != NULL);
 
-               g_settings_set_int (dialog->priv->filter_settings,
-                                   GEDIT_SETTINGS_ACTIVE_FILE_FILTER, id);
-       }
+       iface->set_newline_type (dialog, newline_type);
 }
 
-/* FIXME: use globs too - Paolo (Aug. 27, 2007) */
-static gboolean
-all_text_files_filter (const GtkFileFilterInfo *filter_info,
-                      gpointer                 data)
+GtkSourceNewlineType
+gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog)
 {
-       static GSList *known_mime_types = NULL;
-       GSList *mime_types;
+       GeditFileChooserDialogInterface *iface;
 
-       if (known_mime_types == NULL)
-       {
-               GtkSourceLanguageManager *lm;
-               const gchar * const *languages;
-
-               lm = gtk_source_language_manager_get_default ();
-               languages = gtk_source_language_manager_get_language_ids (lm);
-
-               while ((languages != NULL) && (*languages != NULL))
-               {
-                       gchar **mime_types;
-                       gint i;
-                       GtkSourceLanguage *lang;
-
-                       lang = gtk_source_language_manager_get_language (lm, *languages);
-                       g_return_val_if_fail (GTK_SOURCE_IS_LANGUAGE (lang), FALSE);
-                       ++languages;
-
-                       mime_types = gtk_source_language_get_mime_types (lang);
-                       if (mime_types == NULL)
-                               continue;
-
-                       for (i = 0; mime_types[i] != NULL; i++)
-                       {
-                               if (!g_content_type_is_a (mime_types[i], "text/plain"))
-                               {
-                                       gedit_debug_message (DEBUG_COMMANDS,
-                                                            "Mime-type %s is not related to text/plain",
-                                                            mime_types[i]);
-
-                                       known_mime_types = g_slist_prepend (known_mime_types,
-                                                                           g_strdup (mime_types[i]));
-                               }
-                       }
-
-                       g_strfreev (mime_types);
-               }
-
-               /* known_mime_types always has "text/plain" as first item" */
-               known_mime_types = g_slist_prepend (known_mime_types, g_strdup ("text/plain"));
-       }
+       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
 
-       /* known mime_types contains "text/plain" and then the list of mime-types unrelated to "text/plain"
-        * that gedit recognizes */
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_val_if_fail (iface->get_newline_type != NULL, GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
 
-       if (filter_info->mime_type == NULL)
-               return FALSE;
+       return iface->get_newline_type (dialog);
+}
 
-       /*
-        * The filter is matching:
-        * - the mime-types beginning with "text/"
-        * - the mime-types inheriting from a known mime-type (note the text/plain is
-        *   the first known mime-type)
-        */
 
-       if (strncmp (filter_info->mime_type, "text/", 5) == 0)
-               return TRUE;
+void
+gedit_file_chooser_dialog_set_current_folder (GeditFileChooserDialog *dialog,
+                                              GFile                  *folder)
+{
+       GeditFileChooserDialogInterface *iface;
 
-       mime_types = known_mime_types;
-       while (mime_types != NULL)
-       {
-               if (g_content_type_is_a (filter_info->mime_type, (const gchar*)mime_types->data))
-                       return TRUE;
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-               mime_types = g_slist_next (mime_types);
-       }
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_current_folder != NULL);
 
-       return FALSE;
+       iface->set_current_folder (dialog, folder);
 }
 
-static void
-gedit_file_chooser_dialog_init (GeditFileChooserDialog *dialog)
+void
+gedit_file_chooser_dialog_set_current_name (GeditFileChooserDialog *dialog,
+                                            const gchar            *name)
 {
-       dialog->priv = gedit_file_chooser_dialog_get_instance_private (dialog);
-
-       dialog->priv->filter_settings = g_settings_new ("org.gnome.gedit.state.file-filter");
-}
+       GeditFileChooserDialogInterface *iface;
 
-static GtkWidget *
-gedit_file_chooser_dialog_new_valist (const gchar             *title,
-                                     GtkWindow               *parent,
-                                     GtkFileChooserAction     action,
-                                     const GtkSourceEncoding *encoding,
-                                     const gchar             *first_button_text,
-                                     va_list                  varargs)
-{
-       GtkWidget *result;
-       const char *button_text = first_button_text;
-       gint response_id;
-       GtkFileFilter *filter;
-       gint active_filter;
-
-       result = g_object_new (GEDIT_TYPE_FILE_CHOOSER_DIALOG,
-                              "title", title,
-                              "local-only", FALSE,
-                              "action", action,
-                              "select-multiple", action == GTK_FILE_CHOOSER_ACTION_OPEN,
-                              NULL);
-
-       create_extra_widget (GEDIT_FILE_CHOOSER_DIALOG (result));
-
-       g_signal_connect (result,
-                         "notify::action",
-                         G_CALLBACK (action_changed),
-                         NULL);
-
-       if (encoding != NULL)
-       {
-               gedit_encodings_combo_box_set_selected_encoding (
-                               GEDIT_ENCODINGS_COMBO_BOX (GEDIT_FILE_CHOOSER_DIALOG 
(result)->priv->option_menu),
-                               encoding);
-       }
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-       active_filter = g_settings_get_int (GEDIT_FILE_CHOOSER_DIALOG (result)->priv->filter_settings,
-                                           GEDIT_SETTINGS_ACTIVE_FILE_FILTER);
-       gedit_debug_message (DEBUG_COMMANDS, "Active filter: %d", active_filter);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_current_name != NULL);
 
-       /* Filters */
-       filter = gtk_file_filter_new ();
+       iface->set_current_name (dialog, name);
+}
 
-       gtk_file_filter_set_name (filter, ALL_FILES);
-       gtk_file_filter_add_pattern (filter, "*");
-       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
+void
+gedit_file_chooser_dialog_set_file (GeditFileChooserDialog *dialog,
+                                    GFile                  *file)
+{
+       GeditFileChooserDialogInterface *iface;
 
-       if (active_filter != 1)
-       {
-               /* Make this filter the default */
-               gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
-       }
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+       g_return_if_fail (file == NULL || G_IS_FILE (file));
 
-       filter = gtk_file_filter_new ();
-       gtk_file_filter_set_name (filter, ALL_TEXT_FILES);
-       gtk_file_filter_add_custom (filter,
-                                   GTK_FILE_FILTER_MIME_TYPE,
-                                   all_text_files_filter,
-                                   NULL,
-                                   NULL);
-       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_file != NULL);
 
-       if (active_filter == 1)
-       {
-               /* Make this filter the default */
-               gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
-       }
+       iface->set_file (dialog, file);
+}
 
-       g_signal_connect (result,
-                         "notify::filter",
-                         G_CALLBACK (filter_changed),
-                         NULL);
+GSList *
+gedit_file_chooser_dialog_get_files (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogInterface *iface;
 
-       if (parent != NULL)
-       {
-               gtk_window_set_transient_for (GTK_WINDOW (result), parent);
-               gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE);
-       }
+       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
-       while (button_text)
-       {
-               response_id = va_arg (varargs, gint);
-
-               gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
-               if ((response_id == GTK_RESPONSE_OK) ||
-                   (response_id == GTK_RESPONSE_ACCEPT) ||
-                   (response_id == GTK_RESPONSE_YES) ||
-                   (response_id == GTK_RESPONSE_APPLY))
-               {
-                       gtk_dialog_set_default_response (GTK_DIALOG (result), response_id);
-               }
-
-               button_text = va_arg (varargs, const gchar *);
-       }
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_val_if_fail (iface->get_files != NULL, NULL);
 
-       return result;
+       return iface->get_files (dialog);
 }
 
-/**
- * gedit_file_chooser_dialog_new:
- * @title: (allow-none): Title of the dialog, or %NULL
- * @parent: (allow-none): Transient parent of the dialog, or %NULL
- * @action: Open or save mode for the dialog
- * @encoding: the encoding
- * @first_button_text: (allow-none): text to go in the first button, or %NULL
- * @...: (allow-none): response ID for the first button, then
- * additional (button, id) pairs, ending with %NULL
- *
- * Creates a new #GeditFileChooserDialog.  This function is analogous to
- * gtk_dialog_new_with_buttons().
- *
- * Return value: a new #GeditFileChooserDialog
- */
-GtkWidget *
-gedit_file_chooser_dialog_new (const gchar             *title,
-                              GtkWindow               *parent,
-                              GtkFileChooserAction     action,
-                              const GtkSourceEncoding *encoding,
-                              const gchar             *first_button_text,
-                              ...)
+GFile *
+gedit_file_chooser_dialog_get_file (GeditFileChooserDialog *dialog)
 {
-       GtkWidget *result;
-       va_list varargs;
+       GeditFileChooserDialogInterface *iface;
+
+       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
-       va_start (varargs, first_button_text);
-       result = gedit_file_chooser_dialog_new_valist (title, parent, action,
-                                                      encoding, first_button_text,
-                                                      varargs);
-       va_end (varargs);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_val_if_fail (iface->get_file != NULL, NULL);
 
-       return result;
+       return iface->get_file (dialog);
 }
 
 void
-gedit_file_chooser_dialog_set_encoding (GeditFileChooserDialog  *dialog,
-                                       const GtkSourceEncoding *encoding)
+gedit_file_chooser_dialog_set_do_overwrite_confirmation (GeditFileChooserDialog *dialog,
+                                                         gboolean                overwrite_confirmation)
 {
+       GeditFileChooserDialogInterface *iface;
+
        g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
-       g_return_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
 
-       gedit_encodings_combo_box_set_selected_encoding (
-                               GEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu),
-                               encoding);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_do_overwrite_confirmation != NULL);
+
+       iface->set_do_overwrite_confirmation (dialog, overwrite_confirmation);
 }
 
-const GtkSourceEncoding *
-gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog)
+void
+gedit_file_chooser_dialog_show (GeditFileChooserDialog *dialog)
 {
-       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
-       g_return_val_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu), NULL);
-       g_return_val_if_fail ((gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_OPEN ||
-                              gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE), NULL);
+       GeditFileChooserDialogInterface *iface;
 
-       return gedit_encodings_combo_box_get_selected_encoding (
-                               GEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
-}
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-static void
-set_enum_combo (GtkComboBox *combo,
-                gint         value)
-{
-       GtkTreeIter iter;
-       GtkTreeModel *model;
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->show != NULL);
 
-       model = gtk_combo_box_get_model (combo);
+       iface->show (dialog);
+}
 
-       if (!gtk_tree_model_get_iter_first (model, &iter))
-       {
-               return;
-       }
+void
+gedit_file_chooser_dialog_destroy (GeditFileChooserDialog *dialog)
+{
+       GeditFileChooserDialogInterface *iface;
 
-       do
-       {
-               gint nt;
+       g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
 
-               gtk_tree_model_get (model, &iter, 1, &nt, -1);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->destroy != NULL);
 
-               if (value == nt)
-               {
-                       gtk_combo_box_set_active_iter (combo, &iter);
-                       break;
-               }
-       } while (gtk_tree_model_iter_next (model, &iter));
+       iface->destroy (dialog);
 }
 
 void
-gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog *dialog,
-                                           GtkSourceNewlineType    newline_type)
+gedit_file_chooser_dialog_set_modal (GeditFileChooserDialog *dialog,
+                                     gboolean                is_modal)
 {
+       GeditFileChooserDialogInterface *iface;
+
        g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
-       g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE);
 
-       set_enum_combo (GTK_COMBO_BOX (dialog->priv->newline_combo),
-                       newline_type);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
+       g_return_if_fail (iface->set_modal != NULL);
+
+       iface->set_modal (dialog, is_modal);
 }
 
-GtkSourceNewlineType
-gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog)
+GtkWindow *
+gedit_file_chooser_dialog_get_window (GeditFileChooserDialog *dialog)
 {
-       GtkTreeIter iter;
-       GtkSourceNewlineType newline_type;
+       GeditFileChooserDialogInterface *iface;
 
-       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
-       g_return_val_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == 
GTK_FILE_CHOOSER_ACTION_SAVE,
-                             GTK_SOURCE_NEWLINE_TYPE_DEFAULT);
+       g_return_val_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
-       gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
-                                      &iter);
+       iface = GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE (dialog);
 
-       gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->newline_store),
-                           &iter,
-                           1,
-                           &newline_type,
-                           -1);
+       if (iface->get_window)
+       {
+               return iface->get_window (dialog);
+       }
 
-       return newline_type;
+       return NULL;
 }
 
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-chooser-dialog.h b/gedit/gedit-file-chooser-dialog.h
index a91b818..5923931 100644
--- a/gedit/gedit-file-chooser-dialog.h
+++ b/gedit/gedit-file-chooser-dialog.h
@@ -2,7 +2,7 @@
  * gedit-file-chooser-dialog.h
  * This file is part of gedit
  *
- * Copyright (C) 2005 - Paolo Maggi
+ * Copyright (C) 2014 - Jesse van den Kieboom
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,50 +21,94 @@
 #ifndef __GEDIT_FILE_CHOOSER_DIALOG_H__
 #define __GEDIT_FILE_CHOOSER_DIALOG_H__
 
+#include <gtk/gtk.h>
 #include <gtksourceview/gtksource.h>
 
-#include <gedit/gedit-enum-types.h>
-#include <gedit/gedit-document.h>
-
 G_BEGIN_DECLS
 
-#define GEDIT_TYPE_FILE_CHOOSER_DIALOG             (gedit_file_chooser_dialog_get_type ())
-#define GEDIT_FILE_CHOOSER_DIALOG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialog))
-#define GEDIT_FILE_CHOOSER_DIALOG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass))
-#define GEDIT_IS_FILE_CHOOSER_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG))
-#define GEDIT_IS_FILE_CHOOSER_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG))
-#define GEDIT_FILE_CHOOSER_DIALOG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogClass))
+/*
+ * Type checking and casting macros
+ */
+#define GEDIT_TYPE_FILE_CHOOSER_DIALOG                 (gedit_file_chooser_dialog_get_type ())
+#define GEDIT_FILE_CHOOSER_DIALOG(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialog))
+#define GEDIT_FILE_CHOOSER_DIALOG_IFACE(obj)           (G_TYPE_CHECK_CLASS_CAST ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogInterface))
+#define GEDIT_IS_FILE_CHOOSER_DIALOG(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG))
+#define GEDIT_FILE_CHOOSER_DIALOG_GET_IFACE(obj)       (G_TYPE_INSTANCE_GET_INTERFACE ((obj), 
GEDIT_TYPE_FILE_CHOOSER_DIALOG, GeditFileChooserDialogInterface))
 
-typedef struct _GeditFileChooserDialog         GeditFileChooserDialog;
-typedef struct _GeditFileChooserDialogClass    GeditFileChooserDialogClass;
-typedef struct _GeditFileChooserDialogPrivate  GeditFileChooserDialogPrivate;
+typedef struct _GeditFileChooserDialog           GeditFileChooserDialog; /* dummy typedef */
+typedef struct _GeditFileChooserDialogInterface  GeditFileChooserDialogInterface;
 
-struct _GeditFileChooserDialogClass
+struct _GeditFileChooserDialogInterface
 {
-       GtkFileChooserDialogClass parent_class;
-};
+       GTypeInterface g_iface;
 
-struct _GeditFileChooserDialog
-{
-       GtkFileChooserDialog parent_instance;
+       /* Virtual public methods */
+       void    (*set_encoding)         (GeditFileChooserDialog  *dialog,
+                                        const GtkSourceEncoding *encoding);
+
+       const GtkSourceEncoding *
+               (*get_encoding)         (GeditFileChooserDialog *dialog);
+
+       void    (*set_newline_type)     (GeditFileChooserDialog  *dialog,
+                                        GtkSourceNewlineType     newline_type);
+
+       GtkSourceNewlineType
+               (*get_newline_type)     (GeditFileChooserDialog *dialog);
+
+       void    (*set_current_folder)   (GeditFileChooserDialog *dialog,
+                                        GFile                  *folder);
+
+       void    (*set_current_name)     (GeditFileChooserDialog *dialog,
+                                        const gchar            *name);
+
+       void    (*set_file)             (GeditFileChooserDialog *dialog,
+                                        GFile                  *file);
+
+       GFile * (*get_file)             (GeditFileChooserDialog *dialog);
+
+       GSList *(*get_files)            (GeditFileChooserDialog *dialog);
+
+       void    (*set_do_overwrite_confirmation)
+                                       (GeditFileChooserDialog *dialog,
+                                        gboolean                overwrite_confirmation);
+
+       void    (*show)                 (GeditFileChooserDialog *dialog);
+
+       void    (*destroy)              (GeditFileChooserDialog *dialog);
+
+       void    (*set_modal)            (GeditFileChooserDialog *dialog,
+                                        gboolean                is_modal);
 
-       GeditFileChooserDialogPrivate *priv;
+       GtkWindow *
+               (*get_window)           (GeditFileChooserDialog *dialog);
 };
 
-GType           gedit_file_chooser_dialog_get_type             (void) G_GNUC_CONST;
+typedef enum
+{
+       GEDIT_FILE_CHOOSER_SAVE               = 1 << 0,
+       GEDIT_FILE_CHOOSER_OPEN               = 1 << 1,
+       GEDIT_FILE_CHOOSER_ENABLE_ENCODING    = 1 << 2,
+       GEDIT_FILE_CHOOSER_ENABLE_LINE_ENDING = 1 << 3
+} GeditFileChooserFlags;
 
-GtkWidget      *gedit_file_chooser_dialog_new                  (const gchar              *title,
+/*
+ * Public methods
+ */
+GType          gedit_file_chooser_dialog_get_type              (void)  G_GNUC_CONST;
+
+GeditFileChooserDialog *
+               gedit_file_chooser_dialog_create                (const gchar              *title,
                                                                 GtkWindow                *parent,
-                                                                GtkFileChooserAction      action,
-                                                                const GtkSourceEncoding  *encoding,
-                                                                const gchar              *first_button_text,
-                                                                ...);
+                                                                GeditFileChooserFlags     flags,
+                                                                const GtkSourceEncoding  *encoding);
+
+void            gedit_file_chooser_dialog_destroy              (GeditFileChooserDialog   *dialog);
 
 void            gedit_file_chooser_dialog_set_encoding         (GeditFileChooserDialog   *dialog,
                                                                 const GtkSourceEncoding  *encoding);
 
-const GtkSourceEncoding
-               *gedit_file_chooser_dialog_get_encoding         (GeditFileChooserDialog   *dialog);
+const GtkSourceEncoding *
+                gedit_file_chooser_dialog_get_encoding         (GeditFileChooserDialog   *dialog);
 
 void            gedit_file_chooser_dialog_set_newline_type     (GeditFileChooserDialog   *dialog,
                                                                 GtkSourceNewlineType      newline_type);
@@ -72,6 +116,32 @@ void                 gedit_file_chooser_dialog_set_newline_type     
(GeditFileChooserDialog   *dia
 GtkSourceNewlineType
                 gedit_file_chooser_dialog_get_newline_type     (GeditFileChooserDialog   *dialog);
 
+void            gedit_file_chooser_dialog_set_current_folder   (GeditFileChooserDialog   *dialog,
+                                                                GFile                    *folder);
+
+void            gedit_file_chooser_dialog_set_current_name     (GeditFileChooserDialog   *dialog,
+                                                                const gchar              *name);
+
+void            gedit_file_chooser_dialog_set_file             (GeditFileChooserDialog   *dialog,
+                                                                GFile                    *file);
+
+GFile          *gedit_file_chooser_dialog_get_file             (GeditFileChooserDialog   *dialog);
+
+GSList         *gedit_file_chooser_dialog_get_files            (GeditFileChooserDialog   *dialog);
+
+
+void            gedit_file_chooser_dialog_set_do_overwrite_confirmation (
+                                                                GeditFileChooserDialog   *dialog,
+                                                                gboolean                  
overwrite_confirmation);
+
+void            gedit_file_chooser_dialog_show                 (GeditFileChooserDialog   *dialog);
+
+void            gedit_file_chooser_dialog_set_modal            (GeditFileChooserDialog   *dialog,
+                                                                gboolean                  is_modal);
+
+GtkWindow      *gedit_file_chooser_dialog_get_window           (GeditFileChooserDialog   *dialog);
+
+
 G_END_DECLS
 
 #endif /* __GEDIT_FILE_CHOOSER_DIALOG_H__ */
diff --git a/gedit/gedit-marshal.list b/gedit/gedit-marshal.list
index 9762ba2..3f72ae0 100644
--- a/gedit/gedit-marshal.list
+++ b/gedit/gedit-marshal.list
@@ -18,3 +18,4 @@ VOID:INT,INT
 VOID:OBJECT,OBJECT,INT
 OBJECT:OBJECT,OBJECT,INT,INT
 VOID:STRING,STRING
+ENUM:VOID
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ec912cc..e5a940e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,8 +15,10 @@ gedit/gedit-debug.c
 gedit/gedit-document.c
 gedit/gedit-documents-panel.c
 gedit/gedit-encodings-combo-box.c
+gedit/gedit-encoding-items.c
 gedit/gedit-encodings-dialog.c
-gedit/gedit-file-chooser-dialog.c
+gedit/gedit-file-chooser-dialog-gtk.c
+gedit/gedit-file-chooser-dialog-osx.c
 gedit/gedit-highlight-mode-dialog.c
 gedit/gedit-highlight-mode-selector.c
 gedit/gedit-io-error-info-bar.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]