mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-28 18:32:50 +00:00
Merge pull request #1000 from sirblackheart/native-gtk3-file-dialog
Experimental native gtk3 file dialog
This commit is contained in:
commit
f51de0bd73
@ -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 --
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
194
src/she/gtk/native_dialogs.cpp
Normal file
194
src/she/gtk/native_dialogs.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
// 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 <gtkmm/image.h>
|
||||
#include <gdkmm/pixbuf.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
|
||||
}
|
||||
this->set_use_preview_label(false);
|
||||
this->set_preview_widget(m_preview);
|
||||
this->signal_update_preview().connect(sigc::mem_fun(this, &FileDialogGTK3::updatePreview));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void updatePreview() {
|
||||
this->set_preview_widget_active(false);
|
||||
std::string fileName = this->get_filename();
|
||||
try {
|
||||
if (!Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) {
|
||||
auto previewPixbuf = Gdk::Pixbuf::create_from_file(fileName, 256, 256, true);
|
||||
m_preview.set(previewPixbuf);
|
||||
this->set_preview_widget_active();
|
||||
}
|
||||
} catch(Glib::Error e) {}
|
||||
}
|
||||
|
||||
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;
|
||||
Gtk::Image m_preview;
|
||||
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")
|
32
src/she/gtk/native_dialogs.h
Normal file
32
src/she/gtk/native_dialogs.h
Normal 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")
|
Loading…
x
Reference in New Issue
Block a user