Experimental native gtk3 file dialog

This pull request basicly adds the suport for gtk3 dialogs to she.
it is disabled by default and can be enabled with
cmake ... -DWITH_GTK_FILE_DIALOG_SUPPORT=ON ..
and needs the Experimental option "Use native file dialog"
enabled in aseprite enabled.
It is currently only available on *nix and has a external
dependencie on gtkmm >= 3.16 and glibmm >= 2.45

To have at least backwardcompatibility with ubuntu 15.10
the cmake option -D_WITH_DEPRECATED_GLIB_SUPPORT was added
to make use of a deprecated glibmm method.

Further testing ist need to see how far this backward
compatibility works, as of now ubuntu 12.04 does not seem to work.
But as ubuntu 12.04 will reach its end of support this summer and
ubuntu 15.04 having passed its end of life in february the question
is how far back this support is aimed for. Please enter the commit message for your changes. Lines starting
This commit is contained in:
Gabriel Rauter 2016-03-04 21:22:44 +01:00
parent 36eb38a5e7
commit 745fd180d4
5 changed files with 238 additions and 1 deletions

View File

@ -35,6 +35,8 @@ project(aseprite C CXX)
# CMakeCache.txt)
option(WITH_WEBP_SUPPORT "Enable support to load/save .webp files" off)
option(WITH_GTK_FILE_DIALOG_SUPPORT "Enable support for the experimental native GTK File Dialog" off)
option(WITH_DEPRECATED_GLIB_SUPPORT "Enable support for older glib versions" off)
option(USE_STATIC_LIBC "Use static version of C and C++ runtimes" off)
option(USE_SHARED_CURL "Use your installed copy of curl" off)
@ -360,6 +362,13 @@ if(UNIX AND NOT APPLE AND NOT BEOS)
if(XDGA_FOUND)
list(APPEND PLATFORM_LIBS Xxf86dga ${X11_LIBRARIES})
endif()
if(WITH_GTK_FILE_DIALOG_SUPPORT)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
endif()
endif()
# -- Windows --

View File

@ -97,7 +97,7 @@ if(USE_SKIA_BACKEND)
find_library(SKIA_OPENGL_LIBRARY opengl32)
find_library(SKIA_LIBEGL_LIBRARY libEGL.dll PATH "${SKIA_BUILD_OUT_DIR}")
if(SKIA_LIBEGL_LIBRARY)
add_definitions(-DSK_ANGLE=1)
add_definitions(-DSK_ANGLE=1)
endif()
endif()
else()
@ -193,6 +193,15 @@ if(APPLE)
osx/native_dialogs.mm)
endif()
if(WITH_GTK_FILE_DIALOG_SUPPORT AND UNIX AND NOT APPLE AND NOT BEOS)
if(WITH_DEPRECATED_GLIB_SUPPORT)
add_definitions(-DASEPRITE_DEPRECATED_GLIB_SUPPORT)
endif()
add_definitions(-DASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT)
list(APPEND SHE_SOURCES
gtk/native_dialogs.cpp)
endif()
add_library(she ${SHE_SOURCES})
target_link_libraries(she
@ -210,3 +219,8 @@ if(USE_SKIA_BACKEND)
target_link_libraries(she
${SKIA_LIBRARIES})
endif()
if(WITH_GTK_FILE_DIALOG_SUPPORT)
target_link_libraries(she
${GTKMM_LIBRARIES})
endif()

View File

@ -14,6 +14,9 @@
#elif defined(__APPLE__)
#include "she/osx/clipboard.h"
#include "she/osx/native_dialogs.h"
#elif defined(ASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT) && defined(__linux__)
#include "she/clipboard_simple.h"
#include "she/gtk/native_dialogs.h"
#else
#include "she/clipboard_simple.h"
#include "she/native_dialogs.h"
@ -56,6 +59,9 @@ public:
#elif defined(__APPLE__)
if (!m_nativeDialogs)
m_nativeDialogs = new NativeDialogsOSX();
#elif defined(ASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT) && defined(__linux__)
if (!m_nativeDialogs)
m_nativeDialogs = new NativeDialogsGTK3();
#endif
return m_nativeDialogs;
}

View File

@ -0,0 +1,176 @@
// GTK Component of SHE library
// Copyright (C) 2016 Gabriel Rauter
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
//disable EMPTY_STRING macro already set in allegro, enabling it at the end of file
#pragma push_macro("EMPTY_STRING")
#undef EMPTY_STRING
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "she/gtk/native_dialogs.h"
#include "base/string.h"
#include "she/display.h"
#include "she/error.h"
#include <gtkmm/application.h>
#include <gtkmm/filechooserdialog.h>
#include <gtkmm/button.h>
#include <gtkmm/filefilter.h>
#include <glibmm/refptr.h>
#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
#include <string>
#include <map>
namespace she {
class FileDialogGTK3 : public FileDialog, public Gtk::FileChooserDialog {
public:
FileDialogGTK3(Glib::RefPtr<Gtk::Application> app) :
Gtk::FileChooserDialog(""), m_app(app), m_cancel(true) {
this->add_button("_Cancel", Gtk::RESPONSE_CANCEL);
m_ok_button = this->add_button("_Open", Gtk::RESPONSE_OK);
this->set_default_response(Gtk::RESPONSE_OK);
m_filter_all = Gtk::FileFilter::create();
m_filter_all->set_name("All formats");
this->set_do_overwrite_confirmation();
if (FileDialogGTK3::lastUsedDir().empty()) {
#ifdef ASEPRITE_DEPRECATED_GLIB_SUPPORT
FileDialogGTK3::lastUsedDir() = Glib::get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
#else
FileDialogGTK3::lastUsedDir() = Glib::get_user_special_dir(Glib::USER_DIRECTORY_DOCUMENTS);
#endif
}
}
void on_show() override {
//setting the filename only works properly when the dialog is shown
if (!m_file_name.empty()) {
if (this->get_action() == Gtk::FILE_CHOOSER_ACTION_OPEN) {
this->set_current_folder(m_file_name);
} else {
if (Glib::file_test(m_file_name, Glib::FILE_TEST_EXISTS)) {
this->set_filename(m_file_name);
} else {
this->set_current_folder(FileDialogGTK3::lastUsedDir());
this->set_current_name(m_file_name);
}
}
} else {
this->set_current_folder(FileDialogGTK3::lastUsedDir());
}
//TODO set position centered to parent window, need she::screen to provide info
this->set_position(Gtk::WIN_POS_CENTER);
Gtk::FileChooserDialog::on_show();
this->raise();
}
void on_response(int response_id) override {
switch(response_id) {
case(Gtk::RESPONSE_OK): {
m_cancel = false;
m_file_name = this->get_filename();
FileDialogGTK3::lastUsedDir() = this->get_current_folder();
break;
}
}
this->hide();
}
void dispose() override {
for (auto& window : m_app->get_windows()) {
window->close();
}
m_app->quit();
delete this;
}
void toOpenFile() override {
this->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN);
m_ok_button->set_label("_Open");
}
void toSaveFile() override {
this->set_action(Gtk::FILE_CHOOSER_ACTION_SAVE);
m_ok_button->set_label("_Save");
}
void setTitle(const std::string& title) override {
this->set_title(title);
}
void setDefaultExtension(const std::string& extension) override {
m_default_extension = extension;
}
void addFilter(const std::string& extension, const std::string& description) override {
auto filter = Gtk::FileFilter::create();
filter->set_name(description);
filter->add_pattern("*." + extension);
m_filter_all->add_pattern("*." + extension);
m_filters[extension] = filter;
}
std::string fileName() override {
return m_file_name;
}
void setFileName(const std::string& filename) override {
m_file_name = filename;
}
bool show(Display* parent) override {
//keep pointer on parent display to get information later
m_display = parent;
//add filters in order they will appear
this->add_filter(m_filter_all);
for (const auto& filter : m_filters) {
this->add_filter(filter.second) ;
if (filter.first.compare(m_default_extension) == 0) {
this->set_filter(filter.second);
}
}
auto filter_any = Gtk::FileFilter::create();
filter_any->set_name("Any files");
filter_any->add_pattern("*");
this->add_filter(filter_any);
//Run dialog in context of a gtk application so it can be destroys properly
m_app->run(*this);
return !m_cancel;
}
private:
std::string m_file_name;
std::string m_default_extension;
Glib::RefPtr<Gtk::FileFilter> m_filter_all;
std::map<std::string, Glib::RefPtr<Gtk::FileFilter>> m_filters;
Gtk::Button* m_ok_button;
Glib::RefPtr<Gtk::Application> m_app;
Display* m_display;
bool m_cancel;
static std::string& lastUsedDir() { static std::string lastUsedDir; return lastUsedDir; }
};
NativeDialogsGTK3::NativeDialogsGTK3()
{
}
FileDialog* NativeDialogsGTK3::createFileDialog()
{
m_app = Gtk::Application::create();
FileDialog* dialog = new FileDialogGTK3(m_app);
return dialog;
}
} // namespace she
#pragma pop_macro("EMPTY_STRING")

View File

@ -0,0 +1,32 @@
// GTK Component of SHE library
// Copyright (C) 2016 Gabriel Rauter
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
//disable EMPTY_STRING macro already set in allegro, enabling it at the end of file
#pragma push_macro("EMPTY_STRING")
#undef EMPTY_STRING
#ifndef SHE_GTK_NATIVE_DIALOGS_H_INCLUDED
#define SHE_GTK_NATIVE_DIALOGS_H_INCLUDED
#pragma once
#include "she/native_dialogs.h"
#include <gtkmm/application.h>
#include <glibmm/refptr.h>
namespace she {
class NativeDialogsGTK3 : public NativeDialogs {
public:
NativeDialogsGTK3();
FileDialog* createFileDialog() override;
private:
Glib::RefPtr<Gtk::Application> m_app;
};
} // namespace she
#endif
#pragma pop_macro("EMPTY_STRING")